PNG file structure analysis (I: Understand the PNG file storage format)
We all know that during the development of the mobile phone application program for j2's, we can use images in PNG format (even on some mobile phones, we can only use images in PNG format), although using images can add many highlights to our application, however, only images in PNG format are supported, which limits the possibility of further improvement (in fact, it should be said that the processing capability on the mobile phone platform is limited ). In MIDP2 or APIs provided by some vendors (such as NOKIA), drawPixels/getPixels methods are provided. These methods further improve the flexibility of developers in processing images. However, we need to use. 0 implementation of this type of method is still whimsical, so in order to achieve more advanced applications, we must fully tap the potential of PNG.
PNG file structure
For a PNG file, the file header is always described by fixed Bytes:
The first byte 0x89 is out of the ASCII character range to prevent some software from processing PNG files as text files. The remaining parts of the file are composed of more than three PNG data blocks (Chunk) in a specific order. Therefore, a standard PNG file structure should be as follows:
PNG data block (Chunk)
PNG defines two types of data blocks. One is critical chunk, which is a standard data block, and the other is ancillary chunks ), this is an optional data block. Key data blocks define four standard data blocks. Each PNG file must contain them. PNG read/write software must also support these data blocks. Although the PNG file specification does not require the PNG encoding/Decoding of optional data blocks, the specification advocates the support of optional data blocks.
The following table lists the types of data blocks in PNG. The key data blocks are distinguished by the dark background.
For the sake of simplicity, we assume that in the PNG file we use, the four data blocks are stored in the above Order, and only appear once.
Data Block Structure
In a PNG file, each data block consists of four parts:
The value in the CRC (cyclic redundancy check) field is calculated for the Data in the Chunk Type Code field and Chunk Data field. The specific CRC algorithm is defined in ISO 3309 and ITU-T V.42, and its value is calculated according to the following CRC code generation polynomial:
X32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
Next, let's take a look at the structure of each key data block in sequence.
Header chunk: it contains the basic information of the image data stored in the PNG file and needs to appear as the first data block in the PNG data stream, in addition, a PNG data stream can only contain one file header data block.
The file header data block consists of 13 bytes. Its format is shown in the following table.
Because we are studying PNG on the mobile phone, first let's take a look at the requirements of MIDP1.0 for the PNG images used:
BKGD cHRM gAMA hIST iCCP iTXt pHYs
SBIT sPLT sRGB tEXt tIME tRNS zTXt
For more information, see http://www.w3.org/TR/REC-png.html
The palette data block PLTE (palette chunk) contains color transformation data related to indexed-color image, which is only related to indexed color images, it must be placed before the image data chunk.
PLTE data blocks are the palette information that defines the image. PLTE can contain 1 ~ There are 256 palette information. Each palette information consists of three Bytes:
Therefore, the length of the color palette should be a multiple of 3. Otherwise, this will be an invalid color palette.
For indexed images, the color palette information is required. The color index of the palette starts from 0, followed by 1, 2 ......, The number of colors in the color palette cannot exceed the number of colors specified in the color depth (when the color depth is 4, the number of colors in the color palette cannot exceed 2 ^ 4 = 16). Otherwise, this will cause the PNG image to be invalid.
Real-color images and true-color images with alpha channel data can also have color palette data blocks, so that the non-real-color display program can use it to quantify image data and display the image.
Image data Block IDAT (image data chunk): It stores actual data and can contain multiple consecutive sequential image data blocks in the data stream.
IDAT stores the real data information of the image. Therefore, if we can understand the IDAT structure, we can easily generate PNG images.
Image trailer chunk: it indicates that a PNG file or data stream has ended and must be placed at the end of the file.
If we carefully observe the PNG file, we will find that the last 12 characters of the file should always look like this:
00 00 00 00 49 45 4E 44 AE 42 60 82
It is hard to understand that due to the definition of the data block structure, the length of the IEND data block is always 0 (00 00 00 00, unless information is manually added), and the data mark is always IEND (49 45 4E 44 ), therefore, the CRC code is always AE 42 60 82.
Instance research PNG
The following is an image generated by Fireworks. The image size is 8x8. To make it easier for you to watch, we can enlarge the image:
Use UltraEdit32 to open the file as follows:
00000000 ~ 00000007:
As you can see, the selected first 8 bytes are the identification of the PNG file.
The next part is the IHDR data block:
00000008 ~ 00000020:
00000021 ~ 0000002F:
Optional data block sBIT, color sampling rate, RGB all 256 (2 ^ 8 = 256)
00000030 ~ 00000062:
Here is the color palette Information
00000063 ~ 000000C5:
This part contains three data blocks of the pHYs and tExt types. Because it is not very important, it is not described in detail.
201700c0 ~ 000000F8:
The selected part is the IDAT data block.
The compressed data section in IDAT will be described in detail later.
000000F9 ~ 00000104:
IEND data blocks. As mentioned above
00 00 00 00 49 45 4E 44 AE 42 60 82
So far, we have been able to identify each data block from a PNG file. As PNG specifies that all other auxiliary data blocks except key data blocks are optional, with this standard, we can delete all the auxiliary data blocks to reduce the size of the PNG file. (Of course, it should be noted that the PNG format can save the layer and text information in the image. Once these auxiliary data blocks are deleted, the image will lose its original editability .)
The PNG file after the auxiliary data block is deleted. The file size is 147 bytes, and the original file size is 261 bytes. After the file size is reduced, the image content is not affected.
In fact, we can do some interesting things by changing the color value of the color palette, such as the flow of clouds/water waves, and the fade-in and fade-out effects of images. Here, provide a link for you to see, maybe more directly.
As mentioned above, IDAT data blocks are generated using the LZ77 compression algorithm. Due to the limitations of mobile phone processors, if we still use the LZ77 compression algorithm when generating IDAT data blocks, the efficiency will be greatly reduced. Therefore, only the LZ77 Algorithm without compression can be used for efficiency purposes. This article does not describe the implementation of the LZ77 algorithm, if you are interested in the java implementation of the LZ77 algorithm, you can refer to the following two sites:
PNG file format White Paper: http://www.w3.org/TR/REC-png.html
The few Chinese PNG format description: http://dev.gameres.com/Program/Visual/Other/PNGFormat.htm
RFC-1950 (ZLIB Compressed Data Format Specification): ftp://ds.internic.net/rfc/rfc1950.txt
RFC-1950 (DEFLATE Compressed Data Format Specification): ftp://ds.internic.net/rfc/rfc1951.txt
JAVA Implementation of LZ77 algorithm: http://jazzlib.sourceforge.net/
LZ77 algorithm JAVA implementation, including the j2-version: http://www.jcraft.com/jzlib/index.html
PNG file structure analysis (below: generate a PNG file on the mobile phone)
We have learned about the PNG storage format above. Therefore, to generate a PNG image, you only need to write the file according to the above data blocks.
(Because the IHDR and PLTE structures are very simple, here we will focus on the IDAT generation method, and the IHDR and PLTE data content will follow the above data content)
The problem is true. We know that for most graphics files, we can map the actual image content to a two-dimensional color array. For the above PNG files, because it uses a 16-color palette (actually 13 colors), The ing of images can be as follows:
(Color palette comparison chart)
In PNG Spec, it is pointed out that if the PNG file is not stored using the delimiter scan method, the data is stored by line (ScanLine). to distinguish the first line, PNG requires that 0 be added before each row to indicate differentiation. Therefore, the above image ing should be as follows:
In addition, it should be noted that because PNG stores images in order to save space, each row is stored by Bit, it is not the Byte we think. If you haven't forgotten it, the color depth in our IHDR data block indicates this. Therefore, in order to make up the IDAT required by PNG, our data needs to be changed to the following:
Finally, we can compress the data with LZ77 to obtain the correct IDAT content.
However, things are not that simple, because we are studying PNG on the mobile phone. If we need to compress LZ77 on the mobile phone, the time consumed can be imagined. Therefore, we have to try again to reduce the time consumed during compression.
Fortunately, LZ77 also provides a non-compression method (strange ?), Therefore, we only need to simply write data in a non-compressed manner, which wastes space, but returns time!
Well, let's take a look at how to compress LZ77 blocks without compression:
LEN is the index data length, which occupies two bytes. For our image, the first Scan Line contains five bytes (such as 0,203,169,135,101 of the first row ), therefore, the LEN value is 5 (byte/row) x 8 (ROW) = 40 (byte), the generated byte is 28 00 (the low byte is in front of), and NLEN is the complement of LEN, that is, NLEN = LEN ^ 0 xFFFF, so NLEN is D7 FF, Adler32 information is 24 A7 0B A4 (for specific algorithms, see the source program). Therefore, in this order, we generate an IDAT data block. Finally, we can write the IHDR, PLTE, IDAT, and IEND data blocks into the file to get the PNG file,
(The selected part is the generated "COMPRESSED" data)
So far, we have been able to convert the array into PNG images in the fastest time.
Generated PNG file:
Example (with source program)