PHP & GD - transparent background being filled with nearby color
I know PHP+GD Transparency issues have been beat to death on this and many other sites, but I've followed all the recommendations and I can't seem to fix my issue.
First, the explanation:
I am trying to overlay one image on top of another on开发者_如何学JAVAe. They both have areas that are transparent. As a demo that I know should look a particular way, I am trying to overlay a checkmark on top of a blue arrow shape that I created.
Here are the two images:
Now to my code:
I am using a library/API that I built to take a TINY bit of the pain away from editing images with PHP+GD. It's still in it's infancy, but the pertinent files are:
The Base Class
The Main Loader The (poorly named) Combine ClassI am running the code using the following script:
<?php
require_once('Image.php');
header("Content-Type: image/png");
$img = new Image();
$over = new Image();
$img->source = "arrow.png";
$over->source = "chk-done_24.png";
$img->Combine->Overlay($over, 20, 20, 0, 0, $over->width, $over->height);
$img->output();
$img->clean();
unset($img);
?>
I expect the output to be something like this:
But instead I get this:
I would totally understand the issue if the filled area was white or black, but filling with the blue color just doesn't make any sense to me.
In the Combine Class I linked above, I have also tried imagecopy, imagecopyresampled, and the vanilla imagecopymerge, both with similar results.
I'm at a total loss.
Edit:
To be clear, my question is this: What part of my code is incorrect? Why is it filling the transparent area with a color (instead of black or white) and how can I fix it while still maintaining the ability to merge images with transparency?
Update:
Please note, when a new Image object is created, it calls newImage
which contains the following code:
$this->handle = imagecreatetruecolor($this->width, $this->height);
imagealphablending($this->handle, false);
imagesavealpha($this->handle, true);
I feel like that might be easy to miss.
Note that it doesn't matter that you create the handle in newImage
and call imagealphablending
and imagesavealpha
on it, because loadImage
throws that handle away.
The reason it is "filling" the transparent area with the blue color is that it is not filling the transparent area with anything at all. It it just completely dropping the alpha channel, and the blue color is what happens to be stored in those pixels with an alpha of zero. Note this may be difficult to see in a graphics program, as that program may itself replace completely-transparent pixels with black or white.
As for what is wrong with your code, I can't say for sure as I don't get the same results as you report when I try your existing code. But if I change your loadImage
to something like this so the source images are forced to true color, it works for me:
private function loadImage()
{
$img = null;
switch( $this->type )
{
case 1:
$img = imagecreatefromgif($this->source);
break;
case 2:
$img = imagecreatefromjpeg($this->source);
break;
case 3:
$img = imagecreatefrompng($this->source);
break;
default:
break;
}
if (!$img) return false;
$this->handle = imagecreatetruecolor($this->width, $this->height);
imagealphablending($this->handle, false);
imagesavealpha($this->handle, true);
imagecopyresampled($this->handle, $img, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
return true;
}
(Personally, I prefer ImageMagick over GD).
精彩评论