PHP image pixelate?

霸气de小男生 提交于 2019-12-04 09:54:42

问题


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:

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.


回答1:


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:




回答2:


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.




回答3:


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




回答4:


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;
}



回答5:


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


来源:https://stackoverflow.com/questions/8936601/php-image-pixelate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!