2012-01-20 16 views
6

Necesito hacer este efecto con php. Sé que hay IMG_FILTER_PIXELATE en el filtro de imágenes de PHP. Pero necesito que sea más suave y en relieve? como en esta imagen:imagen de PHP pixelate?

image

Este efecto hará que cualquier imagen cargada por el usuario a ser pixelada y el borde de la imagen se ponen de color rojo (sé IMG_FILTER_EDGEDETECT pero no sé cómo usarlo para cambiar el borde color).

No tengo ni idea de cómo hacerlo.

+3

La imagen los enlaces parecen como si provinieran de un filtro de Photoshop. Probablemente no puedas replicar ese aspecto exacto sin una programación de manipulación de imágenes bastante hardcore. ¿Puedes crear un conjunto de imágenes de muestra, una "antes" y una "después" que demuestren el efecto exacto que estás buscando? – Charles

+0

Para el efecto pixelado, creo que es como el filtro de mosaico en photoshop. ¿Cómo puedo hacer eso? – just2cya

+0

http://www.flickr.com/photos/[email protected]/6729984045/ Creo esto usando una textura de filtro de mosaico de Photoshop, y para la imagen de abajo, uso el color de reemplazo. – just2cya

Respuesta

14

A medida que la última respuesta fue teórica y parecía no ser suficiente, he creado un ejemplo práctico:
Nota: Este es el momento de la función de efecto pixelado perfecto y "ideal", pero cumple su función. Siéntase libre de editarlo de acuerdo a sus propias necesidades.

<?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"); 


?> 

Esta es la función de ejemplo para crear un efecto pixelado en las imágenes. He aquí un ejemplo resultados del uso de esta función:
original:

pixelado 5PX:

10px Pixelated:

20px Pixelated:

+0

Oh, gracias. Pero necesito que sea como en \t flickr.com/photos/[email protected]/6729984045, creé esto usando una textura de filtro de mosaico de Photoshop. En esta imagen, parece que cada cuadrado está en relieve. ¿Es posible? – just2cya

+0

Básicamente sí ... necesitas cambiar la oscuridad de los píxeles exteriores de un cuadrado ... es más trabajo y lamentablemente no tengo tiempo para escribir el guión ahora. –

+0

Finalmente uso su script y agrego este script desde http://stackoverflow.com/questions/9106893/php-emboss-with-color/9107056#9107056 ¡Gracias! – just2cya

1

Aquí va teóricamente:
tiene una imagen:

RGBRGBRGBRGB
GBRGBRGBRGBR
GBRGBRGBRRGB
BGRGBGRGGRBG

Tome el color del primer píxel y establecer el mismo color de un cuadrado de lado píxeles (tanto hacia abajo como hacia la derecha). Luego tome el color de un quinto píxel (ya que 4 unidades en el inicio ya tienen el mismo color). Si terminaste la primera fila, baja +3 filas y comienza de nuevo.

Así se obtiene:
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB

En PHP se pueden utilizar las siguientes funciones para hacer esto:
http://php.net/manual/en/function.imagecolorat.php para seleccionar el color de un píxel
http://php.net/manual/en/function.imagecolorset.php a establecer el color de un píxel
http://php.net/manual/en/function.imagesx.php obtener ancho de imagen
http://php.net/manual/en/function.imagesy.php get altura de la imagen

uso de bucles a través de los píxeles de una imagen

+0

Hola, gracias por tu respuesta. Puedo hacer el cambio de color usando las funciones que mencionaste. Ahora tengo que encontrar una forma de hacer el efecto de pixelado ... ¿Alguna Idea? – just2cya

+0

Todo el post fue sobre cómo hacer el efecto de pixel ... ¿cómo podrías extrañarlo? :) Voy a hacer una secuencia de comandos de muestra con comentarios. Espere una nueva respuesta/comentario. –

2

Gracias por su respuesta . Usé su función y agregué otro bucle para cambiar el color del píxel externo de los cuadrados usando una función llamada imagelinethick en http://www.php.net/manual/en/function.imageline.php.Así se hizo:

<?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); 

?> 

El resultado es la siguiente: http://www.flickr.com/photos/[email protected]/6759029339/

Pero creo que esto todavía necesita algunas mejoras para que sea más suave.

+0

¿Alguien puede ayudar? – just2cya

0

Este es mi intento del problema.

Puede modificar el tamaño del bloque de píxeles y puede aplicar un desenfoque que suavice el efecto en imágenes de alto contraste. Sin embargo, puede ser lento en imágenes grandes con pequeños tamaños de bloques de pixelado.

Los scripts almacenan los colores de los píxeles relevantes en una matriz. Luego imprime la imagen, altera el contraste según sea necesario, pixela la imagen con la función imagefilter() y luego (si se establece la mejora de mosaico) lo vuelve a hacer (esto aumenta el efecto 3D en las teselas finales). Si se requiere borrosidad, la secuencia de comandos aplica el desenfoque Gaussiano. A continuación, el guión dibuja cuadrados rellenos utilizando la matriz de colores para crear el colorido efecto pixelado dentro de los bordes de los mosaicos en relieve.

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

Nota para PHP 5.4 y hasta es necesario utilizar:

imageJPEG($image, NULL, 75); 

Ya no se puede especificar NULL utilizando una cita doble (como en este ejemplo):

imageJPEG($image, "", 75);