Search code examples
phpimagemagickpngimagickalpha-transparency

PHP removing alpha in Imagick results in corrupted picture


I have an URL with an image. I save the image inside a variable. If I load the variable with Imagick, the image is after removing the alpha corrupted.

code:

$image = new Imagick();
$image->readImageBlob($picture);
$image->writeImage ("test.png");

enter image description here

code:

$image = new Imagick();
$image->readImageBlob($picture);
$image->setImageBackgroundColor('white');
$image->setImageAlphaChannel(11);
$image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->writeImage ("test.png");

enter image description here

PHP Version 7.3.11

imagick module version: 3.4.4RC2

Imagick compiled with ImageMagick version: ImageMagick 7.0.7-11 Q16 x64 2017-11-23

ImageMagick release date: 2017-11-23

The image is broken right after "setImageAlphaChannel". Is the source file causing the issue? If yes, is there a way to repair the broken image?

Thanks in advance!

Edit:

Here is my full code:

<?php


$url="https://i.imgur.com/jD5hRgO.png";

$ch = curl_init(); 
curl_setopt ($ch, CURLOPT_URL, $url); 
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
curl_setopt ($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6"); 
curl_setopt ($ch, CURLOPT_TIMEOUT, 60); 
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1); 
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt ($ch, CURLOPT_REFERER, $url); 
$picture = curl_exec ($ch); 
curl_close($ch);

$image = new Imagick();
$image->readImageBlob($picture);
$image->writeImage ("before.png");


$image = new Imagick();
$image->readImageBlob($picture);
$image->setImageBackgroundColor('white');
$image->setImageAlphaChannel(11);
$image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->writeImage ("after.png");


?>

Solution

  • You want to use Imagick::ALPHACHANNEL_REMOVE.

    $image = new Imagick();
    $image->readImageBlob($picture);
    $image->setImageBackgroundColor('white');
    $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
    $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
    $image->writeImage ("after.png");
    

    This will replace transparent pixels with the background color.

    The image is broken right after "setImageAlphaChannel". Is the source file causing the issue?

    Not really broken, but the issue is caused by the source file. Setting the alpha channel to 11 (i.e. OpaqueAlphaChannel in the C-API) will force the "hidden" color values to be opaque. In your example, the unseen RGB data was left-over artifacts from the author generating the image.

    If yes, is there a way to repair the broken image?

    Nope! You need to redo the broken files from source. Applying -alpha opaque is destructive to the alpha mask.

    Quote from "Masks" usage article...

    The original 'shape' of the image can no longer be recovered after this operation as the original alpha channel data has been overwritten.