How to Swap Colors in Image Using Gd Library in PHP

Can I swap colors in image using GD library in PHP?

This will replace the white color with Gray

$imgname = "test.gif";
$im = imagecreatefromgif ($imgname);

$index = imagecolorclosest ( $im, 255,255,255 ); // get White COlor
imagecolorset($im,$index,92,92,92); // SET NEW COLOR

$imgname = "result.gif";
imagegif($im, $imgname ); // save image as gif
imagedestroy($im);

Sample Image

Replace a color with another in an image with PHP

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.

Colorizing and swapping colors with PHP GD Image Library?

use Blue (#0276DB) instead of orange, and then inverse the image (using IMAGE_FILTER_NEGATE) to get orange and black.

So, your code will be:

<?php
header('Content-type: image/jpeg');
$im = imagecreatefromjpeg('test.jpg');

imagefilter($im, IMG_FILTER_GRAYSCALE);
imagefilter($im, IMG_FILTER_CONTRAST, 255);
imagefilter($im, IMG_FILTER_NEGATE);
imagefilter($im, IMG_FILTER_COLORIZE, 2, 118, 219);
imagefilter($im, IMG_FILTER_NEGATE);

imagejpeg($im);
?>

Change HUE of an image with PHP GD Library?

I'm pretty sure there are no functions in PHP that can handle the change of hue. But you can write your own function to do this, here are the steps to change the image's hue:

  1. Traverse the image pixel by pixel
  2. Get the RGB color at pixel using imagecolorat()
  3. Transform the RGB value into a HSL value
  4. Change the hue value, leave saturation and lightness alone (Hue is a value from 0 to 360)
  5. Transform the new HSL value back to RGB
  6. Change the color at current pixel

Actually this seems quite an interesting thing to try out, so I might just do this myself and post it here if you don't find any other solution.

EDIT

Wrote the function. To change hue in PHP, you'll need functions to transform between RGB and HSL color spaces and a function that does the traversing of the image. This might be a bit ugly but it works nicely. Quite slow on larger images.

function imagehue(&$image, $angle) {
if($angle % 360 == 0) return;
$width = imagesx($image);
$height = imagesy($image);

for($x = 0; $x < $width; $x++) {
for($y = 0; $y < $height; $y++) {
$rgb = imagecolorat($image, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$alpha = ($rgb & 0x7F000000) >> 24;
list($h, $s, $l) = rgb2hsl($r, $g, $b);
$h += $angle / 360;
if($h > 1) $h--;
list($r, $g, $b) = hsl2rgb($h, $s, $l);
imagesetpixel($image, $x, $y, imagecolorallocatealpha($image, $r, $g, $b, $alpha));
}
}
}

Here's the required helper functions for converting color space, shamelessly copied from http://www.actionscript.org/forums/showthread.php3?t=50746 with minor alterations:

function rgb2hsl($r, $g, $b) {
$var_R = ($r / 255);
$var_G = ($g / 255);
$var_B = ($b / 255);

$var_Min = min($var_R, $var_G, $var_B);
$var_Max = max($var_R, $var_G, $var_B);
$del_Max = $var_Max - $var_Min;

$v = $var_Max;

if ($del_Max == 0) {
$h = 0;
$s = 0;
} else {
$s = $del_Max / $var_Max;

$del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
$del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
$del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;

if ($var_R == $var_Max) $h = $del_B - $del_G;
else if ($var_G == $var_Max) $h = ( 1 / 3 ) + $del_R - $del_B;
else if ($var_B == $var_Max) $h = ( 2 / 3 ) + $del_G - $del_R;

if ($h < 0) $h++;
if ($h > 1) $h--;
}

return array($h, $s, $v);
}

function hsl2rgb($h, $s, $v) {
if($s == 0) {
$r = $g = $B = $v * 255;
} else {
$var_H = $h * 6;
$var_i = floor( $var_H );
$var_1 = $v * ( 1 - $s );
$var_2 = $v * ( 1 - $s * ( $var_H - $var_i ) );
$var_3 = $v * ( 1 - $s * (1 - ( $var_H - $var_i ) ) );

if ($var_i == 0) { $var_R = $v ; $var_G = $var_3 ; $var_B = $var_1 ; }
else if ($var_i == 1) { $var_R = $var_2 ; $var_G = $v ; $var_B = $var_1 ; }
else if ($var_i == 2) { $var_R = $var_1 ; $var_G = $v ; $var_B = $var_3 ; }
else if ($var_i == 3) { $var_R = $var_1 ; $var_G = $var_2 ; $var_B = $v ; }
else if ($var_i == 4) { $var_R = $var_3 ; $var_G = $var_1 ; $var_B = $v ; }
else { $var_R = $v ; $var_G = $var_1 ; $var_B = $var_2 ; }

$r = $var_R * 255;
$g = $var_G * 255;
$B = $var_B * 255;
}
return array($r, $g, $B);
}

And finally, an usage example. This example opens an image, shifts its hue by 180° and outputs to the browser:

header('Content-type: image/png');
$image = imagecreatefrompng('image.png');
imagehue($image, 180);
imagepng($image);

As the angle of hue is set in degrees, giving 0, 360, 720 or any multiple of 360 will result in no change to the image.

PHP GD palette colors

Check the return on imagecolorstotal, you are always getting 256 colors as the return no matter how high you set the number of colors to be dithered to. PNG-8 & GIF formats only support palettes of up to 256 colors. So even if you can use more than 256 in a palette, you'd have to save it back as true color for anyone to be able to use it, thus making the whole conversion process a waste of time. In other words imagetruecolortopallete has an upper limit of 256 colors, you cannot go higher.

Here's how you can do it in truecolor, though it's resource intensive. Maybe look into imagemagick if you want to do this more efficiently.

$im = imagecreatefrompng("lamb.png");
$img = imagecreatetruecolor(imagesx($im), imagesy($im));
$degrees = 0;
if ($degrees > 360) {$degrees = $degrees % 360 ;}

foreach (range(0, imagesx($im) - 1) as $x ) {
foreach (range(0, imagesy($im) - 1) as $y) {
$rgb = imagecolorat($im, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$hsv = rgbtohsv($r,$g,$b);
$rgb = hsvtorgb($degrees, $hsv['s'], $hsv['v']);
imagesetpixel($img, $x,$y,imagecolorallocate($img, $rgb['r'], $rgb['g'], $rgb['b']));
}
}

imagepng($img, 'lamb2.png');

Edit: Adding rgbtohsv & hsvtorgb functions. I did not write these functions.

function rgbtohsv ($R, $G, $B) {
// HSV Results:Number 0-1
$HSL = array();

$var_R = ($R / 255);
$var_G = ($G / 255);
$var_B = ($B / 255);

$var_Min = min($var_R, $var_G, $var_B);
$var_Max = max($var_R, $var_G, $var_B);
$del_Max = $var_Max - $var_Min;

$V = $var_Max;

if ($del_Max == 0)
{
$H = 0;
$S = 0;
}
else
{
$S = $del_Max / $var_Max;

$del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
$del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
$del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;

if ($var_R == $var_Max) $H = $del_B - $del_G;
else if ($var_G == $var_Max) $H = ( 1 / 3 ) + $del_R - $del_B;
else if ($var_B == $var_Max) $H = ( 2 / 3 ) + $del_G - $del_R;

if ($H<0) $H++;
if ($H>1) $H--;
}

$HSL['h'] = $H;
$HSL['s'] = $S;
$HSL['v'] = $V;

return $HSL;
}

function hsvtorgb ($H, $S, $V)
{
$RGB = array();

if($S == 0)
{
$R = $G = $B = $V * 255;
}
else
{
$var_H = $H * 6;
$var_i = floor( $var_H );
$var_1 = $V * ( 1 - $S );
$var_2 = $V * ( 1 - $S * ( $var_H - $var_i ) );
$var_3 = $V * ( 1 - $S * (1 - ( $var_H - $var_i ) ) );

if ($var_i == 0) { $var_R = $V ; $var_G = $var_3 ; $var_B = $var_1 ; }
else if ($var_i == 1) { $var_R = $var_2 ; $var_G = $V ; $var_B = $var_1 ; }
else if ($var_i == 2) { $var_R = $var_1 ; $var_G = $V ; $var_B = $var_3 ; }
else if ($var_i == 3) { $var_R = $var_1 ; $var_G = $var_2 ; $var_B = $V ; }
else if ($var_i == 4) { $var_R = $var_3 ; $var_G = $var_1 ; $var_B = $V ; }
else { $var_R = $V ; $var_G = $var_1 ; $var_B = $var_2 ; }

$R = $var_R * 255;
$G = $var_G * 255;
$B = $var_B * 255;
}

$RGB['r'] = $R;
$RGB['g'] = $G;
$RGB['b'] = $B;

return $RGB;
}

Change “Saturation” of an image with PHP GD Library?

I think you need something like

$s=$s * (100+$saturationPercentage)/100 

else you are just adding a constant to each value rather than a percentage of the existing value.

Also, where you decrement 1 if your new saturation exceeds 1, you probaly would be better just setting it to 1.0, i.e. fully saturated like this:

if($s>1)$s=1

otherwise, say the resulting saturation is 1.3 (i.e. very, very saturated) you will make that into 0.3, i.e. very undersaturated, instead of 1.0 (fully saturated).

So, if $s is 0.7, and you add 10%, you will get

$s = 0.7 * (100 + 10)/100
$s = 0.7 * 1.1
$s = 0.77


Related Topics



Leave a reply



Submit