...

View Full Version : Checking PNG files for transparency



pootlecat
04-12-2012, 10:33 PM
Hi,

I found this code today and was really happy, for a short while:
http://stackoverflow.com/questions/2057923/how-to-check-a-png-for-grayscale-alpha-color-type


if(ord(file_get_contents($alpha_png_candidate, NULL, NULL, 25, 1)) == 6) {
is_alpha_png_so_do_something();
}

The function is supposed to return the following:
0 - greyscale
2 - RGB
3 - RGB with palette
4 - greyscale + alpha
6 - RGB + alpha
But all the PNG files I test return a value of "1".
Does anyone have any ideas?

Thanks!

Fou-Lu
04-13-2012, 05:49 AM
Meh I should get my environment reinstalled.
Taking a look at the first spec I found here: http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html 25th byte looks correct. 8 for png header, 4 for chunk length, 4 for chunk type, 4 for width, 4 for height, and finally the bit depth. So lets see, 8+4+4+4+4 = yeah 24 so that's right. Start at 25, read one byte.

What's actually returning 1 that you indicate here? Have you successfully opened the file and read that byte? Given the filestructure, the ord should only return 0, 2, 3, 4, 6; assuming that this structure is correct, 1 is not an option.

pootlecat
04-13-2012, 03:26 PM
Thanks very much for your reply, I'm pulling my hair out lol :)
Here is the code I am using:


function is_alpha_png($fn){
return (ord(@file_get_contents($fn, NULL, NULL, 25, 1)) == 6);
}
$fin = "00100000001.png";
$trans = is_alpha_png($fin);
echo "trans = $trans <br>";

and it's printing out "trans = 1".
This is what the PNG looks like:
http://affiliates.vitalimagery.com/pnginfo.gif
If I'm calculating right (its been many years!) it should be returning '6' which would be right...

Fou-Lu
04-13-2012, 06:19 PM
Yes this is correct then.
The result of the function is_alpha_png is returning a boolean. If it returns 0, then it does not have a bit depth of 6. Any other result (typically 1), it does.



if (is_alpha_png($fin))
{
print 'This file has alpha transparency';
}


If you want to return the bitdepth, pull the ==6 off of the comparison.

pootlecat
04-13-2012, 06:27 PM
Thank you so much - I had a feeling I was missing something simple! :)

pootlecat
04-13-2012, 06:41 PM
Soooo, it's reporting the bitdepth correctly now but (after some testing) I guess a PNG can have an alpha channel and not be transparent so I'm still not much further forward. Can anyone confirm this is the case?

Fou-Lu
04-13-2012, 07:14 PM
Soooo, it's reporting the bitdepth correctly now but (after some testing) I guess a PNG can have an alpha channel and not be transparent so I'm still not much further forward. Can anyone confirm this is the case?

Best I know you can have an alpha layer and not deal with it it all. It just wastes more space than necessary.
Graphics are not my specialty, but I don't believe that PHP has a builtin way to detect alpha levels in images. This will require you to parse the image according to the spec (which is relatively complex), and scan the alpha channels manually.

Is there a reason why you need to know whether a png contains a transparent layer?

pootlecat
04-13-2012, 07:28 PM
Best I know you can have an alpha layer and not deal with it it all. It just wastes more space than necessary.
Graphics are not my specialty, but I don't believe that PHP has a builtin way to detect alpha levels in images. This will require you to parse the image according to the spec (which is relatively complex), and scan the alpha channels manually.

Is there a reason why you need to know whether a png contains a transparent layer?

It is something our customers always want to know and I was really hoping I could find an easy way to check a PNG and let them know.
Thanks!

Fou-Lu
04-13-2012, 09:17 PM
Then this will suffice.
The alternative is to go through the entire image and check each pixel to see if the alpha channel is opaque. Just going through the GD, it does appear that this can be done with PHP GD library.


function hasAlphaColour($r)
{
$bResult = false;
$x = imagesx($r);
$y = imagesy($r);
for ($i = 0; $i < $x && !$bResult; ++$i)
{
for ($j = 0; $j < $y && !$bResult; ++$j)
{
$index = imagecolorat($r, $i, $j);
$colors = imagecolorsforindex($r, $index);
if (isset($colors['alpha']) && $colors['alpha'] > 0)
{
$bResult = true;
}
}
}
return $bResult;
}

if (is_alpha_png($fin))
{
$r = imagecreatefrompng($fin);
if (hasAlphaColour($r))
{
print 'has at least one color with alpha';
}
imagedestroy($r);
}


Looks like would work; no clue if it actually does.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum