JPEG2000的Kakadu源代码浅析之三:码流解码(一)
本章内容可能要涉及一些信号和图像处理的知识,我将尽可能用较为正式的表述,具体内容可以参考相关书籍。JPEG2000信号与信息处理的一些基础知识也可以参考我的笔记:http://lincoln.yu.googlepages.com/sgnotes.zip
码流解码过程从main函数中的kdu_codestream codestream的构造声明处开始。随即完成对输入流的绑定,和codestream的一些基本设置。然后根据codestream的已有信息获得通道(channel)个数并从每个通道中取得分量的图像尺寸(dimension)信息。接着完成输出流的配置。随后的两个while嵌套就是进行解码的关键步骤。
解码是基于一个单元类型为kde_flow_control,以tile为索引的指针数组进行的。第一层while进行行扫描,由for循环对每个数组单元调用advance_tile过程判断是否完成。而第二层while是对行内每个单元在各分量上进行解码。从而advance_components和process_components是核心的解码步骤。
首先是kde_flow_control的创建,一个kde_flow_control对应一个tile,其横向索引由构造函数参数x_tnum指定(纵向由advance_tile成员函数遍历)。以下是创建的主要工作流程:
1 导入最关键的参数,码流封装单元codestream;
2 然后从codestream中打开指定tile,调用kdu_codestream::open函数:
调用kdu_codestream::create_tile函数
创建一个kd_tile对象;
初始化该对象
以component, resolution, band为序进行三层遍历设置;
调用kd_tile::open函数打开该kd_tile对象
以component为索引遍历初始化
其它初始化操作;
设置弃级:<code>tc->apparent_dwt_levels = tc->dwt_levels - codestream->discard_levels;</code>;
以resolution, band为序进行二层遍历初始化;
3 以component为索引从codestream中获取参数;
4 以channel为索引配置参数,完成和component的映射;
5 为各component创建解码单元
分配数据处理空间,基准尺寸由comp->reversible确定;
如果该分量只包含一个分辨率级,则直接创建kdu_decoder,否则创建kdu_synthesis,再由它递归为各较低分辨率级创建相应解码单元;
6 为各具有色彩映射的channel分配数据处理空间,用对应component的分配器;
关于resolution和band的结构如下(以3级结构190x240为例):
res_level 0 1 2 3
dwt_level 3 3 2 1
dims(width) 24 48 95 190
style [LL] [HL] [HL] [HL]
[LH][HH] [LH][HH] [LH][HH]
图像二维子带变换作为JPEG2000解码的主要组成部分之一采用提升快速算法实现,并且这是一种递归的方法。