Skip to content
Advertisement

Convert PNG files with transparency to WebP using PHP GD

I have a utility class that loads image files and, among other operations, converts them to other formats. It uses PHP GD.

Everything works fine except PNG files that have transparency are done wrong when converting to WebP. The result image has a black background where the transparency should be.

This is my code:

class OImage {
    private ?GdImage $image      = null;
    private ?int     $image_type = null;
    
    public function load(string $filename): void {
        $image_info       = getimagesize($filename);
        $this->image_type = $image_info[2];

        switch ($this->image_type) {
            case IMAGETYPE_JPEG: { $this->image = imagecreatefromjpeg($filename); }
            break;
            case IMAGETYPE_GIF: {  $this->image = imagecreatefromgif($filename);  }
            break;
            case IMAGETYPE_PNG: {  $this->image = imagecreatefrompng($filename);  }
            break;
            case IMAGETYPE_WEBP: { $this->image = imagecreatefromwebp($filename); }
            break;
        }
    }
    
    public function save(string $filename, int $image_type=IMAGETYPE_JPEG, int $compression=75, int $permissions=null): void {
        switch ($image_type) {
            case IMAGETYPE_JPEG: { imagejpeg($this->image, $filename, $compression); }
            break;
            case IMAGETYPE_GIF: {  imagegif($this->image,  $filename); }
            break;
            case IMAGETYPE_PNG: {  imagepng($this->image,  $filename); }
            break;
            case IMAGETYPE_WEBP: {
                imagepalettetotruecolor($this->image);
                imagealphablending($this->image, true);
                imagesavealpha($this->image, true);
                imagewebp($this->image, $filename);
            }
            break;
        }
        if (!is_null($permissions)) {
            chmod($filename, $permissions);
        }
    }
    
    ...
}

The class has many other functions to resize or scale, but are not related to my problem here. I have tried setting imagealphablending and imagesavealpha to true or false with the exact same outcome.

I was also thinking on switching to Imagick, but they don’t have yet a PHP 8 extension.

I am using PHP 8 on Debian 9 and GD 2.2.4

Any help?

Thanks!

Advertisement

Answer

Yes! Thanks @msbit, I was calling to resize on my tests, as I supposed that code was ok… and it wasn’t 😅 The resize function used to be:

    public function resize(int $width, int $height): void {
        $new_image = imagecreatetruecolor($width, $height);
        imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
        $this->image = $new_image;
    }

Now I have added an if to check if it is a PNG or WebP so this is the result:

    public function resize(int $width, int $height): void {
        $new_image = imagecreatetruecolor($width, $height);
        if ($this->image_type === IMAGETYPE_PNG || $this->image_type === IMAGETYPE_WEBP) {
            imagealphablending($new_image, false);
            imagesavealpha($new_image, true);
            $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
            imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent);
        }
        imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
        $this->image = $new_image;
    }

Now everything works flawlessly 🥳

Thanks!!

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement