php-imagine / Imagine

PHP Object Oriented image manipulation library
https://imagine.readthedocs.io
Other
4.42k stars 530 forks source link

`getImageAlphaChannel` returns incorrect value #842

Closed brianjhanson closed 1 year ago

brianjhanson commented 1 year ago

Issue description

798 changed the logic surrounding alpha channels and seems to have caused the $image->getImagick()->getImageAlphaChannel() to return true for JPG.

What version of Imagine are you using?

1.3.3

What's the PHP version you are using?

PHP 8.0.26 (cli) (built: Dec  5 2022 21:59:43) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.26, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.26, Copyright (c), by Zend Technologies

What's the imaging library you are using [gd/imagick/gmagick/any]?

imagick

What's the imaging library configuration

imagick

imagick module => enabled
imagick module version => 3.7.0
imagick classes => Imagick, ImagickDraw, ImagickPixel, ImagickPixelIterator, ImagickKernel
Imagick compiled with ImageMagick version => ImageMagick 6.9.11-60 Q16 x86_64 2021-01-25 https://imagemagick.org
Imagick using ImageMagick library version => ImageMagick 6.9.11-60 Q16 aarch64 2021-01-25 https://imagemagick.org
ImageMagick copyright => (C) 1999-2021 ImageMagick Studio LLC
ImageMagick release date => 2021-01-25
ImageMagick number of supported formats:  => 237
ImageMagick supported formats => 3FR, 3G2, 3GP, AAI, AI, APNG, ART, ARW, AVI, AVIF, AVS, BGR, BGRA, BGRO, BIE, BMP, BMP2, BMP3, BRF, CAL, CALS, CANVAS, CAPTION, CIN, CIP, CLIP, CMYK, CMYKA, CR2, CR3, CRW, CUR, CUT, DATA, DCM, DCR, DCX, DDS, DFONT, DNG, DPX, DXT1, DXT5, EPDF, EPI, EPS, EPS2, EPS3, EPSF, EPSI, EPT, EPT2, EPT3, ERF, FAX, FILE, FITS, FRACTAL, FTP, FTS, G3, G4, GIF, GIF87, GRADIENT, GRAY, GRAYA, GROUP4, H, HALD, HDR, HEIC, HISTOGRAM, HRZ, HTM, HTML, HTTP, HTTPS, ICB, ICO, ICON, IIQ, INFO, INLINE, IPL, ISOBRL, ISOBRL6, J2C, J2K, JBG, JBIG, JNG, JNX, JP2, JPC, JPE, JPEG, JPG, JPM, JPS, JPT, JSON, K25, KDC, LABEL, M2V, M4V, MAC, MAGICK, MAP, MASK, MAT, MATTE, MEF, MIFF, MKV, MNG, MONO, MOV, MP4, MPC, MPG, MRW, MSL, MTV, MVG, NEF, NRW, NULL, ORF, OTB, OTF, PAL, PALM, PAM, PATTERN, PBM, PCD, PCDS, PCL, PCT, PCX, PDB, PDF, PDFA, PEF, PES, PFA, PFB, PFM, PGM, PGX, PICON, PICT, PIX, PJPEG, PLASMA, PNG, PNG00, PNG24, PNG32, PNG48, PNG64, PNG8, PNM, POCKETMOD, PPM, PREVIEW, PS, PS2, PS3, PSB, PSD, PTIF, PWP, RADIAL-GRADIENT, RAF, RAS, RAW, RGB, RGBA, RGBO, RGF, RLA, RLE, RMF, RW2, SCR, SCT, SFW, SGI, SHTML, SIX, SIXEL, SPARSE-COLOR, SR2, SRF, STEGANO, SUN, TEXT, TGA, THUMBNAIL, TIFF, TIFF64, TILE, TIM, TTC, TTF, TXT, UBRL, UBRL6, UIL, UYVY, VDA, VICAR, VID, VIDEO, VIFF, VIPS, VST, WBMP, WEBM, WEBP, WMV, WPG, X, X3F, XBM, XC, XCF, XPM, XPS, XV, XWD, YCbCr, YCbCrA, YUV

Directive => Local Value => Master Value
imagick.locale_fix => 0 => 0
imagick.skip_version_check => 1 => 1
imagick.progress_monitor => 0 => 0
imagick.set_single_thread => 1 => 1
imagick.shutdown_sleep_count => 10 => 10
imagick.allow_zero_dimension_images => 0 => 0

Minimal PHP code to reproduce the error:

The exact images I used in this example are below


$png = __DIR__ . '/assets/puppy-transparent.png';
$jpg = __DIR__ . '/assets/puppy.jpg';

echo '<h2>Imagine</h2>';
$imagine = new \Imagine\Imagick\Imagine();

/** @var \Imagine\Image\ImageInterface $pngImage */
$pngImage = $imagine->open($png);
$jpgImage = $imagine->open($jpg);

echo '<pre>';
var_dump([
    'png' => $pngImage->getImagick()->getImageAlphaChannel(),
    'jpg' => $jpgImage->getImagick()->getImageAlphaChannel()
]);
echo '</pre>';

echo '<h2>Imagick</h2>';

$imPng = new Imagick($png);
$imJpg = new Imagick($jpg);

echo '<pre>';
var_dump([
    'png' => $imPng->getImageAlphaChannel(),
    'jpg' => $imJpg->getImageAlphaChannel()
]);
echo '</pre>';

Output Screenshot

CleanShot 2023-01-24 at 13 37 18

Assets used

puppy puppy-transparent

ausi commented 1 year ago

I think getImageAlphaChannel() returning true is correct here as the image has an alpha channel at this point (even though it might not be used).

To determine if the image has any transparency maybe the following code can help? (untested)

$alphaRange = $image->getImagick()->getImageChannelRange(Imagick::CHANNEL_ALPHA);
$isTransparent = $alphaRange['minima'] < $alphaRange['maxima'];
brianjhanson commented 1 year ago

Thank you @ausi! I was just coming around to the same feeling. I'm not super familiar with this library, so it took me most of the day to reason around what was happening.

This was a bug reported in our CMS so I'll fix it over there and close things here.

Thanks again, that snippet worked perfectly.

ausi commented 1 year ago

👍

Maybe such a hasTransparency() method would be a good addition to this library too. But I’m not sure how easy this is to achieve with the other drivers (GD and GMagick).