man page地址:
http://www.libpng.org/pub/png/libpng-1.2.5-manual.html
png_sig_cmp函数用于判断这是不是一个png文件,用法是:
is_png = !png_sig_cmp(header, 0, number);
这里要传头8个字节,返回0则是png,非0则不是png
然后png_struct和png_info两个最关键的结构体需要初始化。有内置的初始化函数提供给你,使得哪怕我们是用动态库加载的方式也能正确使用。需要传入libpng版本,一个错误处理函数的handler,handler函数需要用的数据结构
1 png_structp png_ptr = png_create_read_struct 2 (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, 3 user_error_fn, user_warning_fn); 4 if (!png_ptr) 5 return (ERROR); 6 7 png_infop info_ptr = png_create_info_struct(png_ptr); 8 if (!info_ptr) 9 { 10 png_destroy_read_struct(&png_ptr, 11 (png_infopp)NULL, (png_infopp)NULL); 12 return (ERROR); 13 } 14 15 png_infop end_info = png_create_info_struct(png_ptr); 16 if (!end_info) 17 { 18 png_destroy_read_struct(&png_ptr, &info_ptr, 19 (png_infopp)NULL); 20 return (ERROR); 21 }
png_create_read_struct,png_create_info_struct实际就是这两个api
进阶用法:使用自己的mem allocation函数,可以通过调用
png_structp png_ptr = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, user_error_fn, user_warning_fn, (png_voidp) user_mem_ptr, user_malloc_fn, user_free_fn);
来进行,其实就是最后三个参数。
如果libpng库内部出现错误,那么是希望能用longjmp跳转回我们自己写的函数的。因此,我们需要调用setjmp并且把png_jmpbuf(png_ptr)传进去。
建立回调函数
png图片可以自定义用户数据?
high-level用户接口
读入图片数据阶段限定的图片操作如下表:
1 PNG_TRANSFORM_IDENTITY No transformation 2 PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to 3 8 bits 4 PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel 5 PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit 6 samples to bytes 7 PNG_TRANSFORM_PACKSWAP Change order of packed 8 pixels to LSB first 9 PNG_TRANSFORM_EXPAND Perform set_expand() 10 PNG_TRANSFORM_INVERT_MONO Invert monochrome images 11 PNG_TRANSFORM_SHIFT Normalize pixels to the 12 sBIT depth 13 PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA 14 to BGRA 15 PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA 16 to AG 17 PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity 18 to transparency 19 PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples
看起来七牛云的结果是运用了PNG_TRANSFORM_PACKING这个选项的,因为2,4,8bit的png他们都扩展到了8位
PNG_TRANSFORM_INVERT_ALPHA,原来透明和不透明的意义还可以变的呀。。。
png_read_png(png_ptr, info_ptr, png_transforms, NULL)
调用这个函数就读取png图片了,里面png_transforms就是上面的flag位或的结果
等价于png_read_info(), png_read_image(), png_read_end()三个api的总和。
png_bytep row_pointers[height];
row_pointers = png_get_rows(png_ptr, info_ptr);
这里就可以获取的图片raw data的指针了
如果我们调用了png_set_rows(),那么我们就有责任在外部释放row_pointers[];
如果我们是使用png_read_png()来读取图片的,那么库会帮你申请这部分内存,然后调用png_destroy_*()来释放相应资源。
low-level 读取接口
png_read_info(png_ptr, info_ptr);
这个api可以让你获取Png图片相关信息,但是不会读取图片数据。
查询图片信息接口
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); bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); filter_method = png_get_filter_type(png_ptr, info_ptr); compression_type = png_get_compression_type(png_ptr, info_ptr); interlace_type = png_get_interlace_type(png_ptr, info_ptr);
除了这些之外,
png_get_PLTE
png_get_pHYs
png_get_sCAL_s
这些接口同样重要,可以使你获取相关信息
如果你想获取PHYs里面的信息,也有下面的这些方法你可以使用
res_x = png_get_x_pixels_per_meter(png_ptr, info_ptr) res_y = png_get_y_pixels_per_meter(png_ptr, info_ptr) res_x_and_y = png_get_pixels_per_meter(png_ptr, info_ptr) res_x = png_get_x_pixels_per_inch(png_ptr, info_ptr) res_y = png_get_y_pixels_per_inch(png_ptr, info_ptr) res_x_and_y = png_get_pixels_per_inch(png_ptr, info_ptr) aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, info_ptr) (Each of these returns 0 [signifying "unknown"] if the data is not present or if res_x is 0; res_x_and_y is 0 if res_x != res_y) The data from the oFFs chunk can be retrieved in se
OFFs字段内的内容有下面的api提供
x_offset = png_get_x_offset_microns(png_ptr, info_ptr); y_offset = png_get_y_offset_microns(png_ptr, info_ptr); x_offset = png_get_x_offset_inches(png_ptr, info_ptr); y_offset = png_get_y_offset_inches(png_ptr, info_ptr); (Each of these returns 0 [signifying "unknown" if both x and y are 0] if the data is not present or if the chunk is present but the unit is the pixel)
PNG stores comments in keyword/text pairs
这句话的意思是:PNG里面也有类似于jpeg里面的exif键值对信息?one pair per chunk!
输入图片的变换
4 bit/pixel paletted or grayscale data will be returned 2 pixels/byte with the leftmost pixel in the high-order bits of the byte, unless png_set_packing() is called
如果一张png图片的位深为4,那么一个字节就存2个像素,靠左的像素就存储在字节的高位上,除非png_set_packing()函数被调用,这个函数是什么gui.
Data will be decoded into the supplied row buffers packed into bytes unless the library has been told to transform it into another format. For example, 4 bit/pixel paletted or grayscale data will be returned 2 pixels/byte with the leftmost pixel in the high-order bits of the byte, unless png_set_packing() is called. 8-bit RGB data will be stored in RGB RGB RGB format unless png_set_filler() is called to insert filler bytes, either before or after each RGB triplet. 16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant byte of the color value first, unless png_set_strip_16() is called to transform it to regular RGB RGB triplets, or png_set_filler() is called to insert filler bytes, either before or after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can be modified with png_set_filler() or png_set_strip_16().
The following code transforms grayscale images of less than 8 to 8 bits, changes paletted images to RGB, and adds a full alpha channel if there is transparency information in a tRNS chunk. This is most useful on grayscale images with bit depths of 2 or 4 or if there is a multiple-image viewing application that wishes to treat all images in the same way.
if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
These three functions are actually aliases for png_set_expand(), added in libpng version 1.0.4, with the function names expanded to improve code readability. In some future version they may actually do different things.
原文:http://www.cnblogs.com/derekxyw/p/6486002.html