上一篇讲了libpng和zlib的关系
zlib,Libpng,gzip,libzip库的联系与区别
接下来记录libpng的使用
准备
首先了解png,bmp文件格式的特点,本篇不详细介绍。
bmp图片是微软的图片格式,就是原始的像素数据加上bmp文件头组成,像素数据是倒装的,即第一个像素的(RGB)三个字节再原始文件的最后。png是原始数据压缩后加入png格式文件描述。
下载libpng和zlib的源码,放在同一个目录中
由于libpng实际上使用的是zlib的算法,libpng是zlib的顶层文件,所以从libpng的文件看起。
libpng
libpng内提供了示例文件example.c 和一个使用手册libpng-manual.txt。推荐有耐心想学好的阅读libpng-manual.txt,但这个文件有5000多行,让人崩溃。主要内容如下
如果只是使用的话,先看1,2,3,4,5,6
简介
建议使用者学习example.c 和 pngtest.c,libpng 符合IOS/IEC 15948:2004 标准。
Libpng被设计为一次处理多个会话,易于修改,可移植到绝大多数可用的机器(ANSI、K&R、16位、32位和64位),并且易于使用。libpng的最终目标是促进以任何可能的方式接受PNG文件格式。虽然还有很多工作要做(请参阅TODO文件),但libpng应该能够满足用户的大多数需求。
Libpng是线程安全的,前提是线程使用结构的不同实例。每个线程都应该有自己的png_struct和png_info实例,以及自己的图像。Libpng不会保护自己不受使用同一个结构实例的两个线程的影响。
结构
libpng有两个重要的主要结构,png_struct和png info。它们都是内部结构,不对外(从libpng 1.5.0开始)。
png info结构用于提供有关png文件的信息。以前,png信息字段的目的是让用户直接访问。然而这往往会导致使用动态加载库的应用程序出现问题,结果是开发了一组用于png信息的接口函数(png get *()和png set *()函数),并且已弃用直接访问png信息字段的方式。
png_struct结构体是标准库用来解码单个图像的对象。这个结构体也不对外。
几乎所有的libpng api都要求一个指向png结构体的指针作为第一个参数。很多(特别是png set和png_get api)也需要一个指向png info的指针作为第二个参数。
在png.h中定义的一些用于基本数据访问(读取和写入PNG格式的整数)的应用程序可见宏不接受PNG信息指针,但几乎可以认为是安全地,必须传递(png_struct*)才能安全的调用API函数。(不太会翻译)
一个图片可以有多个相关的 png_info 结构体,参照pngtest.c。一个用于在IDAT块之前有效的信息,另一个(下面称为“end_info”)用于在它们之后有效的信息。图像数据块IDAT(image data chunk):它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。IDAT存放着图像真正的数据信息。
png.h头文件是使用libpng编程的宝贵参考。当我在讨论这个主题时,确保你包含了libpng头文件:
#include <png.h>
#include <zlib.h>
类型
png.h头文件定义了许多api使用的整型类型。其中大多数都是相当明显的;例如,与特定大小的整数对应的类型和用于传递颜色值的类型
一个例外是如何处理非整数。为了方便应用程序,大多数接受这样数字的api都有c (double)参数;
但是,PNG和libpng内部使用32位有符号整数,并通过乘以100 000对值进行编码。
从libpng 1.5.8开始,在PNG .h中定义了一个方便的宏 PNG_FP_1,并定义了一个类型(png_fixed_point),即简单的(png_int_32)。
所有接受(double)参数的API都有一个匹配的API,它接受相应的定点整数参数。定点API与附加了“_fixed”的浮点API同名。
api中允许的值的实际范围通常小于(png_fixed_point)的完整范围(-21474到+21474)。当api需要一个非负参数时,类型被记录为上面的png uint 32。更多信息请参阅头文件和下面的文本。
必须特别注意sCAL块处理,因为块本身使用编码为包含十进制浮点数的字符串的非整数值。请参阅头文件中的注释。
配置
头文件的函数声明经常被c格式的预处理指令保护:
#ifdef PNG_feature_SUPPORTED
declare-function
#endif
...
#ifdef PNG_feature_SUPPORTED
use-function
#endif
尽管标准构建将包含所有已实现的API,但构建库时也可以不支持这些API。应用程序在使用API之前应该检查特性宏,以获得最大的可移植性。从libpng 1.5.8开始,在构建libpng期间设置的特性宏都记录在头文件“pnglibconf”中。这个文件总是包含在png.h中。
如果您不需要更改默认的库配置,请跳到下一节(“读取”)。本节余下内容可以不看。
注意,'scripts'目录下的一些makefile和(在1.5.0中)'projects'目录下的所有构建项目文件只是简单地复制scripts/pnglibconf.h。pnglibconf.h预先构建的。这意味着这些构建系统不允许对库进行简单的自动配置——它们只支持默认配置。
在支持自动配置时,对libpng配置进行微小更改的最简单方法是使用(通常)CPPFLAGS向命令行添加定义。例如:
CPPFLAGS=-DPNG_NO_FLOATING_ARITHMETIC
这将改变内部的libpng数学实现的伽玛校正和其他算术计算为定点,避免需要快速浮点支持。结果可以在生成的pnglibconf.h中看到,请确保它包含更改的特性宏设置。
如果你需要进行更广泛的配置更改——一个或两个以上功能宏设置---您可以添加-DPNG_USER_CONFIG到编译命令行,或者把宏列表设置添加到 pngusr.h,或者你可以设置DFA_XTRA (一个makefile变量)包含相同的信息的文件的形式“选项”设置。
A. 修改 pnglibconf.h
有各种方法可以构建libpng。并不是所有这些都支持pnglibconf.h的重新配置。
要重新配置pnglibconf.h,必须从scripts/pnglibconf.dfa使用awk重新构建。否则必须手工编辑。
手动编辑是通过复制scripts/pnglibconf.h来实现的。预构建到pnglibconf.h,并更改定义所支持特性的行,密切关注scripts/pnglibconf.dfa 中的“选项”信息。描述这些特性及其需求的信息。这很容易出错。
B. 使用 DFA_XTRA配置
从pnglibconf.dfa重建,如果一个功能性的“awk”,或后来的变体,如“nawk”或“gawk”可用,是很容易的。configure构建将自动找到合适的awk并构建pnglibconf.h。scripts/ pnglibconf.mak文件包含一组make规则,用于在不使用configure时执行相同的操作,并且scripts目录中的许多makefile都使用这种方法。
重建时,只需编写一个包含更改选项和设置的新文件DFA_XTRA到这个文件的名称。这会导致构建将新文件追加到scripts/pnglibconf.dfa的末尾。pngusr.dfa文件应该包含以下格式的行:
everything = off
这将关闭所有可选特性。在pngusr的开头包含它。dfa使构建最小配置变得更容易。之后,您至少需要打开一些特性,以便能够读取或编写代码,或者两者兼备。
option feature on option feature off
启用或禁用单个功能。这将自动启用一个特性所需要的其他特性,或禁用其他需要一个特性所关闭的特性。冲突的设置将导致awk发出错误消息
设置特性默认值
将“feature”的默认值更改为“value”。在pnglibconf.h的顶部列出了少量的设置,它们被记录在源代码中。这些值中的大多数对库有性能影响,但大多数对API没有明显的影响。有些也可以被API覆盖。
这种构建自定义pnglibconf.h的方法在contrib/pngminim/*中说明。参见makefile和pngusr.dfa中的"$(PNGCONF):"目标文件在这些目录中。
C. 使用 PNG_USER_CONFIG 配置
如果在构建pnglibconf.h时-PNG_USER_CONFIG 被添加到CPPFLAGS中,pngusr.h文件将自动包含在scripts/pnglibconf.dfa中的选项之前是处理。你的pngusr.h文件应该只包含打开或关闭特性或设置设置的宏定义。
除了全局设置"everything = off"之外,上面列出的所有选项都可以使用pngusr.h中的宏来设置:
#define PNG_feature_SUPPORTED
is equivalent to:
option feature on
#define PNG_NO_feature
is equivalent to:
option feature off
#define PNG_feature value
is equivalent to:
setting feature default value
请注意,在这两种情况下,pngusr.dfa pngusr.h, pngusr文件vou supply的内容覆盖scripts/ pngglibconf .dfa的内容如果导致令人困惑或难以理解的行为,可以检查中间文件pnglibconf。查找每个设置和选项的完整依赖信息。只需在文件中找到该特性,并读取它之前的c注释。这个方法在contrib/pngminim/* makefiles和pngusr.h中也有说明。
下一篇文章继续翻译 libpng手册的 Reading 部分。 |