1. Jasper库1.1. 介绍JasPer软件的核心是Jasper库。实际上,大部分Jasper的代码都和这个库有关系。Jasper库提供表现图像、色彩(色彩空间定义)和其他相关的入口类。这些类都有很好的接口,通过这些接口程序可以和类对象交互。可以使用这个饿库来操作图像、导入/导出各种格式的图像并执行基本的色彩管理操作。
理论上,Jasper库的结构在3.1中显示。库由两个不同的类型代码组成:
1. 核心代码
2. 编码驱动
核心代码提供在库上的基本框架,而编码驱动仅仅提供编码和解码各种格式图像数据的方式。所有的应用程序接口都通过核心代码;编码驱动仅仅被核心代码直接调用,其他应用程序从来不需要。
Jasper库中支持的编码既是模块的也是可扩展的。在核心代码和编码驱动之间有定义良好的接口;而且,对于新图像格式的支持能在不修改库的情况下很容易添加。为了这样,新格式的编码驱动要提供。而且,应用程序仅仅需要包含它要使用的图像格式的编码驱动。在这种情况下,应用程序能避免将内存花在从来都不使用的编码驱动上。
1.2. 核心代码核心代码提供下面这些关键的代码。(为了避免名字冲突,所有核心代码使用的的标识符都以jas_或JAS_前缀)。
1.2.1. 图像类图像类以jas_image_t开始。这些类用来表示一个图形。提供了下面这些方法:
1. 图像创建/销毁
2. 查询通用的图像属性(例如:引用grid的宽度和高度,色彩)
3. 查询组件属性(例如:宽度、高度、grid的偏移、grid的空间、组件类型、采样精度)
4. 设置各种图像属性
5. 装载和保存图像(例如:编码/解码)
6. 复制图像
7. 添加和删除组件
8. 读写组件数据
1.2.2. 色彩类这些类以jas_cmprof_t开始。这个类用来定义色彩空间。这样的一个定义被重定向为相关的色彩空间,例如CIE XYZ和CIE LAB。
1.2.3. 色彩转换类色彩转换类以jas_cmxform_t开始。这个类用来在一个图像数据上进行色彩空间转换。一个色彩空间被转换自两个或更多的色彩。
1.2.4. 流类以jas_stream_t开始,这个类提供类似与标准C库的I/O流输出;其还额外提供了Jasper库中要求的其他代码。这些功能包括:
1. 使用一个流(例如内存缓冲区)来关联一个对象而不是一个文件描述符。
2. 多个字符的获取
1.2.5. 固定点数字类这是一个模板类(一系列的宏)提供定点数字类。用来支持基本的算法操作、类型转换。
1.2.6. Tag值解析类这个类以jas_tvp_t开始;这个类用来解析包含一个或多个tag的字符串。一个tag值对是一个“tag=value”形式的字符串。Tag值在Jasper的一些接口使用来传递参数。例如:这个对用在传递给编码驱动的编码和解码操作的选项。
除了上面的类,还有一些其他的功能:命令行解析程序(和UNIX的getopt相似)。
1.3. 编码驱动核心编码提供一个框架来house编码驱动。一个编码驱动提供某特殊格式图象的编码和解码。每个驱动提供三个方法:
1. 一个编码
2. 解码
3. 验证方法
编码方法将某图像(一个jas_image_t_object)版本的转换到一个流(一个jas_stream_t_object)。解码方法从流中的数据来创建一个图像。验证方法用来测试流中的数据是否符合指定的格式;这个特殊的方法一般用来自动检测图像特使。
Jasper发布中提供的编码驱动是为了适应流数据;换句话说,图像数据流一直在单个的pass中处理。这个设计理念去掉可寻找的流对象的需要。因此,写接受和发送数据的应用程序、管道和其他不支持随机访问的是可能的。
1.4. 图像模型图像是由一个到多个部分组成;每个部分都是由采样的矩形数组组成。这个结构在图3.2中描述。
每个组件的采样值是整数值并且是有符号或无符号的1到16bit/sample。采样数据的符号和精度按照颜色来指定的。所有这些组件和图像中相同的空间扩展相关联,但表示不同类型的信息。
在诠释组件时有相当大的弹性。一个组件可以表达光谱信息(例如:彩色空间)或辅助信息(例如:一个不透明平面)。例如:一个RGB图像有三个组件,三个组件分别和红、绿、蓝颜色面相关联;一个RGBA(例如:带有透明度的RGB)图像有四个颜色面,分别和红、绿、蓝以及alpha平面相关联。各种组件不需要以相同的分辨率来采样;换句话说,不同组件可能有不同的采样周期。例如:以亮度和色调表示的彩色图像,亮度信息比色度信息更好采样并不罕见。
由于一个图像可以由很多组件组成,因此必须有一个描述怎么样用这些组件来组成一个符合图形的方法。为了这个目的,我们使用一个整数格子叫做引用网格。引用网格为一个图像的各个组件提供一个点,并建立他们之间相对对齐的方式。
每个组件和一个矩形的采样网格相关联,这样的网格通过四个参数来指定:水平偏移量、垂直偏移量、水平空间、垂直空间。一个组件的采样被映射到采样网格和引用网格交叉的点;这种情况下:采样(i , j)被 映射到引用网格的(HO + iHS, VO+ jVS)。
为了澄清上面的文字,我们现在介绍一个范例。考虑一个有三个组件的图形。对于第k个组件来说,让我们指示水平网格偏移、垂直网格偏移、水平网格空间和垂直网格空间,分别对应于HOk、VOk、HSk、VSk。假定这些参数有下面的值:
K
(HOk, VOk)
(HSk, VSk)
0
(0,0)
(2,2)
1
(2,3)
(3,4)
2
(3,2)
(4,3)
这种情况下,各组件采样值将对齐到引用网格上,图3.3描述。
图中,颜色面0的坐标原点是(0,0);水平间隔是2个引用网格,垂直间隔是2个引用网格。其他同上解释。
从上面的内容,我们可以看到Jasper的图形模式是很普通的。使用这个模型的主要约束在于使用矩形采样。不过大多数的应用程序都使用这个采样。同样使用Jasper的应用程序能够很容易的适应灰度、彩色和其他多带数据(使用或不使用不透明信息)。
1.5. JasPer头文件为了使用Jasper库,C文件通常必须包含主要的Jasper库的头文件jasper/japser.h。使用下面的预编译指令:
#include <jasper/japser.h>
主要的头文件包含了所有其他库的头文件。因此,为了是应用程序隔离其他库文件名称的改变,应用程序仅仅应该包含主头文件。
1.6. 初始化库第一次使用库总是初始化库。这通过调用jas_init来完成。如果在调用该函数之前调用任何其他库函数,结构是未知的。
1.7. 内存分配所有libjasper中的内存分配都是通过jas_malloc和jas_realloc、jas_calloc和jas_free来完成的。如果有人想要将Jasper代码导入到嵌入式平台,应该需要将这些函数改为指定平台的内存分配方式,而不是malloc等。
1.8. 为新的图形格式添加支持支持新图象格式的编码引擎能很容易被添加到Jasper中,为了能够对新文件格式的支持,必须提供下面三个函数:
1. 一个编码函数
2. 一个解码函数
3. 一个验证函数
编码函数发布一个图像的编码版本到流(一个jas_image_t对象到jas_stream_t对象)。解码函数从流(jas_stream_t对象)中的编码数据创建一个图像(一个jas_image_t对象)。验证函数用来快速的测试数据流是不是正确格式的图像数据(这个函数通常用来自动检查图像格式)。
在编码、解码和验证函数中的具体类型和参数可以通过检查Jasper中已经存在的PNM、BMP、JPEG函数。一旦上面的函数写好了,可以通过调用jas_image_addfmt来通知Jasper新的图形格式引擎已经安装。当然这个调用必须在Jasper被初始化之后调用;jas_init函数代码给出了几个关于如何调用jas_image_addfmt函数的例子。