Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 one. 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:

check mark

blue arrow

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 Class

I 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:

Combined images

But instead I get this:

Square bottom

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.

like image 663
rockerest Avatar asked Jun 03 '11 15:06

rockerest


People also ask

What PHP stand for?

PHP, originally derived from Personal Home Page Tools, now stands for PHP: Hypertext Preprocessor, which the PHP FAQ describes as a "recursive acronym." PHP executes on the server, while a comparable alternative, JavaScript, executes on the client.

What is PHP or HTML?

PHP is used for server-side programming which will interact with databases to retrieve information, storing, email sending, and provides content to HTML pages to display on the screen. HTML is used for specifying colors, text formatting, aligning, etc. PHP is easy to learn but not as much as HTML.

Is PHP a programming?

PHP is an open-source, server-side programming language that can be used to create websites, applications, customer relationship management systems and more. It is a widely-used general-purpose language that can be embedded into HTML.

Is PHP used anymore?

PHP is known to be the most frequently used programming language. According to W3Techs, 78.8% of all websites are using PHP for their server-side. Interesting fact: PHP originally stood for Personal Home Page. Now PHP is widely known and thought of as Hypertext Preprocessor.


1 Answers

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).

like image 133
Anomie Avatar answered Oct 04 '22 00:10

Anomie