2012-01-20 5 views
6

Мне нужно сделать этот эффект с помощью php. Я знаю, что IMG_FILTER_PIXELATE в фильтрах изображений PHP. Но мне нужно, чтобы он был более гладким и рельефным? как на этой картинке:PHP pixelate?

image

Этот эффект будет сделать любое изображение загружено пользователем стать некачественно и край картины становится красным (я знаю IMG_FILTER_EDGEDETECT, но я не знаю, как использовать его, чтобы изменить край цвет).

Я понятия не имею, как это сделать.

+3

Образ вы связались, похоже, что это произошло из фильтра Photoshop. Вероятно, вы не сможете воспроизвести этот точный вид без какого-либо довольно хардкорного программирования манипуляции изображениями. Можете ли вы создать набор образцовых изображений, один «до» и один «после», который демонстрирует точный эффект, который вы ищете? – Charles

+0

Для эффекта pixelate я думаю, что это похоже на фильтр пэчворка в Photoshop. Как я могу это сделать? – just2cya

+0

http://www.flickr.com/photos/[email protected]/6729984045/ Я создаю это, используя текстуру фильтра пятнистого слоя Photoshop, а для нижнего изображения я использую замену цвета. – just2cya

ответ

14

Как последний ответ был теоретическим и, казалось, не достаточно, я создал практический пример:
Примечания: Это далеко от «идеальной» и идеальной функции эффекта пикселя, но это делает работу. Не стесняйтесь редактировать его в соответствии с вашими собственными потребностями.

<?php 
/* Function to make pixelated images 
* Supported input: .png .jpg .jpeg .gif 
* 
* 
* Created on 24.01.2011 by Henrik Peinar 
*/ 


/* 
* image - the location of the image to pixelate 
* pixelate_x - the size of "pixelate" effect on X axis (default 10) 
* pixelate_y - the size of "pixelate" effect on Y axis (default 10) 
* output - the name of the output file (extension will be added) 
*/ 
function pixelate($image, $output, $pixelate_x = 20, $pixelate_y = 20) 
{ 
    // check if the input file exists 
    if(!file_exists($image)) 
     echo 'File "'. $image .'" not found'; 

    // get the input file extension and create a GD resource from it 
    $ext = pathinfo($image, PATHINFO_EXTENSION); 
    if($ext == "jpg" || $ext == "jpeg") 
     $img = imagecreatefromjpeg($image); 
    elseif($ext == "png") 
     $img = imagecreatefrompng($image); 
    elseif($ext == "gif") 
     $img = imagecreatefromgif($image); 
    else 
     echo 'Unsupported file extension'; 

    // now we have the image loaded up and ready for the effect to be applied 
    // get the image size 
    $size = getimagesize($image); 
    $height = $size[1]; 
    $width = $size[0]; 

    // start from the top-left pixel and keep looping until we have the desired effect 
    for($y = 0;$y < $height;$y += $pixelate_y+1) 
    { 

     for($x = 0;$x < $width;$x += $pixelate_x+1) 
     { 
      // get the color for current pixel 
      $rgb = imagecolorsforindex($img, imagecolorat($img, $x, $y)); 

      // get the closest color from palette 
      $color = imagecolorclosest($img, $rgb['red'], $rgb['green'], $rgb['blue']); 
      imagefilledrectangle($img, $x, $y, $x+$pixelate_x, $y+$pixelate_y, $color); 

     }  
    } 

    // save the image 
    $output_name = $output .'_'. time() .'.jpg'; 

    imagejpeg($img, $output_name); 
    imagedestroy($img); 
} 


pixelate("test.jpg", "testing"); 


?> 

Это пример функции для создания пиксельного эффекта на изображения. Вот пример результатов использования этой функции:
Оригинал:

Pixelated 5px:

пиксельного 10px:

пиксельного 20px:

+0

О, спасибо. Но мне нужно, чтобы это было как в \t flickr.com/photos/[email protected]/6729984045, я создал это с использованием текстуры фильтра Photoshop. На этом рисунке, похоже, каждый квадрат рельефный. Является ли это возможным? – just2cya

+0

В основном да ... вам нужно изменить темноту внешних пикселей квадрата ... это больше работает, и у меня, к сожалению, нет времени писать сценарий сейчас. –

+0

Наконец, я использую ваш скрипт и добавляю этот скрипт из http://stackoverflow.com/questions/9106893/php-emboss-with-color/9107056#9107056 Спасибо! – just2cya

1

Здесь идет теоретически:
У вас есть изображение:

RGBRGBRGBRGB
GBRGBRGBRGBR
GBRGBRGBRRGB
BGRGBGRGGRBG

Возьмите цвет первого пикселя и установить один и тот же цвет для квадрата следующего пикселей (как вниз, так и вправо). Затем возьмите цвет 5-го пикселя (так как 4 в начале имеют тот же цвет). Если вы закончили первую строку, перейдите на 3 строки вниз и начните заново.

Таким образом, вы получите:
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB

В PHP вы можете использовать следующие функции, чтобы сделать это:
http://php.net/manual/en/function.imagecolorat.php, чтобы выбрать цвет пиксела
http://php.net/manual/en/function.imagecolorset.php к установить цвет пикселя
http://php.net/manual/en/function.imagesx.php получить ширину изображения
http://php.net/manual/en/function.imagesy.php прибудет высоту изображения

использование для петель через пиксели образа

+0

Привет, спасибо за ваш ответ. Я могу заменить цвет, используя те функции, которые вы упомянули. Теперь я должен найти способ сделать эффект пикселя. Любая идея? – just2cya

