PNG, the Portable Network Graphics format (Portable networks Graphic format,png), is derived from the unofficial "PNG's not GIF", which is a bitmap (bitmap file) storage format. When PNG is used to store grayscale images, the depth of the grayscale image can be as much as 16 bits, and when the color image is stored, the depth of the color image can be as many as 48 bits, and the alpha channel data of up to 16 bits can also be stored.
The PNG format has 8-bit, 24-bit, 32-bit three forms, where 8-bit PNG supports two different forms of transparency (index transparency and alpha transparency), 24-bit PNG does not support transparency, 32-bit PNG adds 24-bit transparent channels on a 8-bit basis, and therefore can exhibit level 256 transparency.
The numbers behind PNG8 and PNG24 are the color values that can be indexed and stored for this PNG format. "8″ represents 2 of the 8-time square is 256 colors, and 24 represents 2 of the 24-time side is about more than 16 million colors."
Format |
Maximum Color channel support |
Indexed color Editing support |
Transparent support |
PNG8 |
256 Index Color |
Support |
Supports setting specific index color to transparent color (Boolean transparent) Supports attaching 8-bit transparency to indexed colors (256 order alpha Transparent)
|
PNG24 |
Approx. 16 million colors |
Not supported |
Not supported |
PNG32 |
Approx. 16 million colors |
Not supported |
Supports 8-bit transparency (256 order alpha Transparent) |
The PNG file format preserves the following characteristics of the GIF file format:
- A color lookup table or color palette can be used to support 256 color images;
- Streaming read/write performance (streamability): Image File format allows continuous readout and writing of image data, which is well suited for generating and displaying images during communication;
- Successive approximation displays (progressive display): This feature enables the transmission of image files on the communication link while the image is displayed on the terminal, the entire contour is displayed and then gradually displays the details of the image, that is, to display the image with low resolution, and then gradually improve its resolution;
- Transparency (transparency): This performance allows some parts of the image to not be displayed to create some distinctive images.
- Auxiliary information (Ancillary information): This feature can be used to store some text annotation information in the image file;
- Independent of the computer hardware and software environment;
- Use lossless compression.
In the PNG file format, add features that are not in the following GIF file format:
- A true color image of 48 bits per pixel;
- A grayscale image of 16 bits per pixel;
- Alpha channels can be added for grayscale and true color graphs.
- Adding gamma information to the image;
- Use cyclic redundancy codes (cyclic redundancy CODE,CRC) to detect damage files;
- Speeding up the display of images by successive approximation;
- Standard read/write toolkit;
- You can store multiple images in one file.
File structure
A PNG image format file (or data flow) consists of a 8-byte PNG file signature (PNG files signature) domain and more than 3 data blocks (chunk) organized by a specific structure.
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.
Decimal number |
137 |
80 |
78 |
71 |
13 |
10 |
26 |
10 |
Hexadecimal number |
89 |
50 |
4e |
47 |
0d |
0a |
1a |
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 |
So we can see the judging function of the PNG format in-x:
bool Image::isPng(const unsigned char * data, ssize_t dataLen){ if (dataLen <= 8) { return false; } static const unsigned char PNG_SIGNATURE[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; return memcmp(PNG_SIGNATURE, data, sizeof(PNG_SIGNATURE)) == 0;}
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 |
Data block structure
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 |
IHDR
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 |
Length (Long) |
4 bytes |
Image width, in pixels |
Height |
4 bytes |
Image height, in pixels |
Bit depth |
1 bytes |
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 bytes |
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 bytes |
Compression method (LZ77 derivation algorithm) |
Filter method |
1 bytes |
Filter method |
Interlace method |
1 bytes |
Interlaced scanning method: 0: Non-interlaced scanning 1:ADAM7 (7-Times interlaced method developed by Adam M. Costello)
|
Plte
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.
The Plte data block is the palette information that defines the image, Plte can contain 1~256 palette information, each palette information consists of 3 bytes of RGB, so the color palette should be a multiple of 3, otherwise, this will be an illegal palette. The same color palette data block contains a maximum number of bytes of 768.
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.
IDAT
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.
Iend
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.
decoding of cocos2dx libpng
BOOL Image::initwithpngdata (const unsigned char * data, ssize_t datalen) {//length of bytes to check if it is a valid PNG file#define pngsigsize 8 BOOL ret = FALSE; Png_byte Header[pngsigsize] = {0}; PNG_STRUCTP png_ptr = 0; Png_infop info_ptr = 0; Do {//PNG headers len is 8 bytes cc_break_if (Datalen < pngsigsize); File header check//Check the data is PNG or not memcpy (header, data, pngsigsize); Cc_break_if (png_sig_cmp (header, 0, pngsigsize)); Initialize the PNG_STRUCTP type struct, LIBPNG internal use//init png_struct png_ptr = png_create_read_struct (png_libpng_ver_string, 0, 0, 0); CC_BREAK_IF (! png_ptr); Create image Information//init png_info info_ptr = png_create_info_struct (png_ptr); Cc_break_if (!info_ptr); #if (cc_target_platform! = Cc_platform_bada && Cc_target_platform! = cc_platform_nacl) Set exception Handling cc_break_if (setjmp (Png_jmpbuf (png_ptr))); #endif Use a custom callback function to set the libpng data source//Set the Read call back function Timagesource ImageSource; Imagesource.data = (unsigned char*) data; Imagesource.size = Datalen; Imagesource.offset = 0; PNG_SET_READ_FN (Png_ptr, &imagesource, Pngreadcallback); Read PNG header info//use underlying processing to read PNG data//Read PNG file Info png_read_info (png_ptr, info_ptr); Querying image information _width = Png_get_image_width (png_ptr, info_ptr); _height = Png_get_image_height (png_ptr, info_ptr); Png_byte bit_depth = png_get_bit_depth (png_ptr, info_ptr); Png_uint_32 Color_type = Png_get_color_type (png_ptr, info_ptr); Cclog ("Color type%u", color_type); Palette format PNG picture, converted to RGB888 pixel format//force palette images to be expanded to 24-bit RGB//It may include Alpha Ch Annel if (Color_type = = Png_color_type_palette) {Png_set_palette_to_rgb (png_ptr); }//pixel format is less than 1 bytes in length grayscale, convert it to a pixel format of 1 bytes per pixel//low-bit-depth grayscale images is to is expanded to 8 bits if (Color_type = = Png_color _type_gray && Bit_depth < 8) {bit_depth = 8; Png_set_expand_gray_1_2_4_to_8 (PNG_PTR); }//Extend the Trns block data information to the full alpha channel information//expand any trns chunk data into a fully alpha channel if (PNG_GET_VA Lid (png_ptr, info_ptr, Png_info_trns)) {Png_set_trns_to_alpha (png_ptr); }//Reduce the 16-bit input to 8-bit//reduce images with 16-bit samples to 8 bits if (bit_depth = = 16) { Png_set_strip_16 (PNG_PTR); }//Expanded earlier for grayscale, then take care of palette and RGB if (Bit_depth < 8) { Png_set_packing (PNG_PTR); }//update details of PNG data//Updated info Png_read_update_info (png_ptr, info_ptr); Bit_depth = Png_get_bit_depth (png_ptr, info_ptr); Color_type = Png_get_color_type (pnG_ptr, info_ptr); Switch (color_type) {case Png_color_type_gray: _renderformat = texture2d::P ixelformat::i8; Break Case Png_color_type_gray_alpha: _renderformat = texture2d::P ixelformat::ai88; Break Case PNG_COLOR_TYPE_RGB: _renderformat = texture2d::P ixelformat::rgb888; Break Case Png_color_type_rgb_alpha: _renderformat = texture2d::P ixelformat::rgba8888; Break Default:break; }//Read PNG information by line,//Read PNG data png_size_t rowbytes; png_bytep* row_pointers = (png_bytep*) malloc (sizeof (png_bytep) * _height); Gets the number of bytes per row of pixels rowbytes = png_get_rowbytes (png_ptr, info_ptr); Request memory Address _datalen = rowbytes * _height; _data = static_cast<unsigned char*> (malloc (_datalen * sizeof (unsigned char))); if (!_data) {if (row_pointers! = nullptr) {free (row_pointers); } break; } for (unsigned short i = 0; i < _height; ++i) {Row_pointers[i] = _data + i*rowbytes; }//Read PNG data png_read_image (PNG_PTR, row_pointers); End Read Data png_read_end (png_ptr, nullptr); Premultiplied Alpha for RGBA8888 if (Color_type = = Png_color_type_rgb_alpha) {//Pre-multiply alpha, using gradient a Lpha Premultipliedalpha (); } else {_haspremultipliedalpha = false; } if (row_pointers! = nullptr) {//Releases memory free (row_pointers) of the picture data; } ret = true; } while (0); if (png_ptr) {//release png_ptr png_destroy_read_struct (&png_ptr, (info_ptr)? &info_ptr:0, 0); } return ret;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
PNG image decoding