7

Can someone help me with a simple script to replace a specific color with another color in an image using PHP? Here is a example (color changed from green to yellow).

before after

Zack
  • 5,108
  • 4
  • 27
  • 39
Florin Frătică
  • 587
  • 4
  • 7
  • 13
  • 1
    possible duplicate of [Can I swap colors in image using GD library in PHP?](http://stackoverflow.com/questions/456044/can-i-swap-colors-in-image-using-gd-library-in-php) – bfavaretto Aug 29 '12 at 13:23

5 Answers5

21

If you meant using GD library in PHP, you should give a check on imagefilter()

Steps are:

  • Start with a .PNG image, use white for inner, alpha for outer.
  • Use imagefilter($img, IMG_FILTER_COLORIZE, 0, 255, 0)) Where 0,255,0 is your RGB color (bright green in this example)
  • Save the alpha and print out result.

Edit, Working code and clarification.

I meant, using alpha for OUTER of the black lines, and white INSIDE. Here's the sample image: WhiteInAlphaOut

And here's a working code for colorizing white parts:

header('Content-Type: image/png');

/* RGB of your inside color */
$rgb = array(0,0,255);
/* Your file */
$file="../test.png";

/* Negative values, don't edit */
$rgb = array(255-$rgb[0],255-$rgb[1],255-$rgb[2]);

$im = imagecreatefrompng($file);

imagefilter($im, IMG_FILTER_NEGATE); 
imagefilter($im, IMG_FILTER_COLORIZE, $rgb[0], $rgb[1], $rgb[2]); 
imagefilter($im, IMG_FILTER_NEGATE); 

imagealphablending( $im, false );
imagesavealpha( $im, true );
imagepng($im);
imagedestroy($im);

Note: We must negate values since colorize only works for non-white parts. We could have a workaround to this by having white-bordered image with black inside.

Note: This code only works for black-border and white-inner images.

Touki
  • 7,465
  • 3
  • 41
  • 63
  • I tried this but it also changed the background (which was transparent) to a greenish one. Should I make the background white? – Florin Frătică Aug 29 '12 at 13:45
  • it's also good to do one more filtering step before those mentioned using BRIGHTNESS and high negative value to make sure image contains pure black (#000) and pure white (#FFF) colors only. Whatever documentation says, use -10000 value with this filter to avoid half-gray pixels. Than COLORIZE makes sense and color you set will colorize black area properly. This procedure is used by some php libraries for applying b/w bitmasks to make custom regions of image transparent. – Wh1T3h4Ck5 Sep 07 '15 at 13:41
  • Isn't this only for swapping to a polar opposite color? What if it's green to blue instead of green to opposite of green? Or am I understanding this code incorrectly? – Goose Aug 18 '16 at 14:34
  • that negate trick is awesome, thanks as i was trying to tint with colorize , but not affecting the white ! – Hayden Thring Dec 27 '18 at 09:47
4

The slow but sure approach, iterating over every pixel.

function ReplaceColour($img, $r1, $g1, $b1, $r2, $g2, $b2)
{
    if(!imageistruecolor($img))
        imagepalettetotruecolor($img);
    $col1 = (($r1 & 0xFF) << 16) + (($g1 & 0xFF) << 8) + ($b1 & 0xFF);
    $col2 = (($r2 & 0xFF) << 16) + (($g2 & 0xFF) << 8) + ($b2 & 0xFF);

    $width = imagesx($img); 
    $height = imagesy($img);
    for($x=0; $x < $width; $x++)
        for($y=0; $y < $height; $y++)
        {
            $colrgb = imagecolorat($img, $x, $y);
            if($col1 !== $colrgb)
                continue; 
            imagesetpixel ($img, $x , $y , $col2);
        }   
}
TimSC
  • 1,459
  • 16
  • 20
  • This doesn't get enough upvotes. This worked for me when I wanted to replace black to white on an image with transparency. Super. – Tin Tran Jul 21 '22 at 11:24
2

I guess the answer would be to have multiple versions of the image and then load the correct image depending on the chosen colour?

You could use a switch statement to load the correct image

//get selected colour
    switch ($colour) {
    case "red":
        echo "<img src='RED IMAGE' ";
        break;
    case "blue":
        echo "<img src='blue IMAGE' ";
        break;
    case "green":
        echo "<img src='green IMAGE' ";
        break;
}

Hope this helps.

David Sigley
  • 1,126
  • 2
  • 13
  • 28
  • What if the user want to chose a lighter/darker red? I can't make 1 milion images. This is why I wanted another solution (using GD library I think). – Florin Frătică Aug 29 '12 at 13:25
  • 1
    Why has this just been down voted? I get that it's not the right solution, but the question doesn't specify that they want every possible colour combination. – David Sigley Dec 05 '13 at 15:16
  • Down voted perhaps, this is Not a developer way of thinking :-) – Padmanabhan Mar 07 '19 at 05:34
2

I tried this:

<?php
$imgname = "1.gif";
$im = imagecreatefromgif ($imgname);
$index = imagecolorexact ($im,0,128,0);
imagecolorset($im,$index,240,255,0);
$imgname = "result.gif";
imagegif($im,$imgname);
?>
<img src="result.gif">

And instead of replacing every green pixel I got this (shirt color didn't changed):

the shirt wasn't replaced

Florin Frătică
  • 587
  • 4
  • 7
  • 13
1
<?php
header("Content-type: image/png");
$im = imagecreate(200, 200)
imagefill($im, 0, 0, $red);

// above could come from an uploaded image
// find a blue in the image
$newblue = imagecolorclosest($im, 0, 0, 255);
// change it to green
imagecolorset($im, $newblue, 0, 255, 0);
imagepng($im);
imagedestroy($im);
?php>

Here you find closest color to the blue and replace with green.

divide by zero
  • 2,340
  • 5
  • 23
  • 34