20

I am looking for a way to quickly determine if a PNG image has transparent features. That is, whether any portion of the image is translucent or displays the background in any way. Does anyone one know a simple way to detect this?

UPDATE: OK, is there a less complicated way then to pull out the PNG specification and hacking code?

Mechanical snail
  • 29,755
  • 14
  • 88
  • 113
kenny
  • 21,522
  • 8
  • 49
  • 87
  • 1
    What exactly are you looking for? The presence of an alpha channel? The declaration of a transparent color in an 8-bit PNG palette? The presence of fully transparent pixels? What about semitransparent pixels and palette entries? – Michael Madsen Apr 02 '10 at 22:34
  • I am looking to determine if any aspect of the PNG image that makes any portion of the image translucent and display the background in any way. – kenny Apr 03 '10 at 01:09

3 Answers3

19

Why not just loop through all of the pixels in the image and check their alpha values?

    bool ContainsTransparent(Bitmap image)
    {
        for (int y = 0; y < image.Height; ++y)
        {
            for (int x = 0; x < image.Width; ++x)
            {
                if (image.GetPixel(x, y).A != 255)
                {
                    return true;
                }
            }
        }
        return false;
    }
Adam P
  • 4,603
  • 6
  • 31
  • 40
  • 11
    Keep in mind that using GetPixel is atrociously slow. You should use the Bitmap.LockBits method to get a pointer to the image data, and use unsafe code to process the image. The GetPixel method will lock the image bits, get the pixel data, build a Color struct, then unlock the image bits every time it is called, requiring orders of magnitude more processing time. – jrista Apr 03 '10 at 02:34
  • I was hoping for something a little quicker than checking every pixel. But it is certainly easier than RTM. I'll have to decide if I have the time for that brute force check. Thanks. – kenny Apr 03 '10 at 10:45
  • 2
    It would be more efficient to return true from within the loop, therefore exiting immediately if the first pixel is transparent. – Tim Booker Jul 02 '10 at 10:09
4

Well, i still don't understand the question completely, but if you just want to check, whether a given image may use transparency features, you can use this code:

Image img = Image.FromFile ( "...", true );
if ( (img.Flags & 0x2) != 0)
{
}

Though it won't help you to determine whether a given png file actually uses transparent features, it will indicate, that it has color type 4 or 6 (both support transparency) according to png file specification.

n535
  • 4,983
  • 4
  • 23
  • 28
  • Thanks, but this isn't helpful for me, since I need to know if the image contained is actually translucent not if it could be. The other answer above works, but I was hoping for something quicker, which this clearly is.... – kenny Apr 03 '10 at 10:49
  • 1
    This is quite useful. I have used it in combination with the code above so I only inspect the pixels of images that support transparency. – Tim Booker Jul 02 '10 at 12:25
  • @apathetic PNG with color type 3 supports transparency as well via tRNS chunk. – Kornel Mar 19 '12 at 17:47
  • 1
    This doesn't work for indexed images. They always seem to return Flag 2 even if they're not transparent. – Nyerguds Aug 16 '16 at 23:04
1

Here is an effective approach: Open the PNG in binary. Seek to byte 26 (25 if counting from zero). Evaluate the byte value of the char: 2 or lower => definitely opaque, 3 or higher => supports transparency. According to my findings, files generated by Photoshop only use 3 or higher when needed making this a reliable way to tell when using these. It appears that almost all of the files have 2 for opaque and 6 for alpha-blended. You may also consider checking the PNG and IHDR strings found in that general area to fool-proof your code.

Zdenek
  • 690
  • 3
  • 14
  • There doesn't seem to be a way to do this for paletted images; they have "3" there even if gimp sees the image as purely opaque. – Nyerguds Aug 16 '16 at 23:08
  • This method is only affirmative for the opaque answer. Otherwise you need to check the whole image. As for unnecessary false positives, you would be appalled to see how many GIFs have the transparent bits set without reason. I have recently coded the GIF transparency recognition in my web gallery to make the effects pretty. Then it had lots of false positives caused by stupid software making those pictures. I just edited the files in a hex editor (didn't want to recompress) and that fixed it. – Zdenek Aug 18 '16 at 16:01
  • BTW, re-consider using paletted PNGs. They have poor compression performance in indexed mode. – Zdenek Aug 18 '16 at 16:08
  • Heh. Were it that simple. The program I'm working on creates e-books (epub format) from entries on a storywriting website, and it makes sure to save and embed any images in it correctly. Because some e-readers have trouble with transparency I allow flattening these images on a white background, but since png writing in .Net is very unoptimized and often increases file size I want to check whether the re-save is actually needed. But I can hardly be held responsible for what kind of images people post into their stories ;) – Nyerguds Aug 18 '16 at 18:28
  • I recommend to you the `pngcrush` utility. It (almost always) finds the optimal compression parameters for a given image. No quality loss, although it does discard the ICC, so use it on sRGB files only. It often saves over 30% size when the file is from the dreaded Microsoft products. It just rarely happens that Photoshop produces a file that is just about 0.1% smaller than what pngcrush can do, so there are ways to improve. – Zdenek Aug 20 '16 at 07:46
  • Hmm. That's yet another 3rd party library to add to the program, though. For now, I'm going with detection; I [figured out quite a good way](http://stackoverflow.com/a/39013496/395685). – Nyerguds Aug 20 '16 at 23:52