Search code examples
ioscocoa-touchcocoapng

Find out if PNG is 8 or 24 bits and alpha


Given a UIImage/NSImage or NSData instance, how do you find out programatically if a PNG is 8 bits or 24 bits? And if it has an alpha channel?

Is there any Cocoa/Cocoa Touch API that helps with this?

To avoid duplication, here is the non-programatic answer to the question, and here's a way to find out if an image is a PNG.


Solution

  • As a person who programmed for a long time on a J2ME platform, I know the PNG format very well. If you have the raw data as a NSData instance, looking up the information is very easy since the PNG format is very straightforward.

    See PNG Specification

    The PNG file starts with a signature and then it contains a sequence of chunks. You are interested only in the first chunk, IHDR.

    So, the code should be along the lines of:

    1. Skip the first 8 bytes (signature)
    2. Skip 4 bytes (IHDR chunk length)
    3. Skip 4 bytes (IHDR chunk type = "IHDR")
    4. Read IHDR

    Width: 4 bytes
    Height: 4 bytes
    Bit depth: 1 byte
    Color type: 1 byte
    Compression method: 1 byte
    Filter method: 1 byte
    Interlace method: 1 byte

    For alpha, you should also check if there is a tRNS (transparency) chunk in the file. To find a chunk, you can go with the following algorithm:

    1. Read chunk length (4 bytes)
    2. Read chunk type (4 bytes)
    3. Check chunk type whether it is the type we are looking for
    4. Skip chunk length bytes
    5. Skip 4 bytes of CRC
    6. Repeat

    EDIT:

    To find info about a UIImage instance, get its CGImage and use one of the CGImageGet... functions. It should be noted that All integer values in a PNG file are read in Big-endian format.