JPEG编码解码流程_第1页
JPEG编码解码流程_第2页
JPEG编码解码流程_第3页
JPEG编码解码流程_第4页
JPEG编码解码流程_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JPEG 图片压缩算法流程详解 薛晓利 JPEG 是 Joint Photographic Exports Group 的英文缩写 中文称之为联合图像专家小组 该小组隶属于 ISO 国际标准化组织 主要负责定制静态数字图像的编码方法 即所谓的 JPEG 算法 JPEG 专家组开发了两种基本的压缩算法 两种熵编码方法 四种编码模式 如下所示 压缩算法 1 有损的离散余弦变换 DCT Discrete Cosine Transform 2 无损的预测压缩技术 熵编码方法 1 Huffman 编码 2 算术编码 编码模式 1 基于 DCT 的顺序模式 编码 解码通过一次扫描完成 2 基于 DCT 的渐进模式 编码 解码需要多次扫描完成 扫描效果由粗到精 逐 级递增 3 无损模式 基于 DPCM 保证解码后完全精确恢复到原图像采样值 4 层次模式 图像在多个空间分辨率中进行编码 可以根据需要只对低分辨率数据 做解码 放弃高分辨率信息 在实际应用中 JPEG 图像编码算法使用的大多是离散余弦变换 Huffman 编码 顺序 编码模式 这样的方式 被人们称为 JPEG 的基本系统 这里介绍的 JPEG 编码算法的流 程 也是针对基本系统而言 基本系统的 JPEG 压缩编码算法一共分为 11 个步骤 颜色模式转换 采样 分块 离 散余弦变换 DCT Zigzag 扫描排序 量化 DC 系数的差分脉冲调制编码 DC 系数的 中间格式计算 AC 系数的游程长度编码 AC 系数的中间格式计算 熵编码 下面 将一 一介绍这 11 个步骤的详细原理和计算过程 1 颜色模式转换 JPEG 采用的是 YCrCb 颜色空间 而 BMP 采用的是 RGB 颜色空间 要想对 BMP 图 片进行压缩 首先需要进行颜色空间的转换 YCrCb 颜色空间中 Y 代表亮度 Cr Cb 则 代表色度和饱和度 也有人将 Cb Cr 两者统称为色度 三者通常以 Y U V 来表示 即用 U 代表 Cb 用 V 代表 Cr RGB 和 YCrCb 之间的转换关系如下所示 Y 0 299R 0 587G 0 114B Cb 0 1687R 0 3313G 0 5B 128 Cr 0 5R 0 418G 0 0813B 128 一般来说 C 值 包括 Cb Cr 应该是一个有符号的数字 但这里通过加上 128 使其变为 8 位的无符号整数 从而方便数据的存储和计算 R Y 1 402 Cr 128 G Y 0 34414 Cb 128 0 71414 Cr 128 B Y 1 772 Cb 128 2 采样 研究发现 人眼对亮度变换的敏感度要比对色彩变换的敏感度高出很多 因此 我们 可以认为 Y 分量要比 Cb Cr 分量重要的多 在 BMP 图片中 RGB 三个分量各采用一个字 节进行采样 也就是我们常听到的 RGB888 的模式 而 JPEG 图片中 通常采用两种采样 方式 YUV411 和 YUV422 它们所代表的意义是 Y Cb Cr 三个分量的数据取样比例一般 是 4 1 1 或者 4 2 2 4 1 1 含义就是 在 2x2 的单元中 本应分别有 4 个 Y 4 个 U 4 个 V 值 用 12 个字节进行存储 经过 4 1 1 采样处理后 每个单元中的值分别有 4 个 Y 1 个 U 1 个 V 只要用 6 个字节就可以存储了 这样的采样方式 虽然损失了一 定的精度但也在人眼不太察觉到的范围内减小了数据的存储量 当然 JPEG 格式里面也允 许将每个点的 U V 值都记录下来 3 分块 由于后面的 DCT 变换是是对 8x8 的子块进行处理的 因此 在进行 DCT 变换之前必 须把源图象数据进行分块 源图象中每点的 3 个分量是交替出现的 先要把这 3 个分量分 开 存放到 3 张表中去 然后由左及右 由上到下依次读取 8x8 的子块 存放在长度为 64 的表中 即可以进行 DCT 变换 注意 编码时 程序从源数据中读取一个 8x8 的数据块后 进行 DCT 变换 量化 编码 然后再读取 处理下一个 8 8 的数据块 JPEG 编码是以每 8x8 个点为一个单位进行处理的 所以如果原始图片的长宽不是 8 的倍数 都需要先补成 8 的倍数 使其可以进行一块块的处理 将原始图像数据分为 8 8 的 数据单元矩阵之后 还必须将每个数值减去 128 然后一一带入 DCT 变换公式 即可达到 DCT 变换的目的 图像的数据值必须减去 128 是因为 DCT 公式所接受的数字范围是 128 到 127 之间 4 离散余弦变换 DCT Discrete Cosine Transform 离散余弦变换 是码率压缩中常用的一种变换编码 方法 任何连续的实对称函数的傅里叶变换中只含有余弦项 因此 余弦变换同傅里叶变 换一样具有明确的物理意义 DCT 是先将整体图像分成 N N 的像素块 然后针对 N N 的 像素块逐一进行 DCT 操作 需要提醒的是 JPEG 的编码过程需要进行正向离散余弦变换 而解码过程则需要反向离散余弦变换 正向离散余弦变换计算公式 反向离散余弦变换计算公式 这里的 N 是水平 垂直方向的像素数目 一般取值为 8 8 8 的二维像素块经过 DCT 操 作之后 就得到了 8 8 的变换系数矩阵 这些系数 都有具体的物理含义 例如 U 0 V 0 时的 F 0 0 是原来的 64 个数据的均值 相当于直流分量 也有人称之为 DC 系 数或者直流系数 随着 U V 的增加 相另外的 63 个系数则代表了水平空间频率和垂直空 间频率分量 高频分量 的大小 多半是一些接近于 0 的正负浮点数 我们称之为交流系 数 AC DCT 变换后的 8 8 的系数矩阵中 低频分量集中在矩阵的左上角 高频成分则集中 在右下角 这里 我们暂时先只考虑水平方向上一行数据 8 个像素 的情况时的 DCT 变换 从 而来说明其物理意义 如下图所示 原始的图像信号 最左边的波形 经过 DCT 变换之后变成了 8 个波 其中第一个波为 直流成分 其余 7 个为交流成分 可见图像信号被分解为直流成分和一些从低频到高频的各种余弦成分 而 DCT 系数只 表示了该种成分所占原图像信号的份额大小 显然 恢复图像信息可以表示为下面的式子 F n C n E n 这里 E n 是一个基底 C n 是 DCT 系数 F n 则是图像信号 如 果考虑垂直方向的变化 那就需要一个二维的基底 大学里面的信号处理 傅里叶变换等 课程上也讲过 任何信号都可以被分解为基波和不同幅度的谐波的组合 而 DCT 变换的物 理意义也正是如此 由于大多数图像的高频分量比较小 相应的图像高频分量的 DCT 系数经常接近于 0 再加上高频分量中只包含了图像的细微的细节变化信息 而人眼对这种高频成分的失真不 太敏感 所以 可以考虑将这一些高频成分予以抛弃 从而降低需要传输的数据量 这样 一来 传送 DCT 变换系数的所需要的编码长度要远远小于传送图像像素的编码长度 到达 接收端之后通过反离散余弦变换就可以得到原来的数据 虽然这么做存在一定的失真 但 人眼是可接受的 而且对这种微小的变换是不敏感的 5 Zigzag 扫描排序 DCT 将一个 8x8 的数组变换成另一个 8x8 的数组 但是内存里所有数据都是线形存 放的 如果我们一行行的存放这 64 个数字 每行的结尾的点和下行开始的点就没有什么关 系 所以 JPEG 规定按如下图中的数字顺序依次保存和读取 64 个 DCT 的系数值 这样数列里的相邻点在图片上也是相邻的了 不难发现 这种数据的扫描 保存 读 取方式 是从 8 8 矩阵的左上角开始 按照英文字母 Z 的形状进行扫描的 一般将其称之 为 Zigzag 扫描排序 如下图所示 6 量化 图像数据转换为 DCT 频率系数之后 还要进行量化阶段 才能进入编码过程 量化阶 段需要两个 8 8 量化矩阵数据 一个是专门处理亮度的频率系数 另一个则是针对色度的 频率系数 将频率系数除以量化矩阵的值之后取整 即完成了量化过程 当频率系数经过 量化之后 将频率系数由浮点数转变为整数 这才便于执行最后的编码 不难发现 经过 量化阶段之后 所有的数据只保留了整数近似值 也就再度损失了一些数据内容 在 JPEG 算法中 由于对亮度和色度的精度要求不同 分别对亮度和色度采用不同的量化表 前者 细量化 后者粗量化 下图给出 JPEG 的亮度量化表和色度量化表 该量化表是从广泛的实验中得出的 当 然 你也可以自定义量化表 这两张表依据心理视觉阀制作 对 8bit 的亮度和色度的图象的处理效果不错 量化表 是控制 JPEG 压缩比的关键 这个步骤除掉了一些高频量 损失了很多细节信息 但事实 上人眼对高频信号的敏感度远没有低频信号那么敏感 所以处理后的视觉损失很小 从上 面的量化表也可以看出 低频部分采用了相对较短的量化步长 而高频部分则采用了相对 较长的量化步长 这样做 也是为了在一定程度上得到相对清晰的图像和更高的压缩率 另一个重要原因是所有的图片的点与点之间会有一个色彩过渡的过程 而大量的图象信息 被包含在低频率空间中 经过 DCT 处理后 在高频率部分 将出现大量连续的零 7 DC 系数的差分脉冲调制编码 8 8 的图像块经过 DCT 变换之后得到的 DC 系数有两个特点 1 系数的数值比较大 2 相邻的 8 8 图像块的 DC 系数值变化不大 根据这两个特点 DC 系数一般采用差分脉冲调制编码 DPCM Difference Pulse Code Modulation 即 取同一个图像分量中每个 DC 值与前一个 DC 值的差值 来进行编码 对差值进行编码所需要的位数会比对原值进行编码所需要 1 ii DCDCdiff 的位数少了很多 假设某一个 8 8 图像块的 DC 系数值为 15 而上一个 8 8 图像块的 DC 系数为 12 则两者之间的差值为 3 8 DC 系数的中间格式计算 JPEG 中为了更进一步节约空间 并不直接保存数据的具体数值 而是将数据按照位 数分为 16 组 保存在表里面 这也就是所谓的变长整数编码 VLI 即 第 0 组中保存的编 码位数为 0 其编码所代表的数字为 0 第 1 组中保存的编码位数为 1 编码所代表的数字 为 1 或者 1 如下面的表格所示 这里 暂且称其为 VLI 编码表 前面提到的那个 DC 差值为 3 的数据 通过查找 VLI 可以发现 整数 3 位于 VLI 表格的第 2 组 因此 可以写成 2 3 的形式 该形式 称之为 DC 系数的中间格式 9 AC 系数的行程长度编码 RLC 量化之后的 AC 系数的特点是 63 个系数中含有很多值为 0 的系数 因此 可以采用 行程编码 RLC Run Length Coding 来更进一步降低数据的传输量 利用该编码方式 可 以将一个字符串中重复出现的连续字符用两个字节来代替 其中 第一个字节代表重复的 次数 第二个字节代表被重复的字符串 例如 4 6 就代表字符串 6666 但是 在 JPEG 编码中 RLC 的含义就同其原有的意义略有不同 在 JPEG 编码中 假设 RLC 编码 之后得到了一个 M N 的数据对 其中 M 是两个非零 AC 系数之间连续的 0 的个数 即 行程长度 N 是下一个非零的 AC 系数的值 采用这样的方式进行表示 是因为 AC 系数 当中有大量的 0 而采用 Zigzag 扫描也会使得 AC 系数中有很多连续的 0 的存在 如此一 来 便非常适合于用 RLC 进行编码 例如 现有一个字符串 如下所示 57 45 0 0 0 0 23 0 30 8 0 0 1 000 经过 RLC 之后 将呈现出以下的形式 0 57 0 45 4 23 1 30 0 8 2 1 0 0 注意 如果 AC 系数之间连续 0 的个数超过 16 则用一个扩展字节 15 0 来表示 16 连 续的 0 10 AC 系数的中间格式 根据前面提到的 VLI 表格 对于前面的字符串 0 57 0 45 4 23 1 30 0 8 2 1 0 0 只处理每对数右边的那个数据 对其进行 VLI 编码 查找上面的 VLI 编码表格 可以 发现 57 在第 6 组当中 因此 可以将其写成 0 6 57 的形式 该形式 称之为 AC 系数 的中间格式 同样的 0 45 的中间格式为 0 6 45 1 30 的中间格式为 1 5 30 11 熵编码 在得到 DC 系数的中间格式和 AC 系数的中间格式之后 为进一步压缩图象数据 有 必要对两者进行熵编码 JPEG 标准具体规定了两种熵编码方式 Huffman 编码和算术编码 JPEG 基本系统规定采用 Huffman 编码 因为不存在专利问题 但 JPEG 标准并没有限制 JPEG 算法必须用 Huffman 编码方式或者算术编码方式 Huffman 编码 对出现概率大的字符分配字符长度较短的二进制编码 对出现概率小 的字符分配字符长度较长的二进制编码 从而使得字符的平均编码长度最短 Huffman 编 码的原理请参考数据结构中的 Huffman 树或者最优二叉树 Huffman 编码时 DC 系数与 AC 系数分别采用不同的 Huffman 编码表 对于亮度和色 度也采用不同的 Huffman 编码表 因此 需要 4 张 Huffman 编码表才能完成熵编码的工 作 具体的 Huffman 编码采用查表的方式来高效地完成 然而 在 JPEG 标准中没有定义 缺省的 Huffman 表 用户可以根据实际应用自由选择 也可以使用 JPEG 标准推荐的 Huffman 表 或者预先定义一个通用的 Huffman 表 也可以针对一副特定的图像 在压缩 编码前通过搜集其统计特征来计算 Huffman 表的值 下面我们举例来说明 8 8 图像子块经过 DCT 及量化之后的处理过程 假设一个图像块经过量化以后得到以下的系数矩阵 15 0 1 0 0 0 0 0 2 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 显然 DC 系数为 15 假设前一个 8 8 的图像块的 DC 系数量化值为 12 则当前 DC 系 统同上一个 DC 系数之间的差值为 3 通过查找 VLI 编码表 可以得到 DC 系数的中间格式 为 2 3 这里的 2 代表后面的数字 3 的编码长度为 2 位 之后 通过 Zigzag 扫 描之后 遇到第一个非 0 的 AC 系数为 2 遇到 0 的个数为 1 AC 系数经过 RLC 编码后可表 示为 1 2 通过查找 VLI 表发现 2 在第 2 组 因此 该 AC 系数的中间格式为 1 2 2 其余的点类似 可以求得这个 8 8 子块熵编码的中间格式为 DC 2 3 AC 1 2 2 0 1 1 0 1 1 0 1 1 2 1 1 EOB 0 0 对于 DC 系数的中间格式 2 3 而言 数字 2 查 DC 亮度 Huffman 表得到 011 数字 3 通过查找 VLI 编码表得到其被编码为 11 对于 AC 系数的中间格式 1 2 2 而言 1 2 查 AC 亮度 Huffman 表得到 11011 2 通过查找 VLI 编码表得到其被编码为 01 对于 AC 系数的中间格式 0 1 1 而言 0 1 查 AC 亮度 Huffman 表得到 00 数字 1 通过查找 VLI 编码表得到其被编码为 0 对于 AC 系数的中间格式 2 1 1 而言 2 1 查 AC 亮度 Huffman 表得到 11100 数 字 1 通过查找 VLI 编码表得到其被编码为 0 对于 AC 系数的中间格式 0 0 而言 查 AC 亮度 Huffman 表得到 1010 因此 最后这个 8 8 子块亮度信息压缩后的数据流为 01111 1101101 000 000 000 111000 1010 总共 31 比特 其压缩比是 64 8 31 16 5 大约每个像素用半个比特 JPEGJPEG 推荐的推荐的 DCDC 和和 ACAC 系数的系数的 huffman huffman 哈夫曼哈夫曼 码表码表 Table K 3 Table for luminance DC coefficient differences Category Code length Code word 0 2 000 1 3 010 2 3 011 3 3 100 4 3 101 5 3 110 6 4 1110 7 5 11110 8 6 111110 9 7 1111110 10 8 11111110 11 9 111111110 Table K 4 Table for chrominance DC coefficient differences Category Code length Code word 0 12 000 1 12 01 2 12 10 3 13 110 4 14 1110 5 15 11110 6 16 111110 7 17 1111110 8 18 11111110 9 19 111111110 10 10 1111111110 11 11 11111111110 Table K 5 Table for luminance AC coefficients sheet 1 of 4 Run Size Code length Code word 0 0 EOB 14 1010 0 1 12 00 0 2 12 01 0 3 13 100 0 4 14 1011 0 5 15 11010 0 6 17 1111000 0 7 18 11111000 0 8 10 1111110110 0 9 16 1111111110000010 0 A 16 1111111110000011 1 1 14 1100 1 2 15 11011 1 3 17 1111001 1 4 19 111110110 1 5 11 11111110110 1 6 16 1111111110000100 1 7 16 1111111110000101 1 8 16 1111111110000110 1 9 16 1111111110000111 1 A 16 1111111110001000 2 1 15 11100 2 2 18 11111001 2 3 10 1111110111 2 4 12 111111110100 2 5 16 1111111110001001 2 6 16 1111111110001010 2 7 16 1111111110001011 2 8 16 1111111110001100 2 9 16 1111111110001101 2 A 16 1111111110001110 3 1 16 111010 3 2 19 111110111 3 3 12 111111110101 3 4 16 1111111110001111 3 5 16 1111111110010000 3 6 16 1111111110010001 3 7 16 1111111110010010 3 8 16 1111111110010011 3 9 16 1111111110010100 3 A 16 1111111110010101 Table K 5 sheet 2 of 4 Run Size Code length Code word 4 1 16 111011 4 2 10 1111111000 4 3 16 1111111110010110 4 4 16 1111111110010111 4 5 16 1111111110011000 4 6 16 1111111110011001 4 7 16 1111111110011010 4 8 16 1111111110011011 4 9 16 1111111110011100 4 A 16 1111111110011101 5 1 17 1111010 5 2 11 11111110111 5 3 16 1111111110011110 5 4 16 1111111110011111 5 5 16 1111111110100000 5 6 16 1111111110100001 5 7 16 1111111110100010 5 8 16 1111111110100011 5 9 16 1111111110100100 5 A 16 1111111110100101 6 1 17 1111011 6 2 12 111111110110 6 3 16 1111111110100110 6 4 16 1111111110100111 6 5 16 1111111110101000 6 6 16 1111111110101001 6 7 16 1111111110101010 6 8 16 1111111110101011 6 9 16 1111111110101100 6 A 16 1111111110101101 7 1 18 11111010 7 2 12 111111110111 7 3 16 1111111110101110 7 4 16 1111111110101111 7 5 16 1111111110110000 7 6 16 1111111110110001 7 7 16 1111111110110010 7 8 16 1111111110110011 7 9 16 1111111110110100 7 A 16 1111111110110101 8 1 19 111111000 8 2 15 111111111000000 Run Size Code length Code word 8 3 16 1111111110110110 8 4 16 1111111110110111 8 5 16 1111111110111000 8 6 16 1111111110111001 8 7 16 1111111110111010 8 8 16 1111111110111011 8 9 16 1111111110111100 8 A 16 1111111110111101 9 1 19 111111001 9 2 16 1111111110111110 9 3 16 1111111110111111 9 4 16 1111111111000000 9 5 16 1111111111000001 9 6 16 1111111111000010 9 7 16 1111111111000011 9 8 16 1111111111000100 9 9 16 1111111111000101 9 A 16 1111111111000110 A 1 19 111111010 A 2 16 1111111111000111 A 3 16 1111111111001000 A 4 16 1111111111001001 A 5 16 1111111111001010 A 6 16 1111111111001011 A 7 16 1111111111001100 A 8 16 1111111111001101 A 9 16 1111111111001110 A A 16 1111111111001111 B 1 10 1111111001 B 2 16 1111111111010000 B 3 16 1111111111010001 B 4 16 1111111111010010 B 5 16 1111111111010011 B 6 16 1111111111010100 B 7 16 1111111111010101 B 8 16 1111111111010110 B 9 16 1111111111010111 B A 16 1111111111011000 C 1 10 1111111010 C 2 16 1111111111011001 C 3 16 1111111111011010 C 4 16 1111111111011011 Table K 5 sheet 4 of 4 Run Size Code length Code word C 5 16 1111111111011100 C 6 16 1111111111011101 C 7 16 1111111111011110 C 8 16 1111111111011111 C 9 16 1111111111100000 C A 16 1111111111100001 D 1 11 11111111000 D 2 16 1111111111100010 D 3 16 1111111111100011 D 4 16 1111111111100100 D 5 16 1111111111100101 D 6 16 1111111111100110 D 7 16 1111111111100111 D 8 16 1111111111101000 D 9 16 1111111111101001 D A 16 1111111111101010 E 1 16 1111111111101011 E 2 16 1111111111101100 E 3 16 1111111111101101 E 4 16 1111111111101110 E 5 16 1111111111101111 E 6 16 1111111111110000 E 7 16 1111111111110001 E 8 16 1111111111110010 E 9 16 1111111111110011 E A 16 1111111111110100 F 0 ZRL 11 11111111001 F 1 16 1111111111110101 F 2 16 1111111111110110 F 3 16 1111111111110111 F 4 16 1111111111111000 F 5 16 1111111111111001 F 6 16 1111111111111010 F 7 16 1111111111111011 F 8 16 1111111111111100 F 9 16 1111111111111101 F A 16 1111111111111110 JPEG 文件格式介绍 JPEG 文件的存储格式有很多种 但最常用的是 JFIF 格式 即 JPEG File Interchange Format JPEG 文件大体可以分为两个部分 1 标记码 由两个字节构成 其中 前一个字节是固定值 0XFF 代表了一个标记码 的开始 后一个字节不同的值代表着不同的含义 需要提醒的是 连续的多个 0XFF 可以 理解为一个 0XFF 并表示一个标记码的开始 另外 标记码在文件中一般是以标记代码的 形式出现的 例如 SOI 的标记代码是 0XFFD8 即 如果 JPEG 文件中出现了 0XFFD8 则代表此处是一个 SOI 标记 2 压缩数据 一个完整的两字节标记码的后面 就是该标记码对应的压缩数据了 它记录了关于文件的若干信息 一些典型的标记码 及其所代表的含义如下所示 SOI Start Of Image 图像开始 标记代码为固定值 0XFFD8 用 2 字节表示 APP0 Application 0 应用程序保留标记 0 标记代码为固定值 0XFFE0 用 2 字节表示 该标记码之后包含了 9 个具体的字段 1 数据长度 2 个字节 用来表示 1 9 的 9 个字段的总长度 即不包含标记代 码但包含本字段 2 标示符 5 个字节 固定值 0X4A6494600 表示了字符串 JFIF0 3 版本号 2 个字节 一般为 0X0102 表示 JFIF 的版本号为 1 2 但也可能为其它数 值 从而代表了其它版本号 4 X Y 方向的密度单位 1 个字节 只有三个值可选 0 无单位 1 点数每英寸 2 点数每厘米 5 X 方向像素密度 2 个字节 取值范围未知 6 Y 方向像素密度 2 个字节 取值范围未知 7 缩略图水平像素数目 1 个字节 取值范围未知 8 缩略图垂直像素数目 1 个字节 取值范围未知 9 缩略图 RGB 位图 长度可能是 3 的倍数 保存了一个 24 位的 RGB 位图 如果没有 缩略位图 这种情况更常见 则字段 7 8 的取值均为 0 APPn Application n 应用程序保留标记 n n 1 15 标记代码为 2 个字节 取值为 0XFFE1 0XFFFF 包含了两个字段 1 数据长度 2 个字节 表示 1 2 两个字段的总长度 即 不包含标记代码 但 包含本字段 2 详细信息 数据长度 2 个字节 内容不定 DQT Define Quantization Table 定义量化表 标记代码为固定值 0XFFDB 包含 9 个具 体字段 1 数据长度 2 个字节 表示 1 和多个 2 字段的总长度 即 不包含标记代码 但包含本字段 2 量化表 数据长度 2 个字节 其中包括以下内容 a 精度及量化表 ID 1 个字节 高 4 位表示精度 只有两个可选值 0 8 位 1 16 位 低 4 位表示量化表 ID 取值范围为 0 3 b 表项 64 精度取值 1 个字节 例如 8 位精度的量化表 其表项长度为 64 0 1 64 字节 本标记段中 2 可以重复出现 表示多个量化表 但最多只能出现 4 次 SOFO Start Of Frame 帧图像开始 标记代码为固定值 0XFFC0 包含 9 个具体字段 1 数据长度 2 个字节 1 6 共 6 个字段的总长度 即 不包含标记代码 但 包含本字段 2 精度 1 个字节 代表每个数据样本的位数 通常是 8 位 3 图像高度 2 个字节 表示以像素为单位的图像高度 如果不支持 DNL 就必须大于 0 4 图像宽度 2 个字节 表示以像素为单位的图像宽度 如果不支持 DNL 就必须大于 0 5 颜色分量个数 1 个字节 由于 JPEG 采用 YCrCb 颜色空间 这里恒定为 3 6 颜色分量信息 颜色分量个数 3 个字节 这里通常为 9 个字节 并依此表示如下一 些信息 a 颜色分量 ID 1 个字节 b 水平 垂直采样因子 1 个字节 高 4 位代表水平采样因子 低 4 位代表垂直采 样因子 c 量化表 1 个字节 当前分量使用的量化表 ID 本标记段中 字段 6 应该重复出现 3 次 因为这里有 3 个颜色分量 DHT Define Huffman Table 定义 Huffman 表 标记码为 0XFFC4 包含 2 个字段 1 数据长度 2 个字节 表示 1 2 的总长度 即 不包含标记代码 但包含本 字段 2 Huffman 表 数据长度 2 个字节 包含以下字段 a 表 ID 和表类型 1 个字节 高 4 位表示表的类型 取值只有两个 0 DC 直流 1 AC 交流 低 4 位 Huffman 表 ID 需要提醒的是 DC 表和 AC 表分开进行编码 b 不同位数的码字数量 16 个字节 c 编码内容 16 个不同位数的码字数量之和 字节 本标记段中 字段 2 可以重复出现 一般需要重复 4 次 DRI Define Restart Interval 定义差分编码累计复位的间隔 标记码为固定值 0XFFDD 包含 2 个具体字段 1 数据长度 2 个字节 取值为固定值 0X0004 表示 1 2 两个字段的总长度 即 不包含标记代码 但包含本字段 2 MCU 块的单元中重新开始间隔 2 个字节 如果取值为 n 就代表每 n 个 MCU 块就 有一个 RSTn 标记 第一个标记是 RST0 第二个是 RST1 RST7 之后再从 RST0 开始重复 如果没有本标记段 或者间隔值为 0 就表示不存在重开始间隔和标记 RST SOS Start Of Scan 扫描开始 标记码为 0XFFDA 包含 2 个具体字段 1 数据长度 2 个字节 表示 1 4 字段的总长度 2 颜色分量数目 1 个字节 只有 3 个可选值 1 灰度图 3 YCrCb 或 YIQ 4 CMYK 3 颜色分量信息 包括以下字段 a 颜色分量 ID 1 个字节 b 直流 交流系数表 ID 1 个字节 高 4 位表示直流分量的 Huffman 表的 ID 低 4 位表示交流分量的 Huffman 表的 ID 4 压缩图像数据 a 谱选择开始 1 个字节 固定值 0X00 b 谱选择结束 1 个字节 固定值 0X3F c 谱选择 1 个字节 固定值 0X00 本标记段中 3 应该重复出现 有多少个颜色分量 就重复出现几次 本段结束之后 就是真正的图像信息了 图像信息直到遇到 EOI 标记就结束了 EOI End Of Image 图像结束 标记代码为 0XFFD9 另外 需要说明的是 在 JPEG 中 0XFF 具有标记的意思 所以在压缩数据流 真正的 图像信息 中 如果出现了 0XFF 就需要做特别处理了 方法是 如果在图像数据流中遇 到 0XFF 应该检测其紧接着的字符 如果是 1 0X00 表示 0XFF 是图像流的组成部分 需要进行译码 2 0XD9 表示与 0XFF 组成标记 EOI 即 代表图像流的结束 同时 图像文件结 束 3 0XD0 0XD7 组成 RSTn 标记 需要忽视整个 RSTn 标记 即不对当前 0XFF 和 紧接着的 0XDn 两个字节进行译码 并按 RST 标记的规则调整译码变量 4 0XFF 忽略当前 0XFF 对后一个 0XFF 进行判断 5 其它数值 忽然当前 0XFF 并保留紧接着此数值用于译码 需要说明的是 JPEG 文件格式中 一个字 16 位 的存储使用的是 Motorola 格式 而不是 Intel 格式 也就是说 一个字的高字节 高 8 位 在数据流的前面 低字节 低 8 位 在数据流的后面 与平时习惯的 Intel 格式有所不同 这种字节顺序问题的起因在于 早期的硬件发展上 在 8 位 CPU 的时代 许多 8 位 CPU 都可以处理 16 位的数据 但它们 显然是分两次进行处理的 这个时候就出现了先处理高位字节还是先处理低位字节的问题 以 Intel 为代表的厂家生产的 CPU 采用先低字节后高字节的方式 而以 Motorola IBM 为代 表的厂家生产的 CPU 则采用了先高字节后低字节的方式 Intel 的字节顺序也称为 little endian 而 Motorola 的字节顺序就叫做 big endian 而 JPEG JFIF 文件格式则采用了 big endian 格式 下面的函数 实现了从 intel 格式到 motolora 格式的转换 USHORT Intel2Moto USHORT val BYTE highBits BYTE val 256 BYTE lowBits BYTE val 256 return lowBits 256 highBits JPEG 解码算法流程详解 薛晓利 1 读入 JPEG JFIF 文件的相关信息 按照 JFIF 文件格式 将 JPEG 文件相关的字段信息一一读取出来 并进行相应的解析 例如 图像的宽度 高度 量化表 Huffman 表 水平 垂直采样因子等 一般而言 JFIF 格式文件的读取顺序依次为 SOI 字段 APP0 字段 APPn 字段 DQT 字段 SOFO 字段 DHT 字段 SOS 字段 压缩数据字段 EOI 字段 读取 JPEG 文件相关信息的时候 有两点需要特别注意 a 由于 JPEG 中以 0XFF 来做为特殊标记符 因此 如果某个像素的取值为 0XFF 那么实际在保存的时候 是以 0XFF00 来保存的 从而避免其跟特殊标记符 0XFF 之间产生混淆 所以 在读取文件信息的时候 如果遇 0XFF00 就必须去除后面的 00 即 将 0XFF00 当做 0XFF b JPEG 文件中 一个字 16 位 的存储是采用了 Motorola 格式 big endian 而 不是我们常用的 Intel 格式 little endian 因此 如果需要的话 请在处理之间进行依次 高低字节的转换 2 读取 Huffman 表 在标记码 DHT 之后 包含了一个或者多个 Huffman 表 通常是 4 个表 对于一个 Huffman 表而言 它包含了以下三部分内容 a 表 ID 和表类型 1 个字节 仅有 4 个可选的取值 0X00 0X01 0X10 0X11 分 别表示 DC 直流 0 号表 DC 直流 1 号表 AC 交流 0 号表 AC 交流 1 号表 b 不同位数的码字数量 前面提到 JPEG 中的 Huffman 编码表是按照编码长度的 位数以表格的形式保存的 而且 Huffman 编码表的位数只能是 1 16 位 因此 这里用 16 个字节来分别表示 1 16 位的每种位长的编码在 Huffman 树中的个数 c 编码内容 该字段记录了 Huffman 树中各个叶子节点的权重 上一个字段 不 同位数的码字数量 的 16 个数值之和 就是本字段的长度 也就是 Huffman 树中叶子节 点的个数 这里 我们不妨以下面一段 Huffman 表的数据为例来说明情况 均以 16 进制表示 11 00 02 02 00 05 01 06 01 00 00 00 00 00 00 00 00 00 01 11 02 21 03 31 41 12 51 61 71 81 91 22 13 32 以上数据串中第一行代表了 Huffman 表 ID 表类型 不同位数的码字数量信息 第一行的第一个字节 0X11 代表了表的 ID 和类型是 AC 交流 1 号表 第一行的第 2 到第 17 字节代表了不同位数码字的数量 即 第 2 个字节 00 表示没有 位数为 1 的编码 第 3 个和第 4 个字节的 02 表示位数为 2 和位数为 3 的编码各有两个 第 5 个字节的 00 表示没有位数为 5 的编码 此外 通过这些数据我们发现 此 Huffman 树有 0 2 2 0 5 1 6 1 17 个叶子节点 第二行为编码的内容 表明 17 个叶子节点按照从小到大的顺序排列 即 权值依次 为 0 1 11 2 21 3 31 41 3 构建 Huffman 树 读取到 Huffman 表的数据之后 就需要构建 Huffman 树了 其具体规则如下 a 第一个编码的数字必定为 0 如果第一个编码的位数为 1 就被编码为 0 如果第 一个编码的位数为 2 就被编码为 00 如果第一个编码的位数为 3 就被编码为 000 b 从第二个编码开始 如果它和它前面编码具有相同的位数 则当前编码是它前面的 编码加 1 如果它的编码位数比它前面的编码位数大 则当前编码时它前面的编码加 1 之 后再在后面添加若干个 0 直到满足编码位数的长度为止 还是以上面的数据为例 第一行的第 2 个字节 00 表示没有位数为 1 的编码 第一行的第 3 个字节 02 表示位数为 2 的编码有 2 个 由于没有位数为 1 的编码 因此 这里位数为 2 的编码中的第一个为 00 第二个为 00 1 01 第一行的第 4 个字节 02 表示位数为 3 的编码有 2 个 因此 这里位数为 3 的编码中的 第一个为 01 1 10 然后添加 1 个 0 得到 100 位数为 3 的编码中的第二个为 100 1 101 依次类推 可以得到如下的 Huffman 树 序 号 码字长 度 码字权值 12000 x00 22010 x01 331000 x11 431010 x02 55110000 x21 65110010 x03 75110100 x31 85110110 x41 95111000 x12 1061110100 x51 117111011 0 0 x61 127111011 1 0 x71 137111100 0 0 x81 147111100 1 0 x91 157111101 0 0 x22 167111101 1 0 x13 178111110 00 0 x32 特别提醒的是 如果中间有某个位数的编码缺失 例如 没有 4 位的编码 则应该在 3 位 的编码后面加 1 添加 2 个 00 补足 5 位 形成下一个 5 位编码 4 DC 系数的 Huffman 解码 JPEG 编码阶段我们讲到

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论