libpng库的学习-关于头信息的部分

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.

posted @ 2017-03-01 21:17  层序圆儿  阅读(1118)  评论(0编辑  收藏  举报