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函数的例子。