We all know that in the development of J2ME mobile applications, in the use of images, we can use images in PNG format (even on some phones, we can only use PNG format pictures), although the use of images can add a lot of bright spots for our application, however, Only images that support PNG format limit our chances of further playing (in fact, it is due to the limited processing power on the mobile platform). In MIDP2, or in the API provided by some vendors (such as Nokia), Drawpixels/getpixels methods are provided, which further enhance the developer's flexibility in handling images, however, MIDP2 is not yet fully popular today, we need to be in MIDP1. The realization of such a method in 0 is also whimsical, so we must fully exploit the potential of PNG in order to achieve more advanced applications.
File structure of PNG
For a PNG file, the header of the file is always described by a bit-fixed byte:
|Decimal number||137 80 78 71 13 10 26 10|
|Hexadecimal number||4E 0D 0A 1 a 0A|
The first byte 0x89 is beyond the range of ASCII characters, in order to prevent some software from treating PNG files as text files. The remainder of the file is made up of more than 3 PNG data blocks (Chunk) in a specific order, so a standard PNG file structure should look like this:
|PNG file Flags||PNG data block||......||PNG data block|
PNG data block (Chunk)
PNG defines two types of data blocks, one of which is called the Critical data Block (critical chunk), which is the standard block of data, and the other is called the auxiliary data Block (ancillary chunks), which is an optional block of data. Critical data blocks define 4 standard blocks, each of which must contain them, and PNG read-write software must support them. Although the PNG file specification does not require the PNG compiler to encode and decode an optional block of data, the specification advocates support for optional blocks of data.
The table below is the category of data blocks in PNG, where we use a dark background to differentiate the key chunks.
|Data blocks in the PNG file format|
|Data block symbols||Data block name||Majority Data block||Optional No||Location restrictions|
|IHDR||File header data block||Whether||Whether||First piece|
|CHRM||Base color and white point data block||Whether||Is||Before Plte and Idat|
|GAMA||Image Gamma Data block||Whether||Is||Before Plte and Idat|
|Sbit||Sample valid bit data block||Whether||Is||Before Plte and Idat|
|Plte||Palette Data Block||Whether||Is||Before the Idat|
|Bkgd||Background color data block||Whether||Is||Before Idat after Plte|
|HIST||Image histogram data block||Whether||Is||Before Idat after Plte|
|Trns||Image Transparent Data block||Whether||Is||Before Idat after Plte|
|OFFs||(Dedicated public data block)||Whether||Is||Before the Idat|
|PHYs||Physical pixel size data block||Whether||Is||Before the Idat|
|SCAL||(Dedicated public data block)||Whether||Is||Before the Idat|
|IDAT||Image data Block||Is||Whether||Continuous with other Idat|
|Time||Image last modified time data block||Whether||Is||Unlimited|
|TEXt||Text Information data block||Is||Is||Unlimited|
|Ztxt||Compressing text data blocks||Is||Is||Unlimited|
|FRAc||(Dedicated public data block)||Is||Is||Unlimited|
|Gifg||(Dedicated public data block)||Is||Is||Unlimited|
|GIFt||(Dedicated public data block)||Is||Is||Unlimited|
|Gifx||(Dedicated public data block)||Is||Is||Unlimited|
|Iend||Image End Data||Whether||Whether||Last data block|
For the sake of simplicity, let's assume that in the PNG file we're using, the 4 blocks are stored in the order above and only once.
Data block structure
In a PNG file, each chunk consists of 4 parts, as follows:
|Name||Number of bytes||Description|
|Length (Long)||4 bytes||Specifies the length of the data field in the data block, which is not longer than (231-1) bytes|
|Chunk Type code (data block type code)||4 bytes||Block type codes are made up of ASCII letters (A-Z and A-Z)|
|Chunk data (block data)||Variable length||Stores data specified according to chunk Type code|
|CRC (cyclic redundancy detection)||4 bytes||Storage of cyclic redundancy codes to detect errors|
The values in the CRC (cyclic redundancy check) field are computed for the data in the chunk Type code domain and the chunk database domain. The CRC-specific algorithm is defined in ISO 3309 and ITU-T v.42, and its value is calculated as a polynomial generated by the following CRC code:
Let's look at the structure of each key block in turn.
Header chunk: It contains basic information about the image data stored in the PNG file and is to appear in the PNG data stream as the first block of data, and only one file header block in a PNG data stream. IHDR
The file header data block consists of 13 bytes, which are formatted as shown in the following table.
|Name of the domain||Number of bytes||Description|
|Width||4 bytes||Image width, in pixels|
|Height||4 bytes||Image height, in pixels|
|Bit depth||1 byte||Image depth:
Indexed color images: 1,2,4 or 8
Grayscale Image: 1,2,4,8 or 16
True Color Image: 8 or 16
|ColorType||1 byte||Color type:
0: Grayscale image, 1,2,4,8 or 16
2: True Color image, 8 or 16
3: Indexed color image, 1,2,4 or 8
4: Grayscale image with alpha channel data, 8 or 16
6: True color image with alpha channel data, 8 or 16
|Compression method||1 byte||Compression method (LZ77 derivation algorithm)|
|Filter method||1 byte||Filter method|
|Interlace method||1 byte||Interlaced scanning method:
0: Non-interlaced scanning
1:ADAM7 (7-Times interlaced method developed by Adam M. Costello)
Since we're looking at PNG on the phone, let's first look at MIDP1.0 's requirements for the PNG image used:
BKGD CHRM GAMA HIST ICCP itxt pHYs
Sbit SPLT SRGB tEXt time Trns ztxt
For more information, refer to the http://www.w3.org/TR/REC-png.html
Palette Data Block Plte (palette chunk) contains color transform data related to indexed color images (indexed-color image), which is only relevant to indexed color images and is placed before image data chunk.
Plte data blocks are palette information that defines an image, and Plte can contain 1~256 palette information, each of which consists of 3 bytes:
0 = black, 255 = red
0 = black, 255 = Green
0 = black, 255 = Blue
Therefore, the length of the palette should be a multiple of 3, otherwise it would be an illegal palette.
For indexed images, palette information is required, the color index of the palette is numbered starting with 0, then 1, 2 ..., the color of the palette cannot exceed the number of colors specified in the color depth (as deep as 4, the number of colors in the palette may not exceed 2^4=16), otherwise this will result in the PNG image being illegal.
True color images and true color images with alpha channel data can also have a palette of data blocks, which are designed to allow non-true color display programs to quantify image data to display the image.
Image data Block Idat: It stores the actual data, which can contain multiple sequential sequential image blocks in the data flow.
Idat stores the real data information of the image, so if you can understand the structure of the idat, we can easily generate PNG images.
Image end Data iend (Image trailer Chunk): It is used to mark a PNG file or the data stream has ended and must be placed at the end of the file.
If we look closely at the PNG file, we will find that the 12 characters at the end of the file should always look like this:
4E (42 60 82) for the XX
It is not difficult to understand that, due to the definition of the block structure, the length of the iend data block is always 0 (00 00 00 00, unless the information is artificially added), the data identification is always iend (4E 44), therefore, CRC code is always AE 42 60 82.
Case study png
The following is an image generated by fireworks, the image size is 8*8, in order to facilitate viewing, we will enlarge the image:
Open the file using UltraEdit32, as follows:
As you can see, the selected header 8 bytes is the identity of the PNG file.
The next place is the IHDR data block:
Optional data block sbit, color sampling rate, RGB are 256 (2^8=256)
Here is the palette information
This section contains the Phys, text two types of data blocks a total of 3 blocks, because it is not very important, and therefore no longer described in detail.
The selected section above is the IDAT data block
The compressed data section in Idat is described in more detail later.
Iend data blocks, which, as mentioned above, usually should be
4E (42 60 82) for the XX
At this point, we have been able to identify each block of data from a PNG file. Since PNG specifies that other auxiliary blocks are optional except for critical chunks, with this standard, we can reduce the size of PNG files by removing all of the auxiliary data blocks. (Of course, it is important to note that the PNG format can save information such as layers, text, and so on in the image, and once these secondary blocks are deleted, the image loses its original editable character.) ）
The PNG file after the secondary data block is deleted, the file size is now 147 bytes, the original file size is 261 bytes, the file size is reduced, and the contents of the image are not affected.
In fact, we can change the color of the color palette to do some interesting things, such as the flow of clouds/water to achieve the effect of fading image, and so on, give a link to everyone to see maybe more direct:http://blog.csdn.net/ Flyingghost/archive/2005/01/13/251110.aspx, I write this article is inspired by this article.
As mentioned above, the IDAT data block is generated using the LZ77 compression algorithm, due to the ability of the mobile phone processor, so if we are generating IDAT data block still use LZ77 compression algorithm, will be inefficient, so for efficiency, only use the uncompressed LZ77 algorithm, About the implementation of the LZ77 algorithm, this article does not intend to delve into, if you are interested in the Java implementation of the LZ77 algorithm, you can refer to the following two sites:
PNG file Structure analysis (bottom: PNG file generated on phone)
We have already learned about PNG storage format, so it is only necessary to write a PNG image to the above data block.
(because the structure of IHDR and Plte is very simple, so here we just focus on the Idat generation method, IHDR and Plte data content are used in the above data content)
The problem is this, we know, for most graphics files, we can map the actual image content into a two-dimensional color array, for the above PNG file, because it is a 16-color palette (actually 13 colors), therefore, the image map can be as follows:
(Palette contrast chart)
PNG spec indicates that if the PNG file is not stored in an interlaced method, then the data is stored in line (scanline), in order to distinguish the first line, the PNG rule in front of each line is preceded by 0 to differentiate, therefore, the image map above should be as follows:
Also, it is important to note that since PNG stores images in order to save space, each row is stored by bit (bit), not the byte (byte) we imagined, and if you do not forget, the color depth in our IHDR data block indicates this, so To get the Idat needed for PNG, our data is changed to the following:
Finally, we can get the correct content of Idat by LZ77 compressing the data.
However, things are not so simple, because we are looking at the PNG on the phone, if we need to complete the LZ77 compression work on the phone, the time is conceivable, so we have to find ways to reduce the time spent in compression.
Fortunately, LZ77 also offers uncompressed compression (odd?). , so we just need to simply use the uncompressed way to write the data, so that although wasted space, but back to the time!
OK, let's take a look at how to make the uncompressed LZ77 compression block:
|0~2||Compression information, fixed to 0x78, 0xDA, 0x1|
|3~6||Len and nlen information for compressed blocks|
|Last 4 bytes||Adler32 Information|
The Len is the length of the data, occupies two bytes, for our image, the first scan line contains 5 bytes (such as the first row of 0, 203, 169, 135, 101), so Len has a value of 5 (Bytes/Line) * 8 (ROW) = 40 (bytes), generating byte 28 00 (low byte in front), Nlen is Len's complement, that is Nlen = len ^ 0xFFFF, so nlen for D7 Ff,adler32 information for the A7 0B A4 (specific algorithm see source program), so in order to do so, we generate IDAT data block, finally, We write the IHDR, Plte, Idat, and iend data blocks to the file, and we get the PNG file,
(The selected section is the generated "compressed" data)
So far, we've been able to convert arrays to PNG images in the quickest possible time.
PNG file Format White paper:http://www.w3.org/TR/REC-png.html
The few Chinese PNG format descriptions: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 the LZ77 algorithm:http://jazzlib.sourceforge.net/
Java implementation of the LZ77 algorithm, including the J2ME version:http://www.jcraft.com/jzlib/index.html
"Go" PNG file format