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.
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:
Skip the first 8 bytes (signature)
Skip 4 bytes (IHDR chunk length)
Skip 4 bytes (IHDR chunk type = "IHDR")
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:
Read chunk length (4 bytes)
Read chunk type (4 bytes)
Check chunk type whether it is the type we are looking for
Skip chunk length bytes
Skip 4 bytes of CRC
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.
Related
So I want to extract data from png file in which those params are always the same:
Bit depth: 8
Color type: 6
Compression method: 0
Filter method: 0
Interlace method: 0
What I want is array of all pixels as rgba. I already have IDAT chunk extracted but I really don't know what I should do next.
According to libpng I have to reverse creating image data process.
As I understand, I have to decompress chunk content, reverse the filtering process and I should get truecolor pixels representation but I really don't know how to decompress it and reverse the filtering process.
Above is the data to read the picture using iOS SDK,
00000004 43674249 50002006 2cb87766
are extra bytes.
Does anyone know what these bytes are?
Your image is not a standard PNG according to the official specifications. The bytes you point out form a valid PNG chunk:
00000004 Data length
43674249 Block ID "CgBI"
50002006 4 bytes of proprietary information
2CB87766 CRC checksum of the data block
but the location and the indicated type of the chunk are invalid for a conforming PNG image.
This indicates the image is processed with Apple's modified version of pngcrush. See http://iphonedevwiki.net/index.php/CgBI_file_format#Differences_from_PNG for non-official information on the block contents and other deviations from the official specification.
Is it possible to use a Three.js BufferAttribute with unsigned bytes instead of floats?
I am rendering a point cloud using the Potree library, which is based on Three.js, and I am looking for ways to save gpu memory. The library's binary format uses 3 * 4 bytes for each point's position, 4 * 1 byte for RGBA and 2 * 1 byte for the normal (oct16 encoded), for a total of 18 bytes per point. The (perceived) problem is that the data is unpacked on the client side and everything is represented as a 32bit float, resulting in 36 bytes per point. Why not use the data without converting it to floats first? Is this a limitation of Three.js or an issue of Potree? And if the problem is on Three's side, are there good reasons behind it? (e.g. browser compatibility)
Coming from OpenGL and bare-bones WebGL programming, it seems really wasteful to use almost 2x more memory than needed...
I was reading BMP file in hex editor while discovered something odd. Two first letters "BM" are written in order, however the next word(2B), which is means file size, is 36 30 in hex. Actual size is 0x3036. I've noticed that other numbers are stored the same way.
I'm also using MARS MIPS emulator which can display memory by words. String in.bmp is stored as b . n i / \0 p m.
Why data isn't stored continuously?
It depends not on the data itself but on how you store this data: per byte, per word (2 bytes, usually), or per long (4 bytes -- again, usually). As long as you store data per byte you don't see anything unusual; data appears "continuous". However, with longer units, you are subject to endianness.
It appears your emulator is assuming all words need to have their bytes reversed; and you can see in your example that this assumption is not always valid.
As for the BM "magic" signature: it's not meant to be read as a word value "BM", but rather as "first, a single byte B, then a single byte M". All next values are written in little-endian order, not only 'exchanging' your 36 and 30 but also the 2 zeroes 'before' (or 'after') (the larger values in the BMP header are of 4 bytes long type).
I'm parsing an Jpeg/JFIF file and I noticed that after the SOI (0xFF D8) I parse the different "streams" starting with 0xFFXX (where XX is a hexadecimal number) until I find the EOI (0XFFD9). Now the structure of the diffrent chunks is:
APP0 marker 2 Bytes
Length 2 Bytes
Now when I parse the a chunk I parse until i reach the length written in the 2 Bytes of the length field. After that I thought I would immediately find another Marker, followed by a length for the next chunk. According to my parser that is not always true, there might be data between the chunks. I couldn't find out what that data is, and if it is relevant to the image. Do you have any hints what this could be and how to interpret those bytes?
I'm lost and would be happy if somebody could point me in the correct direction. Thanks in advance
I've recently noticed this too. In my case it's an APP2 chunk which is the ICC profile which doesn't contain the length of the chunk.
In fact so far as I can see the length of the chunk needn't be the first 2 bytes (though it usually is).
In JFIF all 0xFF bytes are replaced with 0xFF 0x00 in the data section, so it should just be a matter of calculating the length from that. I just read until I hit another header, however I've noticed that sometimes (again in the ICC profile) there are byte sequences which don't make sense such as 0xFF 0x6D, so I may still be missing something.