+0

Весь пост был о том, как сделать пиксельный эффект ... как вы могли его пропустить? :) Я собираюсь сделать образец сценария с комментариями. Ждите ответа или комментария. –

2

Спасибо за ваш ответ , Я использовал вашу функцию и добавил еще один цикл, чтобы изменить цвет внешнего пикселя квадратов, используя функцию, называемую imagelinethick, в http://www.php.net/manual/en/function.imageline.php.Так он стал:

<?php 
$image = imagecreatefromjpeg('Penguins.jpg'); 
$imagex = imagesx($image); 
$imagey = imagesy($image); 

$pixelate_y=10; 
$pixelate_x=10; 
$height=$imagey; 
$width=$imagex; 
for($y = 0;$y < $height;$y += $pixelate_y+1) 
{ 
    for($x = 0;$x < $width;$x += $pixelate_x+1) 
    { 
    // get the color for current pixel 
    $rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y)); 

    // get the closest color from palette 
    $color = imagecolorclosest($image, $rgb['red'], $rgb['green'], $rgb['blue']); 

    imagefilledrectangle($image, $x, $y, $x+$pixelate_x, $y+$pixelate_y, $color); 
    } 
} 


for($y = 0;$y < $height;$y += $pixelate_y+1) 
{ 
for($x = 0;$x < $width;$x += $pixelate_x+1) 
{ 
    //make a border line for each square 
    $rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y)); 
    $color = imagecolorclosest($image, 123, 123, 123); 
    imagelinethick($image, $x, $y, $x, $y+$pixelate_y, $color, 1); 
    imagelinethick($image, $x, $y, $x+$pixelate_x, $y, $color, 2); 
}  
} 

function imagelinethick($image, $x1, $y1, $x2, $y2, $color, $thick = 1) 
{ 
    /* this way it works well only for orthogonal lines 
    imagesetthickness($image, $thick); 
    return imageline($image, $x1, $y1, $x2, $y2, $color); 
    */ 
    if ($thick == 1) { 
     return imageline($image, $x1, $y1, $x2, $y2, $color); 
    } 
$t = $thick/2 - 0.5; 
if ($x1 == $x2 || $y1 == $y2) { 
    return imagefilledrectangle($image, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color); 
} 
$k = ($y2 - $y1)/($x2 - $x1); //y = kx + q 
$a = $t/sqrt(1 + pow($k, 2)); 
$points = array(
    round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a), 
    round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a), 
    round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a), 
    round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a), 
); 
imagefilledpolygon($image, $points, 4, $color); 
return imagepolygon($image, $points, 4, $color); 
} 

header("Content-Type: image/JPEG"); 
imageJPEG($image, "", 75); 

?> 

Результат таков: http://www.flickr.com/photos/[email protected]/6759029339/

Но я думаю, что это все еще нуждаются в улучшении, чтобы сделать ее более гладкой.

+0

Любой может помочь? – just2cya

0

Это моя попытка решить эту проблему.

Вы можете изменить размер блока пикселя, и вы можете применить размытие, смягчающее эффект на высококонтрастных изображениях. Может быть медленным на больших изображениях с небольшими размерами пиксельных блоков.

В сценариях хранятся цвета соответствующих пикселей в массиве. Затем он рельеф изображения, изменяет контрастность по мере необходимости, пикселирует изображение с помощью функции imagefilter(), а затем (если установлен усиление плитки) снова рельефно (это увеличивает 3D-эффект на финальные плитки). Если требуется размытие, скрипт применяет размытие по Гауссу. Затем скрипт рисует заполненные квадраты с использованием цветового массива, чтобы создать красочный пикселированный эффект в границах тисненых плит.

function pixelatemboss($image,$blockwidth=10,$blur=5,$tileenhance="true",$contrast=0,$negate="true") 
{ 
    if($blockwidth>1) 
    { 
     imagefilter($image,IMG_FILTER_CONTRAST,$contrast); 

     for($x=1;$x<imagesx($image);$x=$x+$blockwidth) 
     { 
      for($y=1;$y<imagesy($image);$y=$y+$blockwidth) 
      { 
       $color[$x][$y]=imagecolorat($image,$x,$y); 
      } 
     } 

     imagefilter($image,IMG_FILTER_EMBOSS); 
     imagefilter($image,IMG_FILTER_CONTRAST,$contrast); 
     imagefilter($image,IMG_FILTER_PIXELATE,$blockwidth,false); 
     if($tileenhance=="true") 
     { 
      imagefilter($image,IMG_FILTER_EMBOSS); 
     } 
     for($b=0;$b<$blur;$b++) 
     { 
      imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR); 
     } 
     for($x=1;$x<imagesx($image);$x=$x+$blockwidth) 
     { 
      for($y=1;$y<imagesy($image);$y=$y+$blockwidth) 
      { 
       $rgb=$color[$x][$y]; 
       $r = ($rgb >> 16) & 0xFF; 
       $g = ($rgb >> 8) & 0xFF; 
       $b = $rgb & 0xFF; 
       $col=imagecolorallocate($image,$r,$g,$b); 
       imagefilledrectangle($image,$x,$y,$x+($blockwidth-2),$y+($blockwidth-2),$col); 
      } 
     } 
    } 
    return $image; 
} 
0

Примечание для PHP 5.4 и выше вам не нужно использовать:

imageJPEG($image, NULL, 75); 

Вы больше не можете указать NULL, используя двойные кавычки (как в этом примере):

imageJPEG($image, "", 75);