📄 libpng.3
字号:
See your documentation of setjmp/longjmp for your compiler for moreinformation on setjmp/longjmp. See the discussion on libpng errorhandling in the Customizing Libpng section below for more informationon the libpng error handling. If an error occurs, and libpng longjmp'sback to your setjmp, you will want to call png_destroy_read_struct() tofree any memory. if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return (ERROR); }If you would rather avoid the complexity of setjmp/longjmp issues,you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which caseerrors will result in a call to PNG_ABORT() which defaults to abort().Now you need to set up the input code. The default for libpng is touse the C function fread(). If you use this, you will need to pass avalid FILE * in the function png_init_io(). Be sure that the file isopened in binary mode. If you wish to handle reading data in anotherway, you need not call the png_init_io() function, but you must thenimplement the libpng I/O methods discussed in the Customizing Libpngsection below. png_init_io(png_ptr, fp);If you had previously opened the file and read any of the signature fromthe beginning in order to see if this was a PNG file, you need to letlibpng know that there are some bytes missing from the start of the file. png_set_sig_bytes(png_ptr, number);.SS Setting up callback codeYou can set up a callback function to handle any unknown chunks in theinput stream. You must supply the function read_chunk_callback(png_ptr ptr, png_unknown_chunkp chunk); { /* The unknown chunk structure contains your chunk data, along with similar data for any other unknown chunks: */ png_byte name[5]; png_byte *data; png_size_t size; /* Note that libpng has already taken care of the CRC handling */ /* put your code here. Search for your chunk in the unknown chunk structure, process it, and return one of the following: */ return (-n); /* chunk had an error */ return (0); /* did not recognize */ return (n); /* success */ }(You can give your function another name that you like instead of"read_chunk_callback")To inform libpng about your function, use png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, read_chunk_callback);This names not only the callback function, but also a user pointer thatyou can retrieve with png_get_user_chunk_ptr(png_ptr);If you call the png_set_read_user_chunk_fn() function, then all unknownchunks will be saved when read, in case your callback function will needone or more of them. This behavior can be changed with thepng_set_keep_unknown_chunks() function, described below.At this point, you can set up a callback function that will becalled after each row has been read, which you can use to controla progress meter or the like. It's demonstrated in pngtest.c.You must supply a function void read_row_callback(png_ptr ptr, png_uint_32 row, int pass); { /* put your code here */ }(You can give it another name that you like instead of "read_row_callback")To inform libpng about your function, use png_set_read_status_fn(png_ptr, read_row_callback);.SS Width and height limitsThe PNG specification allows the width and height of an image to be aslarge as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns.Since very few applications really need to process such large images,we have imposed an arbitrary 1-million limit on rows and columns.Larger images will be rejected immediately with a png_error() call. Ifyou wish to override this limit, you can use png_set_user_limits(png_ptr, width_max, height_max);to set your own limits, or use width_max = height_max = 0x7fffffffLto allow all valid dimensions (libpng may reject some very large imagesanyway because of potential buffer overflow conditions).You should put this statement after you create the PNG structure andbefore calling png_read_info(), png_read_png(), or png_process_data().If you need to retrieve the limits that are being applied, use width_max = png_get_user_width_max(png_ptr); height_max = png_get_user_height_max(png_ptr);.SS Unknown-chunk handlingNow you get to set the way the library processes unknown chunks in theinput PNG stream. Both known and unknown chunks will be read. Normalbehavior is that known chunks will be parsed into information invarious info_ptr members while unknown chunks will be discarded. Thisbehavior can be wasteful if your application will never use some knownchunk types. To change this, you can call: png_set_keep_unknown_chunks(png_ptr, keep, chunk_list, num_chunks); keep - 0: default unknown chunk handling 1: ignore; do not keep 2: keep only if safe-to-copy 3: keep even if unsafe-to-copy You can use these definitions: PNG_HANDLE_CHUNK_AS_DEFAULT 0 PNG_HANDLE_CHUNK_NEVER 1 PNG_HANDLE_CHUNK_IF_SAFE 2 PNG_HANDLE_CHUNK_ALWAYS 3 chunk_list - list of chunks affected (a byte string, five bytes per chunk, NULL or '\0' if num_chunks is 0) num_chunks - number of chunks affected; if 0, all unknown chunks are affected. If nonzero, only the chunks in the list are affectedUnknown chunks declared in this way will be saved as raw data onto alist of png_unknown_chunk structures. If a chunk that is normallyknown to libpng is named in the list, it will be handled as unknown,according to the "keep" directive. If a chunk is named in successiveinstances of png_set_keep_unknown_chunks(), the final instance willtake precedence. The IHDR and IEND chunks should not be named inchunk_list; if they are, libpng will process them normally anyway.Here is an example of the usage of png_set_keep_unknown_chunks(),where the private "vpAg" chunk will later be processed by a user chunkcallback function: png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'}; #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) png_byte unused_chunks[]= { 104, 73, 83, 84, (png_byte) '\0', /* hIST */ 105, 84, 88, 116, (png_byte) '\0', /* iTXt */ 112, 67, 65, 76, (png_byte) '\0', /* pCAL */ 115, 67, 65, 76, (png_byte) '\0', /* sCAL */ 115, 80, 76, 84, (png_byte) '\0', /* sPLT */ 116, 73, 77, 69, (png_byte) '\0', /* tIME */ }; #endif ... #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) /* ignore all unknown chunks: */ png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0); /* except for vpAg: */ png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1); /* also ignore unused known chunks: */ png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks, (int)sizeof(unused_chunks)/5); #endif.SS The high-level read interfaceAt this point there are two ways to proceed; through the high-levelread interface, or through a sequence of low-level read operations.You can use the high-level interface if (a) you are willing to readthe entire image into memory, and (b) the input transformationsyou want to do are limited to the following set: PNG_TRANSFORM_IDENTITY No transformation PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to 8 bits PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit samples to bytes PNG_TRANSFORM_PACKSWAP Change order of packed pixels to LSB first PNG_TRANSFORM_EXPAND Perform set_expand() PNG_TRANSFORM_INVERT_MONO Invert monochrome images PNG_TRANSFORM_SHIFT Normalize pixels to the sBIT depth PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA to BGRA PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA to AG PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity to transparency PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples(This excludes setting a background color, doing gamma transformation,dithering, and setting filler.) If this is the case, simply do this: png_read_png(png_ptr, info_ptr, png_transforms, NULL)where png_transforms is an integer containing the bitwise OR ofsome set of transformation flags. This call is equivalent to png_read_info(),followed the set of transformations indicated by the transform mask,then png_read_image(), and finally png_read_end().(The final parameter of this call is not yet used. Someday it might pointto transformation parameters required by some future input transform.)You must use png_transforms and not call any png_set_transform() functionswhen you use png_read_png().After you have called png_read_png(), you can retrieve the image datawith row_pointers = png_get_rows(png_ptr, info_ptr);where row_pointers is an array of pointers to the pixel data for each row: png_bytep row_pointers[height];If you know your image size and pixel size ahead of time, you can allocaterow_pointers prior to calling png_read_png() with if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) png_error (png_ptr, "Image is too tall to process in memory"); if (width > PNG_UINT_32_MAX/pixel_size) png_error (png_ptr, "Image is too wide to process in memory"); row_pointers = png_malloc(png_ptr, height*png_sizeof(png_bytep)); for (int i=0; i<height, i++) row_pointers[i]=png_malloc(png_ptr, width*pixel_size); png_set_rows(png_ptr, info_ptr, &row_pointers);Alternatively you could allocate your image in one big block and definerow_pointers[i] to point into the proper places in your block.If you use png_set_rows(), the application is responsible for freeingrow_pointers (and row_pointers[i], if they were separately allocated).If you don't allocate row_pointers ahead of time, png_read_png() willdo it, and it'll be free'ed when you call png_destroy_*()..SS The low-level read interfaceIf you are going the low-level route, you are now ready to read allthe file information up to the actual image data. You do this with acall to png_read_info(). png_read_info(png_ptr, info_ptr);This will process all chunks up to but not including the image data..SS Querying the info structureFunctions are used to get the information from the info_ptr once ithas been read. Note that these fields may not be completely filledin until png_read_end() has read the chunk data following the image. png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); width - holds the width of the image in pixels (up to 2^31). height - holds the height of the image in pixels (up to 2^31). bit_depth - holds the bit depth of one of the image channels. (valid values are 1, 2, 4, 8, 16 and depend also on the color_type. See also significant bits (sBIT) below). color_type - describes which color/alpha channels are present. PNG_COLOR_TYPE_GRAY (bit depths 1, 2, 4, 8, 16) PNG_COLOR_TYPE_GRAY_ALPHA (bit depths 8, 16) PNG_COLOR_TYPE_PALETTE (bit depths 1, 2, 4, 8) PNG_COLOR_TYPE_RGB (bit_depths 8, 16) PNG_COLOR_TYPE_RGB_ALPHA (bit_depths 8, 16) PNG_COLOR_MASK_PALETTE PNG_COLOR_MASK_COLOR PNG_COLOR_MASK_ALPHA filter_method - (must be PNG_FILTER_TYPE_BASE for PNG 1.0, and can also be PNG_INTRAPIXEL_DIFFERENCING if the PNG datastream is embedded in a MNG-1.0 datastream) compression_type - (must be PNG_COMPRESSION_TYPE_BASE for PNG 1.0) interlace_type - (PNG_INTERLACE_NONE or PNG_INTERLACE_ADAM7) Any or all of interlace_type, compression_type, of filter_method can be NULL if you are not interested in their values. channels = png_get_channels(png_ptr, info_ptr); channels - number of channels of info for the color type (valid values are 1 (GRAY, PALETTE), 2 (GRAY_ALPHA), 3 (RGB), 4 (RGB_ALPHA or RGB + filler byte)) rowbytes = png_get_rowbytes(png_ptr, info_ptr); rowbytes - number of bytes needed to hold a row signature = png_get_signature(png_ptr, info_ptr); signature - holds the signature read from the file (if any). The data is kept in the same offset it would be if the whole signature were read (i.e. if an application had already read in 4 bytes of signature before starting libpng, the remaining 4 bytes would be in signature[4] through signature[7] (see png_set_sig_bytes())). width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -