There is an excellent answer on how to change the HUE of an image using PHP-GD library. But I need to know how to change the SATURATION of an image using PHP-GD. Here is a copy of the code from the answer which successfully changes the HUE of the image.
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));
}
}
}
If you need to take a look at the code of helper functions rgb2hsl
and hsl2rgb
please check the original answer. Since Hue
is one of the parameters of HSL, I thought I could modify the function somehow to get a working solution for Saturation. Despite of limited php skills I had to try but it did not work and produced bizarre results. Here is the modification that I am trying.
MODIFIED CODE: UPDATED as suggested by @mark
function imageSaturation(&$image, $saturationPercentage) {
$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);
$s = $s * (100 + $saturationPercentage ) /100;
if($s > 1) $s = 1;
list($r, $g, $b) = hsl2rgb($h, $s, $l);
imagesetpixel($image, $x, $y, imagecolorallocatealpha($image, $r, $g, $b, $alpha));
}
}
}
header('Content-type: image/png');
$image = imagecreatefrompng('rgb.png');
imageSaturation($image, -80);//bring down current image saturation to 80%
imagepng($image);
EFFORTS UPDATE : It has been pointed out to me by @Dai that these lines help construct a color code of an individual RGB pixel. So I guess this part can remained unchanged ?
$rgb = imagecolorat($image, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$alpha = ($rgb & 0x7F000000) >> 24;
In the next line we are simply converting the RGB values to HSL with rgb2hsl($r, $g, $b);
and assigning it to list($h, $s, $l)
. The point I am stuck at the moment are these lines.
$s += $saturationPercentage / 100;
if($s > 1) $s--;
I understand the syntax, but not sure how I handle these or if they are even required. If not an answer helpful hints / suggestions would be great. I am trying the code on this image to bring down the saturation from 100% to 80%, but I am getting this image as result.
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