7

I need to make this effect with php. I know that there is IMG_FILTER_PIXELATE in PHP image filter. But I need it to be smoother and embossed? like in this image:

image

This effect will make any image uploaded by user become pixelated and the edge of the picture become red (I know IMG_FILTER_EDGEDETECT but I don't know how to use it to change edge color).

I have no idea how to do this.

rcs20
  • 595
  • 9
  • 27
just2cya
  • 125
  • 2
  • 10
  • 3
    The image you linked looks like it came from a Photoshop filter. You probably are not going to be able to replicate that exact look without some pretty hardcore image manipulation programming. Can you create a set of sample images, one "before" and one "after" that demonstrates the exact effect that you're looking for? – Charles Jan 20 '12 at 07:27
  • For the pixelate effect, I think it's like the patchwork filter in photoshop. How can I do that? – just2cya Jan 20 '12 at 07:37
  • http://www.flickr.com/photos/52700219@N06/6729984045/ I create this using Photoshop patchwork filter texture, and for the bottom picture, I use replace color. – just2cya Jan 20 '12 at 09:31

5 Answers5

17

As the last answer was theoretical and seemed to be not enough, I've created a practical example:
Note: This is far from the "ideal" and perfect pixelate effect function, but it does it's job. Feel free to edit it according to your own needs.

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


?>

This is the example function to create pixelated effect on images. Here's an example results of using this function:
Original:

Pixelated 5px:

Pixelated 10px:

Pixelated 20px:

Community
  • 1
  • 1
Henrik Peinar
  • 2,181
  • 18
  • 22
  • Oh, thank you. But I need it to be like in flickr.com/photos/52700219@N06/6729984045, I created this using Photoshop patchwork filter texture. In this picture, it looks like each square is embossed. is it possible? – just2cya Jan 24 '12 at 15:09
  • Basically yea... you need to change the darkness of the outer pixels of a square... it's more work tho and I sadly don't have the time to write the script now. – Henrik Peinar Jan 24 '12 at 17:03
  • I finally use your script and add this script from http://stackoverflow.com/questions/9106893/php-emboss-with-color/9107056#9107056 Thank you! – just2cya Feb 02 '12 at 07:02
  • @HenrikPeinar May i know how to save every pixel of images? – Anand Mishra Aug 27 '18 at 10:02
3

Thank you for your answer. I used your function and added another loop to change color of the outer pixel of the squares using a function called imagelinethick in http://www.php.net/manual/en/function.imageline.php. So it became:

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

?>

The result is like this: http://www.flickr.com/photos/52700219@N06/6759029339/

But I think this still need some improvement to make it smoother.

Jav_Rock
  • 22,059
  • 20
  • 123
  • 164
just2cya
  • 125
  • 2
  • 10
1

Here goes theoretically:
You have a image:

RGBRGBRGBRGB
GBRGBRGBRGBR
GBRGBRGBRRGB
BGRGBGRGGRBG

Take the color of the first pixel and set the same color for a square of next pixels (both down and right). Then take the color of a 5th pixel (as 4 ones in the start have already the same color). If you are done for the first row, go +3 rows down and start again.

So you get:
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB
RRRRGGGBBBB

In PHP you can use the following functions to make this:
http://php.net/manual/en/function.imagecolorat.php to select the color of a pixel
http://php.net/manual/en/function.imagecolorset.php to set the color of a pixel
http://php.net/manual/en/function.imagesx.php get image width
http://php.net/manual/en/function.imagesy.php get image height

use for loops thru the pixels of a image

Henrik Peinar
  • 2,181
  • 18
  • 22
  • Hi, thank you for your answer. I can make the replace color using those functions you mentioned. Now I have to find a way to make the pixellate effect.. Any Idea? – just2cya Jan 24 '12 at 05:10
  • The whole post was about how to make the pixellate effect.... how could you miss it? :) I'm gonna make a sample script with comments. Wait for new answer / comment. – Henrik Peinar Jan 24 '12 at 11:15
0

This is my attempt at the problem.

You can alter the pixelate block size and you can apply a blur which softens the effect on high contrast images. Can be a slow on large images with small pixelate block sizes though.

The scripts stores the colours of relevant pixels in an array. It then embosses the image, alters the contrast as required, pixelates the image using the imagefilter() function and then (if tile enhance is set) embosses it again (this increases the 3D effect on the final tiles). If blur is required the script the applies the Gaussian blur. The script then draws filled squares using the colour array to create the colourful pixelated effect within the embossed tile borders.

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

Note for php 5.4 and up you need to use:

imageJPEG($image, NULL, 75);

You can no longer specify NULL by using a double quote (like this example):

imageJPEG($image, "", 75);