Search code examples
phpcd

PHP GD: Black background transparent


I have the problem that a picture is transparent (which it should be) but the part where a "blend mode" is, is still a bit black but it should not be.

  • Image 1: https://i.sstatic.net/a421g.png
  • Image 2: https://i.sstatic.net/1b74h.png
  • Image 3: https://i.sstatic.net/ysGZ6.png

and the output https://i.sstatic.net/flEBT.png

you can see in the output the small black circles around the yellow part.

my code:

$dst = imagecreatetruecolor(1000, 1000);

    imagefill($dst, 0, 0, imagecolorallocatealpha($dst, 0, 0, 0, 127));

    foreach ($images as $value) {
        // IMPROVE!
        $value[1] = (500 - $value[1]);
        $value[2] = (500 - $value[2]);

        $src = imagecreatefrompng("result/$value[0].png");

        imagealphablending($src, false);
        imagesavealpha($dst, true);

        // BLEND MODE
        imagecolortransparent($src, imagecolorat($src, 0, 0));

        imagecopy($dst, $src, $value[1], $value[2], 0, 0, imagesx($src), imagesy($src));
        imagedestroy($src);
    }

    $dst = imagecropauto($dst, IMG_CROP_DEFAULT);

    imagepng($dst, sprintf('images/64/%s_%d.png', $name, $rotation));
    imagedestroy($dst

So I hope anyone can help!

Greetings.


Solution

  • "image 3" is screen blend image. Since there is no function in GD library, you should make it yourself or use ImageMagick.

    example blend code for each pixel using GD:

    $src = imagecreatefrompng("result/$value[0].png");
    $rgba = imagecolorat($src, 0, 0);
    $color = imagecolorsforindex($src, $rgba);
    
    //2-type blend mode
    if($color['alpha'] == 0){
        //no-alpha image, Screen Blend
        for($y = $value[2]; $y < imagesy($dst); $y++){
            if($y - $value[2] > imagesy($src) - 1) break;
            if($y < 0) continue;
            for($x = $value[1]; $x < imagesx($dst); $x++){
                if($x - $value[1] > imagesx($src) - 1) break;
                if($x < 0) continue;
                $rgb_dst = imagecolorat($dst, $x, $y);
                $colors_dst = imagecolorsforindex($dst, $rgb_dst);
    
                $rgb_src = imagecolorat($src, $x - $value[1], $y - $value[2]);
                $colors_src = imagecolorsforindex($src, $rgb_src);
    
                $r = $colors_dst['red'] + $colors_src['red'] - ($colors_dst['red'] * $colors_src['red']) / 255;
                $g = $colors_dst['green'] + $colors_src['green'] - ($colors_dst['green'] * $colors_src['green']) / 255;
                $b = $colors_dst['blue'] + $colors_src['blue'] - ($colors_dst['blue'] * $colors_src['blue']) / 255;
                $alpha = $colors_dst['alpha'];
    
                imagesetpixel($dst, $x, $y, imagecolorallocatealpha($dst, $r, $g, $b, $alpha));
            }
        }
    }else{
        //legacy
        imagealphablending($src, false);
        imagecolortransparent($src, imagecolorat($src, 0, 0));
        imagecopy($dst, $src, $value[1], $value[2], 0, 0, imagesx($src), imagesy($src));
    }
    imagedestroy($src);
    

    result: result image