I have set of images. In this images exist green alpha color. I need replace that transparent color to another color (i want replace to white alpha color).
Its my code:
$img = imagecreatefrompng($path . $file);
$white_color_transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
for ($y = 0; $y < imagesy($img); $y++) {
for ($x = 0; $x < imagesx($img); $x++) {
$rgb = imagecolorat($img, $x, $y);
$pixel_color = imagecolorsforindex($img, $rgb);
if ($pixel_color['alpha'] != 0 && $pixel_color['alpha'] != 127){
imagesetpixel($img, $x, $y, $white_color_transparent);
}
}
}
imagealphablending($img, false);
imagesavealpha($img, true);
imagepng($img, $path . $file);
And my result color its the same than id source image, when i add before
imagesetpixel($img, $x, $y, $white_color_transparent);
that line:
imagesetpixel($img, $x, $y, $white_color);
i get only white color without transparency.
Without seeing your image, I'm not sure there's an easy way to do it.
EDIT 2:
One thing I noticed from my first edit is that it didn't work for an image with transparency and had no opaque layer behind it.
Here is my attempt to deal with an image that has some transparency. As you can see by the example. It didn't work out perfectly.
<?php
//These colors here are the rgba values of the green transparency I used in my test image. You will need to know this to reverse the rgb blending.
$red = 28;
$green = 198;
$blue = 72;
$alpha = .48;
$img = imagecreatefrompng('test.png');
//Adding in the image blending that Zombaya brought up. Need this so it overwrites the pixel instead of blending it
imagealphablending($img, false);
for ($y = 0; $y < imagesy($img); $y++) {
for ($x = 0; $x < imagesx($img); $x++) {
$rgb = imagecolorat($img, $x, $y);
$pixel_color = imagecolorsforindex($img, $rgb);
//If pixel color matches our alpha layer color, we change it white transparent
//Not sure how accurate the rounding for the alpha conversion is. Maybe the reason for the green edges in this example:
if($pixel_color['red'] == $red &&
$pixel_color['green'] == $green &&
$pixel_color['blue'] == $blue &&
$pixel_color['alpha'] == round(127 - ($alpha * 127))){
$color = imagecolorallocatealpha($img, 255, 255, 255, 127);
} else {
//This is the algorithm from the link. But reordered to get the old color before the transparent color went over it.
$oldR = ($pixel_color['red'] - $alpha * $red) / (1 - $alpha);
$oldG = ($pixel_color['green'] - $alpha * $green ) / (1 - $alpha);
$oldB = ($pixel_color['blue'] - $alpha * $blue) / (1 - $alpha);
$color = imagecolorallocatealpha($img, $oldR, $oldG, $oldB, $pixel_color['alpha']);
}
imagesetpixel($img, $x, $y, $color);
}
}
imagesavealpha($img, true);
imagepng($img, 'test_result.png');
-> Original without transparency
-> Starting image with transparency
-> Resulting image. Notice the green edges. And I may have got lucky with using similar opacity for the red and green. The white part is transparent
EDIT:
I thought about this some more and I came across this link: How to calculate an RGB colour by specifying an alpha blending amount?
This helped me understand how to fix your problem. Although this is dependent on if you have just a solid color that is transparent over the image. If it is a gradient it is more difficult.
<?php
//These colors here are the rgba values of the green transparency I used in my test image. You will need to know this to reverse the rgb blending.
$red = 44;
$green = 215;
$blue = 56;
$alpha = .45;
$img = imagecreatefrompng('test2.png');
for ($y = 0; $y < imagesy($img); $y++) {
for ($x = 0; $x < imagesx($img); $x++) {
$rgb = imagecolorat($img, $x, $y);
$pixel_color = imagecolorsforindex($img, $rgb);
//This is the algorithm from the link. But reordered to get the old color before the transparent color went over it.
$oldR = ($pixel_color['red'] - $alpha * $red) / (1 - $alpha);
$oldG = ($pixel_color['green'] - $alpha * $green ) / (1 - $alpha);
$oldB = ($pixel_color['blue'] - $alpha * $blue) / (1 - $alpha);
$color = imagecolorallocate($img, $oldR, $oldG, $oldB);
imagesetpixel($img, $x, $y, $color);
}
}
imagesavealpha($img, true);
imagepng($img, 'test_result.png');
- Starting Image
- After Image
Here is an explanation of the rgb calculation used in the code above. The link shows the basic formula:
out = alpha * new + (1 - alpha) * old
out
is the resulting color after mixing the original with the new color.
So we need to rearrange the formula to get the old color, which yields this:
old = (out - alpha * new) / (1 - alpha)
OLD ANSWER:
Why this line doesn't work:
$white_color_transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
127 means fully transparent, so that means it is invisible. Which is why the result image is the same as the starting image.
Why this line creates a fully white image:
$white_color = imagecolorallocatealpha($img, 255, 255, 255, 0);
or
$white_color = imagecolorallocate($img, 255, 255, 255);
This basically just places a white pixel over the selected pixel (0 means no transparency), which is why the selected pixels become fully white.
Now if you do the following:
$white_color_semi_transparent = imagecolorallocatealpha($img, 255, 255, 255, 40);
Instead of replace the transparent green with a transparent white, you know get a lighter green instead of a semi transparent white.
See my test example:
- Starting Image
- Resulting Image with color 255,255,255,40
So this tells us two things:
I'm not sure how you'd solve your issue. It would depend on your image. I think it's possible to get the coloring you want, but it obviously the more complex your image is the more difficult it will be. For example, my two overlapped squares with two colors versus say a photo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With