首页 [jpeg 图像]JPEG图像格式详解

[jpeg 图像]JPEG图像格式详解

举报
开通vip

[jpeg 图像]JPEG图像格式详解[jpeg 图像]JPEG图像格式详解 [jpeg 图像]JPEG图像格式详解 篇一 : JPEG图像格式详解 JPEG图像格式详解 JPEG 压缩简介 ------------- 1. 色彩模型 JPEG 的图片使用的是 YCrCb 颜色模型, 而不是计算机上最常用的 RGB. 关于色 彩模型, 这里不多阐述. 只是说明, YCrCb 模型更适合图形压缩. 因为人眼对图片上 的亮度 Y 的变化远比色度 C 的变化敏感. 我们完全可以每个点保存一个 8bit 的亮 度值, 每 2x2 个点保存一个 Cr...

[jpeg 图像]JPEG图像格式详解
[jpeg 图像]JPEG图像格式详解 [jpeg 图像]JPEG图像格式详解 篇一 : JPEG图像格式详解 JPEG图像格式详解 JPEG 压缩简介 ------------- 1. 色彩模型 JPEG 的图片使用的是 YCrCb 颜色模型, 而不是计算机上最常用的 RGB. 关于色 彩模型, 这里不多阐述. 只是说明, YCrCb 模型更适合图形压缩. 因为人眼对图片上 的亮度 Y 的变化远比色度 C 的变化敏感. 我们完全可以每个点保存一个 8bit 的亮 度值, 每 2x2 个点保存一个 Cr Cb 值, 而图象在肉眼中的感觉不会起太大的变化. 所以, 原来用 RGB 模型, 4 个点需要 4x3=12 字节. 而现在仅需要 4+2=6 字节; 平 均每个点占 12bit. 当然 JPEG 格式里允许每个点的 C 值都记录下来; 不过 MPEG 里 都是按 12bit 一个点来存放的, 我们简写为 YUV12. [R G B] -> [Y Cb Cr] 转换 ------------------------- | Y | | 0.299 0.587 0.114 | | R | | 0 | | Cb | = |- 0.1687 - 0.3313 0.5 | * | G | + |128| | Cr | | 0.5 - 0.4187 - 0.0813| | B | |128| Y = 0.299*R + 0.587*G + 0.114*B Cb = - 0.1687*R - 0.3313*G + 0.5 *B + 128 Cr = 0.5 *R - 0.4187*G - 0.0813*B + 128 [Y,Cb,Cr] -> [R,G,B] 转换 ------------------------- R = Y + 1.402 * G = Y - 0.34414* - 0.71414* B = Y + 1.772 * 一般, C 值 应该是一个有符号的数字, 但这里被处理过了, 方法 是加上了 128. JPEG 里的数据都是无符号 8bit 的. 2. DCT JPEG 里, 要对数据压缩, 先要做一次 DCT 变换. DCT 变换的原理, 涉及到数学 知识, 这里我们不必深究. 反正和傅立叶变换 是差不多了. 经过 这个变换, 就把图片里点和点间的规律呈现出来了, 更方便压缩.JPEG 里是对每 8x8 个点为一个单位处理的. 所以如果原始图片的长宽不是 8 的倍数, 都需要先补成 8 的倍数, 好一块块的处理. 另外, 记得刚才我说的 Cr Cb 都是 2x2 记录一次吗? 所 以大多数情况, 是要补成 16x16 的整数块.按从左到右, 从上到下的次序排列 . JPEG 里是对 Y Cr Cb 分别做 DCT 变换的. 这里进行 DCT 变换 的 Y, Cr, Cb 值的范围都是 -128~127. JPEG 编码时使用的是 Forward DCT 解码时使用的 Inverse DCT 下面给出公式: FDCT: 7 7 2*x+1 2*y+1 F = alpha*alpha* sum sum f * cos * cos x=0 y=0 16 16 u,v = 0,1,...,7 { 1/sqrt alpha = { { 1/2 IDCT: 7 7 2*x+1 2*y+1 f = sum sum alpha*alpha*F*cos * cos u=0 v=0 16 16 x,y=0,1...7 这个步骤很花时间, 另外有种 AA&N 优化算法, 大家可以去 inet 自己找一下. 在 Intel 主页上可以找到 AA&N IDCT 的 MMX 优化代码. 3. 重排列 DCT 结果 DCT 将一个 8x8 的数组变换成另一个 8x8 的数组. 但是内存里所有数据都是线 形存放的, 如果我们一行行的存放这 64 个数字, 每行的结尾的点和下行开始的点就 没有什么关系, 所以 JPEG 规定按如下次序整理 64 个数字. 0, 1, 5, 6,14,15,27,28, 2, 4, 7,13,16,26,29,42, 3, 8,12,17,25,30,41,43, 9,11,18,24,31,40,44,53, 10,19,23,32,39,45,52,54, 20,22,33,38,46,51,55,60, 21,34,37,47,50,56,59,61, 35,36,48,49,57,58,62,63 这样数列里的相邻点在图片上也是相邻的了. 4. 量化 对于前面得到的 64 个空间频率振幅值, 我们将对它们作幅度分层量化操作.方 法就是分别除以量化表里对应值并四舍五入. for vector[i] = 下面有张 JPEG 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 量化表. 16 11 10 16 24 40 51 61 12 12 14 19 26 58 60 55 14 13 16 24 40 57 69 56 14 17 22 29 51 87 80 62 18 22 37 56 68 109 103 77 24 35 55 64 81 104 113 92 49 64 78 87 103 121 120 101 72 92 95 98 112 100 103 99 这张表依据心理视觉阀制作, 对 8bit 的亮度和色度的图象的 处理效果不错. 当然我们可以使用任意的量化表. 量化表是定义在 jpeg 的 DQT 标记后. 一般 为 Y 值定义一个, 为 C 值定义一个. 量化表是控制 JPEG 压缩比的关键. 这个步骤除掉了一些高频量, 损失了很高 细节. 但事实上人眼对高空间频率远没有低频敏感.所以处理后的视觉损失很小. 另一个重要原因是所有的图片的点与点之间会有一个色彩过渡的过程. 大量的图象 信息被包含在低空间频率中. 经过量化处理后, 在高空间频率段, 将出现大量连续 的零. 注意, 量化后的数据有可能超过 2 byte 有符号整数的处理范围. 5. 0 RLE 编码 现在我们矢量中有许多连续的 0. 我们可以使用 RLE 来压缩掉这些 0. 这里我们 将跳过第一个矢量 因为它的编码比较特别. 假设有一组矢量 是 57,45,0,0,0,0,23,0,-30,-16,0,0,1,0,0,0, 0 , 0 ,0 , 0,..,0 经过 RLE 压缩后就是 ; ; ; ; ; ; EOB EOB 是一个结束标记, 表示后面都是 0 了. 实际上, 我们用 表示 EOB 但是, 如果这组数字不以 0 结束, 那么就不需要 EOB. 扩展:jpeg格式详解 / jpeg 图像 jpg格式 / jpeg编解码过程详解 另外需要注意的是, 由于后面 huffman 编码的要求, 每组数字 前一个表示 0 的 数量的必须是 4 bit, 就是说, 只能是 0~15, 所以, 如果有这么一组数字: 57, 十八个0, 3, 0, 0, 0, 0, 2, 三十三个0, 895, EOB 我们实际这样编码: ; ; ; , 注意 表示了 16 个连续的 0. 6. huffman 编码 为了提高储存效率, JPEG 里并不直接保存数值, 而是将数值 按位数分成 16 组: 数值 组 实际保存值 0 0 - -1,1 1 0,1 -3,-2,2,3 2 00,01,10,11 -7,-6,-5,-4,4,5,6,7 3 000,001,010,011,100,101,110,111 -15,..,-8,8,..,15 4 0000,..,0111,1000,..,1111 -31,..,-16,16,..,31 5 00000,..,01111,10000,..,11111 -63,..,-32,32,..,63 6 . -127,..,-64,64,..,127 7 . -255,..,-128,128,..,255 8 . -511,..,-256,256,..,511 9 . -1023,..,-512,512,..,1023 10 . -2047,..,-1024,1024,..,2047 11 . -4095,..,-2048,2048,..,4095 12 . -8191,..,-4096,4096,..,8191 13 . -16383,..,-8192,8192,..,16383 14 . -32767,..,-16384,16384,..,32767 15 . 还是来看前面的例子: ; ; ; ; ; ; 只处理每对数右边的那个: 57 是第 6 组的, 实际保存值为 111001 , 所以被编码为 45 , 同样的操作, 编码为 23 -> -30 -> -8 -> 1 -> 前面的那串数字就变成了: , 111001 ; , 101101 ; , 10111; , 00001; , 0111 ; , 1 ; 括号里的数值正好合成一个字节. 后面被编码的数字表示范围 是 -32767..32767. 合成的字节里, 高 4 位是前续 0 的个数, 低 4 位描述了后面数字的位数. 继续刚才的例子, 如果 06 的 huffman 编码为 111000 69 = --- 1111111110011001 21 = --- 11111110110 4 = --- 1011 33 = --- 11011 0 = EOB = --- 1010 那么最后对于前面的例子表示的 63 个系数 按位流 写入 JPG 文件中就是这样的: 111000 111001 111000 101101 1111111110011001 10111 11111110110 00001 1011 0111 11011 1 1010 7. DC 的编码 ----------- 记得刚才我们跳过了每组 64 个数据的第一个吧, DC 就是指的这个数字 代入前面的 FDCT 公式可以得到 c 7 7 DC = F = --------- * sum sum f * cos 0 * cos 0 其中 c = 1/2 4 x=0 y=0 1 7 7 = --- * sum sum f 8 x=0 y=0 即一块图象样本的平均值. 就是说, 它包含了原始 8x8 图象块里的很多能量. JPEG 的作者指出连续块的 DC 率之间有很紧密的联系, 因此他们决定对 8x8 块的 DC 值的差别进行编码. Diff = DC - DC 所以这一块的 DC 就是: DC = DC + Diff JPG 从 0 开始对 DC 编码, 所以 DC=0. 然后再将当前 Diff 值加在上一个值上得 到当前值. 下面再来看看上面那个例子: 例如上面例子中, Diff 是 -511, 就编码成 如果 9 的 Huffman 编码是 1111110 那么在 JPG 文件中, DC 的 2 进制表示为 1111110 000000000 它将放在 63 个 AC 的前面, 上面上个例子的最终 BIT 流如下: 1111110 000000000 111000 111001 111000 101101 1111111110011001 10111 11111110110 00001 1011 0111 11011 1 1010 解码过程简述 ------------- 8. 一个数据单元 Y 的解码 -------------------------------- 在整个图片解码的开始, 你需要先初始化 DC 值为 0. 1) 先解码 DC: a) 取得一个 Huffman 码 b) Huffman解码, 看看后面的数据位数 N c) 取得 N 位, 计算 Diff 值 d) DC + = Diff e) 写入 DC 值: “ vector[0]=DC “ 2) 解码 63 个 AC: ------- 循环处理每个 AC 直到 EOB 或者处理到 64 个 AC a) 取得一个 Huffman 码 b) Huffman 解码, 得到 [记住: 如果是 就是 EOB 了] c) 取得 N 位 计算 AC d) 写入相应数量的 0 e) 接下来写入 AC ----------------- 下一步的解码 ------------ 上一步我们得到了 64 个矢量. 下面我们还需要做一些解码工作: 扩展:jpeg格式详解 / jpeg 图像 jpg格式 / jpeg编解码过程详解 1) 反量化 64 个矢量 : “for vector[i]*=quant[i]” 2) 重排列 64 个矢量到 8x8 的块中 3) 对 8x8 的块作 IDCT 对 8x8 块的 重复上面的操作 [Huffman 解码, 步骤 1), 2), 3)] 4) 将所有的 8bit 数加上 128 5) 转换 YCbCr 到 RGB 9. JPG 文件里怎样组织图片信息 ----------------------------------- 注意 JPEG/JFIF 文件格式使用 Motorola 格式, 而不是 Intel 格式, 就是说, 如果 是一个字的话, 高字节在前, 低字节在后. JPG 文件是由一个个段 构成的. 每个段长度 在处理 JPG 文件时, 如果你碰到一个 0xFF, 而它后面的字节不是 0, 并且这个字节 没有意义. 那么你遇到的 0xFF 字节必须被忽略. 如果你在做 huffman 编码时碰巧产生了一个 0xFF, 那么就用 0xFF 0x00 代替. 就是说在 jpeg 图形解码时碰到 FF00 就把它当作 FF 处理. 另外在 huffman 编码区域结束时, 碰到几个 bit 没有用的时候, 应该用 1 去填充. 然后后面跟 FF. 下面是几个重要的标记 -------------------- SOI = Start Of Image = „FFD8? 这个标记只在文件开始出现一次 EOI = End Of Image = „FFD9? JPG 文件都以 FFD9 结束 RSTi = FFDi [ RST0 = FFD0, RST7=FFD7] = 复位标记 通常穿插在数据流里, 我想是担心 JPG 解码出问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 吧. RST 将 Huffman 的解码数据流复位. DC 也重新从 0 开始计 ------- 10. 标记 ------- 下面是必须处理的标记 SOF0 = Start Of Frame 0 = FFC0 SOS = Start Of Scan = FFDA APP0 = it?s the marker used to identify a JPG file which uses the JFIF specification = FFE0 COM = Comment = FFFE DNL = Define Number of Lines = FFDC DRI = Define Restart Interval = FFDD DQT = Define Quantization Table = FFDB DHT = Define Huffman Table = FFC4 11. JPG 文件中 Haffman 表的储存 ----------------------------- JPEG 里定义了一张表来描述 Haffman 树. 定义在 DHT 标 记后面. 注意: Haffman 代码的长度限制在 16bit 内. 一般一个 JPG 文件里会有 2 类 Haffman 表: 一个用于 DC 一个用于 AC 这张表是这样保存的: 1) 16 字节: 第 i 字节表示了 i 位长的 Huffman 代码的个数 2) 这表的长度 = 这 16 个数字之和 现在你可以想象这张表怎么存放的吧? 对应字节就是对应 Haffman 代码等价数字. 我 不多解释, 这需要你先了解 Haffman 算法. 这里只举一个例子: Haffman 表的表头是 0,2,3,1,1,1,0,1,0,0,0,0,0,0,0,0 就是说长度为 1 的代码没有 长度为 2 的代码为 00 01 长度为 3 的代码是 100 101 110 长度为 4 的代码是 1110 长度为 5 的代码是 11110 长度为 6 的代码是 111110 长度为 7 的代码没有 长度为 8 的代码是 11111100 ..... 后面都没有了. 如果表下面的数据是 45 57 29 17 23 25 34 28 就是说 45 = 00 57 = 01 29 = 100 17 = 101 23 = 110 等等... 如果你懂 Haffman 编码, 这些不难理解 12. 采样系数 ----------- 下面讲解的都是真彩 JPG 的解码, 灰度 JPG 的解码很简单, 因为图形中只有亮度信 息. 而彩色图形由 构成, 前面提到过, Y 通常是每点采样一次, 而 Cr, Cb 一般是 2x2 点采样一次, 当然也有的 JPG 是逐点采样, 或者每两点采样 采样系数均被定义成对比最高采样系数的相对值. 一般情况 下: Y 有最高的采样率, 横向采 样系数HY=2 纵向采样系数 VY=2; Cb 的横向采样系数 HCb=1, 纵向采样系数 VCb=1; 同样 HCr=1, VCr=1 在 Jpeg 里, 8x8 个原始数据, 经过 RLE, Huffman 编码后的一串数据流称为一个 Data Unit JPG 里按 DU 为单位的编码次序如下: 1) for for { 对 Y 的 Data Unit 编码 } 2) for for { 对 Cb 的 Data Unit 编码 } 3) for for { 对 Cr 的 Data Unit 编码 } 按我上面的例子: 就是这样一个次序 YDU,YDU,YDU,YDU,CbDU,CrDU 这些就描述了一块 16x16 的图形. 16x16 = 这里 Hmax=HY=2 Vmax=VY=2 一个 的块被称作 MCU 前面例子中一个 MCU = YDU,YDU,YDU,YDU,CbDU,CrDU 扩展:jpeg格式详解 / jpeg 图像 jpg格式 / jpeg编解码过程详解 如果 HY =1, VY=1 HCb=1, VCb=1 HCr=1, VCr=1 这样 , MCU 只有 8x8 大, MCU = YDU,CbDU,CrDU 对于灰度 JPG, MCU 只有一个 DU JPG 文件里, 图象的每个组成部分的采样系数定义在 SOF0 标记后 13. 简单说一下 JPG 文件的解码 ------------------------- 解码程序先从 JPG 文件中读出采样系数, 这样就知道了 MCU 的大小, 算出整个图象 有几个 MCU. 解码程序再循环逐个对 MCU 解码, 一直到检查到 EOI 标记. 对于每个 MCU, 按正规的次序解出每个 DU, 然后组合, 转换成 就 OK 了 附:JPEG 文件格式 ~~~~~~~~~~~~~~~~ - 文件头 : $ff, $d8 - 任意数量的段 , 见后面 - 文件结束 : $ff, $d9 段的格式: ~~~~~~~~~ - header : $ff 段标识 n 段的类型 sh, sl 该段长度, 包括这两个字节, 但是不包括前面的 $ff 和 n. 注意: 长度不是 intel 次序, 而是 Motorola 的, 高字节在前, 低字节在后! - 该段的 内容 财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容 , 最多 65533 字节 注意: - 有一些无参数的段 这些段没有长度描述 , 只有 $ff 和类型字节. - 段之间无论有多少 $ff 都是合法的, 必须被忽略掉. 段的类型: ~~~~~~~~~ *TEM = $01 可以忽略掉 SOF0 = $c0 帧开始 , 细节附后 SOF1 = $c1 dito SOF2 = $c2 通常不支持 SOF3 = $c3 通常不支持 SOF5 = $c5 通常不支持 SOF6 = $c6 通常不支持 SOF7 = $c7 SOF9 = $c9 arithmetic SOF10 = $ca SOF11 = $cb SOF13 = $cd SOF14 = $ce SOF14 = $ce SOF15 = $cf DHT = $c4 JPG = $c8 DAC = $cc *RST0 = $d0 RSTn *RST1 = $d1 *RST2 = $d2 *RST3 = $d3 *RST4 = $d4 *RST5 = $d5 *RST6 = $d6 *RST7 = $d7 SOI = $d8 EOI = $d9 SOS = $da DQT = $db DNL = $dc DRI = $dd DHP = $de EXP = $df APP0 = $e0 JFIF APP0 segment marker , 通常不支持通常不支持 通常不支持 通常不支持 通常不支持 通常不支持 通常不支持 定义 Huffman Table, 细节附后 未定义/保留 定义 Arithmetic Table, 通常不支持 用于 resync, 通常被忽略 图片开始 图片结束 扫描行开始, 细节附后 定义 Quantization Table, 细节附后 通常不支持, 忽略 定义重新开始间隔, 细节附后 忽略 忽略 细节略) 忽略 JPG0 = $f0 忽略 JPG13 = $fd 忽略 COM = $fe 注释, 细节附后 其它的段类型都保留必须跳过 SOF0: Start Of Frame 0: ~~~~~~~~~~~~~~~~~~~~~~~ - $ff, $c0 - 长度 , 8+components*3 - 数据精度 每个样本位数, 通常是 8 - 图片高度 , 如果不支持 DNL 就必须 >0 - 图片宽度 , 如果不支持 DNL 就必须 >0 - components 数量, 灰度图是 1, YCbCr/YIQ 彩色图是 3, CMYK 彩色图 是 4 - 每个 component: 3 bytes - component id - 采样系数 - quantization table 号 DRI: Define Restart Interval: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - $ff, $dd - 长度 , 必须是 4 - MCU 块的单元中的重新开始间隔 , 意思是说, 每 n 个 MCU 块就有一个 RSTn 标记. 第一个标记是 RST0, 然后是 RST1 等, RST7 后再从 RST0 重复 DQT: Define Quantization Table: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - $ff, $db - 长度 - QT 信息 : bit 0..3: QT 号 bit 4..7: QT 精度, 0 = 8 bit, 否则 16 bit - n 字节的 QT, n = 64* 备注: - 一个单独的 DQT 段可以包含多个 QT, 每个都有自己的信息字节 - 当精度=1 , 每个字都是高位在前低位在后 DAC: Define Arithmetic Table: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 法律原因, 现在的软件不支持 arithmetic 编码. 不能生产使用 arithmetic 编码的 JPEG 文件 DHT: Define Huffman Table: ~~~~~~~~~~~~~~~~~~~~~~~~~~ - $ff, $c4 - 长度 - HT 信息 : bit 0..3: HT 号 bit 4 : HT 类型, 0 = DC table, 1 = AC table bit 5..7: 必须是 0 - 16 bytes: 长度是 1..16 代码的符号数. 这 16 个数的和应该 备注: - 一个单独的 DHT 段可以包含多个 HT, 每个都有自己的信息字节 COM: 注释: ~~~~~~~~~~ - $ff, $fe - 注释长度 = L+2 - 注释为长度为 L 的字符流 SOS: Start Of Scan: ~~~~~~~~~~~~~~~~~~~ - $ff, $da - 长度 , 必须是 6+2* - 扫描行内组件的数量 , 必须 >= 1 , 扩展:jpeg格式详解 / jpeg 图像 jpg格式 / jpeg编解码过程详解 - component id , 见 SOF0 - 使用的 Huffman 表: - bit 0..3: AC table - bit 4..7: DC table - 忽略 3 bytes 备注: - 图片数据 紧接着 SOS 段. | Y | | 0.299 0.587 0.114 | | R | | 0 | | Cb | = |- 0.1687 - 0.3313 0.5 | * | G | + |128| | Cr | | 0.5 - 0.4187 - 0.0813| | B | |128| Y = 0.299*R + 0.587*G + 0.114*B Cb = - 0.1687*R - 0.3313*G + 0.5 *B + 128 Cr = 0.5 *R - 0.4187*G - 0.0813*B + 128 [Y,Cb,Cr] -> [R,G,B] 转换 ------------------------- R = Y + 1.402 * G = Y - 0.34414* - 0.71414* B = Y + 1.772 * 一般, C 值 应该是一个有符号的数字, 但这里被处理过了, 方法 是加上了 128. JPEG 里的数据都是无符号 8bit 的. 2. DCT JPEG 里, 要对数据压缩, 先要做一次 DCT 变换. DCT 变换 的原理, 涉及到数学 知识, 这里我们不必深究. 反正和傅立叶变换 是差不多了. 经过 这个变换, 就把图片里点和点间的规律呈现出来 了, 更方便压缩.JPEG 里是对每 8x8 个点为一个单位处理的. 所以如果原始图片的长宽不是 8 的倍数, 都需要先补成 8 的倍数, 好一块块的处理. 另外, 记得刚才我说的 Cr Cb 都是 2x2 记录一次吗? 所 以大多数情况, 是要补成 16x16 的整数块.按从左到右, 从上到下的次序排列 . JPEG 里是对 Y Cr Cb 分别做 DCT 变换的. 这里进行 DCT 变换 的 Y, Cr, Cb 值的范围都是 -128~127. JPEG 编码时使用的是 Forward DCT 解码时使用的 Inverse DCT 下面给出公式: FDCT: 7 7 2*x+1 2*y+1 F = alpha*alpha* sum sum f * cos * cos x=0 y=0 16 16 u,v = 0,1,...,7 { 1/sqrt alpha = { { 1/2 IDCT: 7 7 2*x+1 2*y+1 f = sum sum alpha*alpha*F*cos * cos u=0 v=0 16 16 x,y=0,1...7 这个步骤很花时间, 另外有种 AA&N 优化算法, 大家可以去 inet 自己找一下. 在 Intel 主页上可以找到 AA&N IDCT 的 MMX 优化代码. 3. 重排列 DCT 结果 DCT 将一个 8x8 的数组变换成另一个 8x8 的数组. 但是内存里所有数据都是线 形存放的, 如果我们一行行的存放这 64 个数字, 每行的结尾的点和下行开始的点就 没有什么关系, 所以 JPEG 规定按如下次序整理 64 个数字. 0, 1, 5, 6,14,15,27,28, 2, 4, 7,13,16,26,29,42, 3, 8,12,17,25,30,41,43, 9,11,18,24,31,40,44,53, 10,19,23,32,39,45,52,54, 20,22,33,38,46,51,55,60, 21,34,37,47,50,56,59,61, 35,36,48,49,57,58,62,63 这样数列里的相邻点在图片上也是相邻的了. 4. 量化 对于前面得到的 64 个空间频率振幅值, 我们将对它们作幅度分层量化操作.方 法就是分别除以量化表里对应值并四舍五入. for vector[i] = 下面有张 JPEG 标准量化表. 16 11 10 16 24 40 51 61 12 12 14 19 26 58 60 55 14 13 16 24 40 57 69 56 14 17 22 29 51 87 80 62 18 22 37 56 68 109 103 77 24 35 55 64 81 104 113 92 49 64 78 87 103 121 120 101 72 92 95 98 112 100 103 99 这张表依据心理视觉阀制作, 对 8bit 的亮度和色度的图象的处理效果不错. 当然我们可以使用任意的量化表. 量化表是定义在 jpeg 的 DQT 标记后. 一般 为 Y 值定义一个, 为 C 值定义一个. 量化表是控制 JPEG 压缩比的关键. 这个步骤除掉了一些高频量, 损失了很高 细节. 但事实上人眼对高空间频率远没有低频敏感.所以处理后的视觉损失很小. 另一个重要原因是所有的图片的点与点之间会有一个色彩过渡的过程. 大量的图象 信息被包含在低空间频率中. 经过量化处理后, 在高空间频率段, 将出现大量连续 的零. 注意, 量化后的数据有可能超过 2 byte 有符号整数的处理范围. 5. 0 RLE 编码 现在我们矢量中有许多连续的 0. 我们可以使用 RLE 来压缩掉这些 0. 这里我们 将跳过第一个矢量 因为它的编码比较特别. 假设有一组矢量 是 57,45,0,0,0,0,23,0,-30,-16,0,0,1,0,0,0, 0 , 0 ,0 , 0,..,0 经过 RLE 压缩后就是 ; ; ; ; ; ; EOB EOB 是一个结束标记, 表示后面都是 0 了. 实际上, 我们用 表示 EOB 但是, 如果这组数字不以 0 结束, 那么就不需要 EOB. 另外需要注意的是, 由于后面 huffman 编码的要求, 每组数字前一个表示 0 的 数量的必须是 4 bit, 就是说, 只能是 0~15, 所以, 如果有这么一组数字: 57, 十八个0, 3, 0, 0, 0, 0, 2, 三十三个0, 895, EOB 我们实际这样编码: ; ; ; , 注意 表示了 16 个连续的 0. 6. huffman 编码 为了提高储存效率, JPEG 里并不直接保存数值, 而是将数值按位数分成 16 组: 数值 组 实际保存值 0 0 - -1,1 1 0,1 -3,-2,2,3 2 00,01,10,11 -7,-6,-5,-4,4,5,6,7 3 000,001,010,011,100,101,110,111 -15,..,-8,8,..,15 4 0000,..,0111,1000,..,1111 -31,..,-16,16,..,31 5 00000,..,01111,10000,..,11111 -63,..,-32,32,..,63 6 . -127,..,-64,64,..,127 7 . -255,..,-128,128,..,255 8 . -511,..,-256,256,..,511 9 . -1023,..,-512,512,..,1023 10 . -2047,..,-1024,1024,..,2047 11 . -4095,..,-2048,2048,..,4095 12 . -8191,..,-4096,4096,..,8191 13 . -16383,..,-8192,8192,..,16383 14 . -32767,..,-16384,16384,..,32767 15 . 还是来看前面的例子: ; ; ; ; ; ; 只处理每对数右边的那个: 57 是第 6 组的, 实际保存值为 111001 , 所以被编码为 45 , 同样的操作, 编码为 23 -> -30 -> -8 -> 1 -> 前面的那串数字就变成了: , 111001 ; , 101101 ; , 10111; , 00001; , 0111 ; , 1 ; 括号里的数值正好合成一个字节. 后面被编码的数字表示范围 是 -32767..32767. 合成的字节里, 高 4 位是前续 0 的个数, 低 4 位描述了后面数字的位数. 继续刚才的例子, 如果 06 的 huffman 编码为 111000 69 = --- 1111111110011001 21 = --- 11111110110 4 = --- 1011 33 = --- 11011 0 = EOB = --- 1010 那么最后对于前面的例子表示的 63 个系数 按位流 写入 JPG 文件中就是这样的: 111000 111001 111000 101101 1111111110011001 10111 11111110110 00001 1011 0111 11011 1 1010 7. DC 的编码 ----------- 记得刚才我们跳过了每组 64 个数据的第一个吧, DC 就是指 的这个数字 代入前面的 FDCT 公式可以得到 c 7 7 DC = F = --------- * sum sum f * cos 0 * cos 0 其中 c = 1/2 4 x=0 y=0 1 7 7 = --- * sum sum f 8 x=0 y=0 即一块图象样本的平均值. 就是说, 它包含了原始 8x8 图象 块里的很多能量. JPEG 的作者指出连续块的 DC 率之间有很紧密的联系, 因此他们决定对 8x8 块的 DC 值的差别进行编码. Diff = DC - DC 所以这一块的 DC 就是: DC = DC + Diff JPG 从 0 开始对 DC 编码, 所以 DC=0. 然后再将当前 Diff 值加在上一个值上得 到当前值. 下面再来看看上面那个例子: 例如上面例子中, Diff 是 -511, 就编码成 如果 9 的 Huffman 编码是 1111110 那么在 JPG 文件中, DC 的 2 进制表示为 1111110 000000000 它将放在 63 个 AC 的前面, 上面上个例子的最终 BIT 流如下: 1111110 000000000 111000 111001 111000 101101 1111111110011001 10111 11111110110 00001 1011 0111 11011 1 1010 解码过程简述 ------------- 8. 一个数据单元 Y 的解码 -------------------------------- 在整个图片解码的开始, 你需要先初始化 DC 值为 0. 1) 先解码 DC: a) 取得一个 Huffman 码 b) Huffman解码, 看看后面的数据位数 N c) 取得 N 位, 计算 Diff 值 d) DC + = Diff e) 写入 DC 值: “ vector[0]=DC “ 2) 解码 63 个 AC: ------- 循环处理每个 AC 直到 EOB 或者处理到 64 个 AC a) 取得一个 Huffman 码 b) Huffman 解码, 得到 [记住: 如果是 就是 EOB 了] c) 取得 N 位 计算 AC d) 写入相应数量的 0 e) 接下来写入 AC ----------------- 下一步的解码 ------------ 上一步我们得到了 64 个矢量. 下面我们还需要做一些解码工作: 1) 反量化 64 个矢量 : “for vector[i]*=quant[i]” 2) 重排列 64 个矢量到 8x8 的块中 3) 对 8x8 的块作 IDCT 对 8x8 块的 重复上面的操作 [Huffman 解码, 步骤 1), 2), 3)] 4) 将所有的 8bit 数加上 128 5) 转换 YCbCr 到 RGB 9. JPG 文件里怎样组织图片信息 ----------------------------------- 注意 JPEG/JFIF 文件格式使用 Motorola 格式, 而不是 Intel 格式, 就是说, 如果 是一个字的话, 高字节在前, 低字节在后. JPG 文件是由一个个段 构成的. 每个段长度 在处理 JPG 文件时, 如果你碰到一个 0xFF, 而它后面的字节不是 0, 并且这个字节 没有意义. 那么你遇到的 0xFF 字节必须被忽略. 如果你在做 huffman 编码时碰巧产生了一个 0xFF, 那么就用 0xFF 0x00 代替. 就是说在 jpeg 图形解码时碰到 FF00 就把它当作 FF 处理. 另外在 huffman 编码区域结束时, 碰到几个 bit 没有用的时候, 应该用 1 去填充. 然后后面跟 FF. 下面是几个重要的标记 -------------------- SOI = Start Of Image = „FFD8? 这个标记只在文件开始出现一次 EOI = End Of Image = „FFD9? JPG 文件都以 FFD9 结束 RSTi = FFDi [ RST0 = FFD0, RST7=FFD7] = 复位标记 通常穿插在数据流里, 我想是担心 JPG 解码出问题吧. RST 将 Huffman 的解码数据流复位. DC 也重新从 0 开始计 ------- 10. 标记 ------- 下面是必须处理的标记 SOF0 = Start Of Frame 0 = FFC0 SOS = Start Of Scan = FFDA APP0 = it?s the marker used to identify a JPG file which uses the JFIF specification = FFE0 COM = Comment = FFFE DNL = Define Number of Lines = FFDC DRI = Define Restart Interval = FFDD DQT = Define Quantization Table = FFDB DHT = Define Huffman Table = FFC4 11. JPG 文件中 Haffman 表的储存 ----------------------------- JPEG 里定义了一张表来描述 Haffman 树. 定义在 DHT 标 记后面. 注意: Haffman 代码的长度限制在 16bit 内. 一般一个 JPG 文件里会有 2 类 Haffman 表: 一个用于 DC 一个用于 AC 这张表是这样保存的: 1) 16 字节: 第 i 字节表示了 i 位长的 Huffman 代码的个数 2) 这表的长度 = 这 16 个数字之和 现在你可以想象这张表怎么存放的吧? 对应字节就是对应 Haffman 代码等价数字. 我 不多解释, 这需要你先了解 Haffman 算法. 这里只举一个例子: Haffman 表的表头是 0,2,3,1,1,1,0,1,0,0,0,0,0,0,0,0 就是说长度为 1 的代码没有 长度为 2 的代码为 00 01 长度为 3 的代码是 100 101 110 长度为 4 的代码是 1110 长度为 5 的代码是 11110 长度为 6 的代码是 111110 长度为 7 的代码没有 长度为 8 的代码是 11111100 ..... 后面都没有了. 如果表下面的数据是 45 57 29 17 23 25 34 28 就是说 45 = 00 57 = 01 29 = 100 17 = 101 23 = 110 等等... 如果你懂 Haffman 编码, 这些不难理解 12. 采样系数 ----------- 下面讲解的都是真彩 JPG 的解码, 灰度 JPG 的解码很简单, 因为图形中只有亮度信 息. 而彩色图形由 构成, 前面提到过, Y 通常是每点采样一次, 而 Cr, Cb 一般是 2x2 点采样一次, 当然也有的 JPG 是逐点采样, 或者每两点采样 采样系数均被定义成对比最高采样系数的相对值. 一般情况 下: Y 有最高的采样率, 横向采 样系数HY=2 纵向采样系数 VY=2; Cb 的横向采样系数 HCb=1, 纵向采样系数 VCb=1; 同样 HCr=1, VCr=1 在 Jpeg 里, 8x8 个原始数据, 经过 RLE, Huffman 编码后的一串数据流称为一个 Data Unit JPG 里按 DU 为单位的编码次序如下: 1) for for { 对 Y 的 Data Unit 编码 } 2) for for { 对 Cb 的 Data Unit 编码 } 3) for for { 对 Cr 的 Data Unit 编码 } 按我上面的例子: 就是这样一个次序 YDU,YDU,YDU,YDU,CbDU,CrDU 这些就描述了一块 16x16 的图形. 16x16 = 这里 Hmax=HY=2 Vmax=VY=2 一个 的块被称作 MCU 前面例子中一个 MCU = YDU,YDU,YDU,YDU,CbDU,CrDU 如果 HY =1, VY=1 HCb=1, VCb=1 HCr=1, VCr=1 这样 , MCU 只有 8x8 大, MCU = YDU,CbDU,CrDU 对于灰度 JPG, MCU 只有一个 DU JPG 文件里, 图象的每个组成部分的采样系数定义在 SOF0 标记后 13. 简单说一下 JPG 文件的解码 ------------------------- 解码程序先从 JPG 文件中读出采样系数, 这样就知道了 MCU 的大小, 算出整个图象 有几个 MCU. 解码程序再循环逐个对 MCU 解码, 一直到检查到 EOI 标记. 对于每个 MCU, 按正规的次序解出每个 DU, 然后组合, 转换成 就 OK 了 附:JPEG 文件格式 ~~~~~~~~~~~~~~~~ - 文件头 : $ff, $d8 - 任意数量的段 , 见后面 - 文件结束 : $ff, $d9 段的格式: ~~~~~~~~~ - header : $ff 段标识 n 段的类型 sh, sl 该段长度, 包括这两个字节, 但是不包括前面的 $ff 和 n. 注意: 长度不是 intel 次序, 而是 Motorola 的, 高字节在前, 低字节在后! - 该段的内容, 最多 65533 字节 注意: - 有一些无参数的段 这些段没有长度描述 , 只有 $ff 和类型字节. - 段之间无论有多少 $ff 都是合法的, 必须被忽略掉. 段的类型: ~~~~~~~~~ *TEM = $01 可以忽略掉 SOF0 = $c0 帧开始 , 细节附后 SOF1 = $c1 dito SOF2 = $c2 通常不支持 SOF3 = $c3 通常不支持 SOF5 = $c5 通常不支持 SOF6 = $c6 通常不支持 SOF7 = $c7 SOF9 = $c9 arithmetic SOF10 = $ca SOF11 = $cb SOF13 = $cd SOF14 = $ce SOF14 = $ce SOF15 = $cf DHT = $c4 JPG = $c8 DAC = $cc *RST0 = $d0 RSTn *RST1 = $d1 *RST2 = $d2 *RST3 = $d3 *RST4 = $d4 *RST5 = $d5 *RST6 = $d6 *RST7 = $d7 SOI = $d8 EOI = $d9 SOS = $da DQT = $db DNL = $dc DRI = $dd DHP = $de EXP = $df APP0 = $e0 JFIF APP0 segment marker , 通常不支持通常不支持 通常不支持 通常不支持 通常不支持 通常不支持 通常不支持 定义 Huffman Table, 细节附后 未定义/保留 定义 Arithmetic Table, 通常不支持 用于 resync, 通常被忽略 图片开始 图片结束 扫描行开始, 细节附后 定义 Quantization Table, 细节附后 通常不支持, 忽略 定义重新开始间隔, 细节附后 忽略 忽略 细节略) 忽略 JPG0 = $f0 忽略 JPG13 = $fd 忽略 COM = $fe 注释, 细节附后 其它的段类型都保留必须跳过 SOF0: Start Of Frame 0: ~~~~~~~~~~~~~~~~~~~~~~~ - $ff, $c0 - 长度 , 8+components*3 - 数据精度 每个样本位数, 通常是 8 - 图片高度 , 如果不支持 DNL 就必须 >0 - 图片宽度 , 如果不支持 DNL 就必须 >0 - components 数量, 灰度图是 1, YCbCr/YIQ 彩色图是 3, CMYK 彩色图 是 4 - 每个 component: 3 bytes - component id - 采样系数 - quantization table 号 DRI: Define Restart Interval: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - $ff, $dd - 长度 , 必须是 4 - MCU 块的单元中的重新开始间隔 , 意思是说, 每 n 个 MCU 块就有一个 RSTn 标记. 第一个标记是 RST0, 然后是 RST1 等, RST7 后再从 RST0 重复 DQT: Define Quantization Table: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - $ff, $db - 长度 - QT 信息 : bit 0..3: QT 号 bit 4..7: QT 精度, 0 = 8 bit, 否则 16 bit - n 字节的 QT, n = 64* 备注: - 一个单独的 DQT 段可以包含多个 QT, 每个都有自己的信息字节 - 当精度=1 , 每个字都是高位在前低位在后 DAC: Define Arithmetic Table: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 法律原因, 现在的软件不支持 arithmetic 编码. 不能生产使用 arithmetic 编码的 JPEG 文件 DHT: Define Huffman Table: ~~~~~~~~~~~~~~~~~~~~~~~~~~ - $ff, $c4 - 长度 - HT 信息 : bit 0..3: HT 号 bit 4 : HT 类型, 0 = DC table, 1 = AC table bit 5..7: 必须是 0 - 16 bytes: 长度是 1..16 代码的符号数. 这 16 个数的和应该 备注: - 一个单独的 DHT 段可以包含多个 HT, 每个都有自己的信息字节 COM: 注释: ~~~~~~~~~~ - $ff, $fe - 注释长度 = L+2 - 注释为长度为 L 的字符流 SOS: Start Of Scan: ~~~~~~~~~~~~~~~~~~~ - $ff, $da - 长度 , 必须是 6+2* - 扫描行内组件的数量 , 必须 >= 1 , - component id , 见 SOF0 - 使用的 Huffman 表: - bit 0..3: AC table - bit 4..7: DC table - 忽略 3 bytes 备注: - 图片数据 紧接着 SOS 段.
本文档为【[jpeg 图像]JPEG图像格式详解】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_751406
暂无简介~
格式:doc
大小:74KB
软件:Word
页数:36
分类:
上传时间:2017-10-25
浏览量:80