Libpng技术简介通俗解释识别图片的一种程序语言定义libpng是一套免费的、公开源代码的程序库,支持对PNG图形文件的创建、读写等操作。判断文件是否是png文件创建和分配Png_struct和png_info释放分配的空间关闭文件打开png文件进行相关操作参考文献1、libpng入门_百度文库、libpng-1.4.0-manual_百度文库=view3、libpng说明_百度文库=view4、使用libpng读取PNG图片像素数据-workingdog的专栏-博客频道-CSDN.NET、libpng用法,读写PNG图像-tiny_dust的日志-网易博客附录:使用libpng解码png图片程序设计(以下是附录全文)libpng的数据结构png_structp变量是在libpng初始化的时候创建,由libpng库内部使用,代表libpng的是调用上下文,库的使用者不应该对这个变量进行访问。调用libpng的API的时候,需要把这个参数作为第一个参数传入。png_infop变量,初始化完成libpng之后,可以从libpng中获得该类型变量指针。这个变量保存了png图片数据的信息,库的使用者可以修改和查阅该变量,比如:查阅图片信息,修改图片解码参数。在早期的版本中直接访问该变量的成员,最新的版本建议是通过API来访问这些成员。libpng的使用0、判断是否为libpng数据这步是可选的,在利用libpng继续数据处理之前,可以调用png_sig_cmp函数来检查是否为png数据,请参阅libpng手册了解详细内容。1、初始化libpng1:/*Createandinitializethepng_structwiththedesirederrorhandler2:*functions.Ifyouwanttousethedefaultstderrandlongjumpmethod,3:*youcansupplyNULLforthelastthreeparameters.Wealsosupplythe4:*thecompilerheaderfileversion,sothatweknowiftheapplication5:*wascompiledwithacompatibleversionofthelibrary.REQUIRED6:*/7:png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,8:png_voidpuser_error_ptr,user_error_fn,user_warning_fn);初始化libpng的时候,用户可以指定自定义错误处理函数,如果不需要指定自定义错误处理函数,则传NULL即可。png_create_read_struct函数返回一个png_structp变量,前面已经提到该变量不应该被用户访问,应该在以后调用libpng的函数时传递给libpng库。如果你需要提供自定义内存管理模块则需要调用png_create_read_struct_2来完成对libpng的初始化:1:png_structppng_ptr=png_create_read_struct_22:(PNG_LIBPNG_VER_STRING,(png_voidp)user_error_ptr,3:user_error_fn,user_warning_fn,(png_voidp)4:user_mem_ptr,user_malloc_fn,user_free_fn)2、创建图像信息——png_infop变量1:/*Allocate/initializethememoryforimageinformation.REQUIRED.*/2:info_ptr=png_create_info_struct(png_ptr);3:if(info_ptr==NULL)4:{5:png_destroy_read_struct(&png_ptr,png_infopp_NULL,png_infopp_NULL);6:return(ERROR);7:}如前面所说,用户将会通过png_infop变量来获得图片的信息,设置图片解码参数等。3、设置错误返回点上文libjpeg解码jpeg图片中提到用setjmp/longjmp函数来处理异常。libpng库默认集成这种机制来完成异常处理,如下代码初始化错误返回点:1:/*Seterrorhandlingifyouareusingthesetjmp/longjmpmethod(thisis2:*thenormalmethodofdoingthingswithlibpng).REQUIREDunlessyou3:*setupyourownerrorhandlersinthepng_create_read_struct()earlier.4:*/5:if(setjmp(png_jmpbuf(png_ptr)))6:{7:/*Freeallofthememoryassociatedwiththepng_ptrandinfo_ptr*/8:png_destroy_read_struct(&png_ptr,&info_ptr,png_infopp_NULL);9:/*Ifwegethere,wehadaproblemreadingthefile*/10:return(ERROR);11:}正如上面注释中提到情况,只有在初始化libpng的时候未指定用户自定义的错误处理函数情况下,才需要设置错误返回点。如果设置了用户自定义的错误处理函数,libpng将会调用用户自定义错误处理函数,而不会返回到这个调用点。当libpng库出现错误的时候,libpng将会自动调用longjmp函数返回到这个点。在这个点我们可以进行必要的清理工作。4、设置libpng的数据源我在上文《图像解码之一——使用libjpeg解码jpeg图片》中提到,一个好的代码库应该能够运行用户输入各式各样的数据,而不能把输入数据定死。libpng在这方面做得非常的好,它提供了默认的文件输入流的支持,并且提供了用户自定义回调函数来完成png数据的输入。对于文件流数据数据设置代码如下:1:/*OneofthefollowingI/OinitializationmethodsisREQUIRED*/2:defstreams/*PNGfileI/Omethod1*/3:/*SetuptheinputcontrolifyouareusingstandardCstreams*/4:png_init_io(png_ptr,fp);用户自定义回调函数设置libpng数据源的代码如下:1:/*Ifyouareusingreplacementreadfunctions,insteadofcalling2:*png_init_io()hereyouwouldcall:3:*/4:png_set_read_fn(png_ptr,(void*)user_io_ptr,user_read_fn);5:/*whereuser_io_ptrisastructureyouwantavailabletothecallbacks*/如果你已经使用png_sig_cmp函数来检查了png数据,需要调用png_set_sig_bytes函数来告诉libpng库,这样库处理数据的时候将会跳过相应的数据,具体请参考libpng手册。5、png图像处理这步有两种设置方案一种称为高层处理,一种称为底层处理。高层处理当用户的内存足够大,可以一次性读入所有的png数据,并且输出数据格式为如下libpng预定义数据类型时,可以用高层函数,下libpng预定义数据类型为:PNG_TRANSFORM_IDENTITYNotransformationPNG_TRANSFORM_STRIP_16Strip16-bitsamplesto8bitsPNG_TRANSFORM_STRIP_ALPHADiscardthealphachannelPNG_TRANSFORM_PACKINGExpand1,2and4-bitsamplestobytesPNG_TRANSFORM_PACKSWAPChangeorderofpackedpixelstoLSBfirstPNG_TRANSFORM_EXPANDPerformset_expand()PNG_TRANSFORM_INVERT_MONOInvertmonochromeimagesPNG_TRANSFORM_SHIFTNormalizepixelstothesBITdepthPNG_TRANSFORM_BGRFlipRGBtoBGR,RGBAtoBGRAPNG_TRANSFORM_SWAP_ALPHAFlipRGBAtoARGBorGAtoAGPNG_TRANSFORM_INVERT_ALPHAChangealphafromopacitytotransparencyPNG_TRANSFORM_SWAP_ENDIANByte-swap16-bitsamplesPNG_TRANSFORM_GRAY_TO_RGBExpandgrayscalesamplestoRGB(orGAtoRGBA)高层读取函数如下:1:/*2:*Ifyouhaveenoughmemorytoreadintheentireimageatonce,3:*andyouneedtospecifyonlytransformsthatcanbecontrolled4:*withoneofthePNG_TRANSFORM_*bits(thispresentlyexcludes5:*dithering,filling,settingbackground,anddoinggamma6:*adjustment),thenyoucanreadtheentireimage(including7:*pixels)intotheinfostructurewiththiscall:8:*/9:png_read_png(png_ptr,info_ptr,png_transforms,png_voidp_NULL);该函数将会把所有的图片数据解码到info_ptr数据结构中。png_transforms为整型参数,为上面libpng预定义的数据类型进行or操作得到。调用了该函数,就不可以再调用png_set_transform函数来设置输出数据。该函数相当于调用底层函数(下文将会介绍)如下调用顺序:a)调用png_read_info函数获得图片信息。b)根据png_transforms所指示的,调用png_set_transform设置输出格式转换的函数。c)调用png_read_image来解码整个图片的数据到内存。d)调用png_read_end结束图片解码。当你调用png_read_png之后,则可以调用如下函数得到png数据:1:row_pointers=png_get_rows(png_ptr,info_ptr);底层处理a)读取输入png数据的图片信息:1:/*Thecalltopng_read_info()givesusalloftheinformationfromthe2:*PNGf