The binary data of a picture can be downloaded from the.
ImageData is an object that contains pixel data and image width and height data.
? This is a picture we are going to decode next, but it is too small. Let's enlarge it for everyone to see. ?
Let's start with
The resulting arrayBuffer looks like this:
& ltstyle & gt
Form {
font-size: 12px;
}
Table tbody tr td {
Fill: .6 6rem .4rem
}
& lt/style & gt;
There are 4 bytes of data in each table cell, and each byte consists of 8 bits. 1 bit represents a number 0 or 1.
Binary data of PNG pictures must start with these 8 bytes: 0x89, 0x50, 0x4e, 0x47, 0x0d, 0, 0x 1A, 0.
0x means that this number is expressed in hexadecimal 16, 0x89, 0x50, 0x4e, 0x47, 0x0d, 0, 0x 1A, and 0 is converted into 137, 80, 78, 7 1, 65438.
The first 8 bytes of this picture meet the requirements of signature.
A data block contains all the data of an image. Data blocks can be divided into start information, data information and end information of data blocks.
The initial information of a data block contains two 32-bit numbers, which are converted into 8 bytes. The first four bytes will be combined into a 32-bit number, indicating the length of data information, and the last four bytes can be converted into text, indicating the type of data block.
We parse the start information of the data block from the eighth byte.
The data block is of IHDR type and has 13 bytes of data information.
The data information of IHDR is as follows:
As can be seen from the above information, this is a 2 * 2 pixel picture, and the color swatch is used as the color type. Each pixel consists of 1 color channel, and each color channel consists of 2 bits. Pixel data is not staggered, and after the filter function type is 0, it is compressed with deflate.
The end message includes a 4-byte CRC32 checksum. The decoder should calculate the CRC32 checksum according to the type of the data block and the data information of the data block, and compare it with the checksum in the end information. If they are equal, it is considered that the image data is transmitted correctly.
This data block is sRGB information, and its length is 1 byte.
The data block type starts with lowercase letters, indicating that the data block is an auxiliary data block, and the data block type starting with uppercase letters indicates a key data block.
SRGB represents the color space used by the picture.
We need to compare CRC32.
9 bytes of physical auxiliary data information.
PHYs data block represents the physical world size of the picture. As can be seen from the above data, this picture should be rendered as 2835 pixels per meter in the real world, with the same width and height.
Please compare CRC32.
12 bytes of PLTE sample data is the key data block.
The data contained in the color sample is RGB data, which is saved in the form of R, G and B, and one *** 12 byte represents four color scales. The sample information obtained is as follows:
[[255, 0, 0], [0, 255, 0], [0, 0, 255], [255, 255, 255]]
Please compare CRC32.
4 bytes of tRNS transparent data, which is an auxiliary data block.
This data block provides transparent information for color samples, and each byte represents the transparent information of a color sample. The combination of color samples and color samples is as follows:
[[255, 0, 0, 255], [0, 255, 0, 255], [0, 0, 255, 255], [255, 255, 255, 127]]
Please compare CRC32.
12 bytes of IDAT pixel data is the key data block.
Before parsing pixel data, we need to know how pixel data is encoded. Each row of pixels will be processed by a filter function first, and the filter function of each row of pixels can be different. Then the pixel data of all rows will be studied by deflate compression algorithm. So we need to decompress the pixel data here first, and use the zlib. interpolate () function directly here. On the browser, you can use the pako toolkit.
The decompressed pixel data are uint8array: 0,16,0, 176.
Next, we need to know carefully how each row of pixels is encoded in order to restore the above data to pixels.
A scan line contains data of a row of pixels in an image. We know that the height of this picture is 2, that is, there are 2 scan lines in the pixel data.
A scan line consists of a filter function flag of 1 byte and pixel information. Pixel information is arranged one by one, and there is no extra space in the middle. If the scan line length is not enough to fill the number of bytes, the last few bits will be filled. The structure of the scan line is as follows:
So we need to know the number of bits in each pixel before we can decode the scan line.
The color type of this picture is 3, so each pixel contains 1 color channels. And because the channel depth of the picture is 2, we know that each pixel is represented by 2 bits.
So we can decode the scan line.
Before compressing the scan lines, each scan line will be processed by a separate filter function to make the subsequent compression effect better.
In filter function type 0, there are five filter functions:
The filter function uses the values of three points, a, b and c, to calculate the current point x.
The filter function 0 in this picture means that the data in this picture is unfiltered. So all we have to do is keep the original data.
Here, the data in each pixel represents the color index of the pixel in the color sample. According to the color sample, we can restore the pixel information of the picture: [[255,0,0,255], [0,255,0,255], [255,255,255, 127]]
Please compare CRC32.
0 byte IEND image end data block, which is a key data block.
No.
Please compare CRC32.
The whole picture is decoded, and the final ImageData object is:
We successfully decoded a simple PNG picture, but I simplified many details:
You can see the source code to realize the above functions in GitHub.