王文胜ID:wwsheng
4954次访问,排名17623好友0人,关注者1
毕业于中科院自动化所,有5年多的开发经验,以前一直专注于Java方面的开发,企业级应用和电信级应用,现在专注于基于ARM的嵌入式Linux开发。
wwsheng的文章
原创 0 篇
翻译 0 篇
转载 22 篇
评论 1 篇
最近评论
kazon:不错,受用了~~
文章分类
收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    转载 JPEG文件编/解码详解收藏

    新一篇: Using USB Devices in a Virtual Machine | 旧一篇: PNG文件结构(PNG图片格式)详解

    JPEGJoint Photographic Experts Group)是联合图像专家小组的英文缩写。它由国际电话与电报咨询委员会CCITTThe International Telegraph and Telephone Consultative Committee)与国际标准化组织ISO1986年联合成立的一个小组,负责制定静态数字图像的编码标准。

    小组一直致力于标准化工作,开发研制出连续色调、多级灰度、静止图像的数字图像压缩编码方法,即JPEG算法。JPEG算法被确定为国际通用标准,其适用范围广泛,除用于静态图像编码外,还推广到电视图像序列的帧内图像压缩。而用JPEG算法压缩出来的静态图片文件称为JPEG文件,扩展名通常为*.jpg*.jpe*.jpeg

    JPEG专家组开发了两种基本的压缩算法、两种数据编码方法、四种编码模式。具体如下:

    压缩算法:

    l 有损的离散余弦变换(Discrete Cosine TransformDCT);

    l 无损的预测技术压缩。

    数据编码方法:

    l 哈夫曼编码;

    l 算术编码;

    编码模式:

    l 基于DCT顺序模式:编/解码通过一次扫描完成;

    l 基于DCT递进模式:编/解码需要多次扫描完成,扫描效果从粗糙到精细,逐级递进;

    l 无损模式:基于DPCM,保证解码后完全精确恢复到原图像采样值;

    l 层次模式:图像在多个空间多种分辨率进行编码,可以根据需要只对低分辨率数据作解码,放弃高分辨率信息。

    在实际应用中,JPEG图像使用的是离散余弦变换、哈夫曼编码、顺序模式。

     

    JPEG压缩编码算法的主要计算步骤如下:

    (0) 8*8分块。

    (1) 正向离散余弦变换(FDCT)

    (2) 量化(quantization)

    (3) Z字形编码(zigzag scan)

    (4) 使用差分脉冲编码调制(DPCM)对直流系数(DC)进行编码。

    (5) 使用行程长度编码(RLE)对交流系数(AC)进行编码。

    (6) 熵编码。

     

    笔者在实践过程中查阅了大量的资料,发现大多数书籍资料和网上资料都是从编码角度分析JPEG的编/解码方式,并且都只是介绍编码过程中的主要方法。所以,本文从解码角度详细分析JPEG的编/解码过程,并且加入许多笔者实践过程中遇到的问题和解决方法,希望从另一个角度说明问题,以更好帮助读者结合其他资料解决问题。

    不过,介绍解码过程之前,首先要了解JPEG文件中数据的存储格式。


    一、JPEG文件格式介绍

    JPEG文件使用的数据存储方式有多种。最常用的格式称为JPEG文件交换格式(JPEG File Interchange FormatJFIF)。而JPEG文件大体上可以分成两个部分:标记码(Tag)和压缩数据。

    标记码由两个字节构成,其前一个字节是固定值0xFF,后一个字节则根据不同意义有不同数值。在每个标记码之前还可以添加数目不限的无意义的0xFF填充,也就说连续的多个0xFF可以被理解为一个0xFF,并表示一个标记码的开始。而在一个完整的两字节的标记码后,就是该标记码对应的压缩数据流,记录了关于文件的诸种信息。

    常用的标记有SOIAPP0DQTSOF0DHTDRISOSEOI

    注意,SOI等都是标记的名称。在文件中,标记码是以标记代码形式出现。例如SOI的标记代码为0xFFD8,即在JPEG文件中的如果出现数据0xFFD8,则表示此处为一个SOI标记。

    本文附录列出一张完整的JPEG定义的标记表,供读者查阅。这里仅列出几个常用标记的标记代码、占用字节长度和表示的意义。

     

    l         SOIStart of Image,图像开始

    u  标记代码                                 2字节     固定值0xFFD8

     

    l       APP0Application,应用程序保留标记0

    u  标记代码                                 2字节     固定值0xFFE0

    u  包含9个具体字段:
     
    数据长度                         2字节     ~9个字段的总长度
                                                               
    即不包括标记代码,但包括本字段
     
    标识符                             5字节    固定值0x4A46494600,即字符串“JFIF0”
     
    版本号                             2字节    一般是0x0102,表示JFIF的版本号
    1.2
                                                               
    可能会有其他数值代表其他版本

     
    XY的密度单位           1字节     只有三个值可选
                                                                0
    :无单位;1:点数/英寸;2:点数/厘米
     
    X方向像素密度               2字节     取值范围未知
     
    Y方向像素密度               2字节     取值范围未知  
     
    缩略图水平像素数目        1字节     取值范围未知

     
    缩略图垂直像素数目        1字节     取值范围未知
     
    缩略图RGB位图             长度可能是3的倍数           缩略图RGB位图数据

     

    本标记段可以包含图像的一个微缩版本,存为24位的RGB像素。如果没有微缩图像(这种情况更常见),则字段缩略图水平像素数目和字段缩略图垂直像素数目的值均为0

     

    l       APPnApplication,应用程序保留标记n,其中n=115(任选)

    u  标记代码                                 2字节     固定值0xFFE1~0xFFF

    u  包含2个具体字段:
     
    数据长度                         2字节     ~2个字段的总长度
                                                               
    即不包括标记代码,但包括本字段
     
     详细信息            数据长度-2字节   内容不定
                                                        

    例如,Adobe Photoshop生成的JPEG图像中就用了APP1APP13两个标记段分别存储了一幅图像的副本。

     

    l       DQTDefine Quantization Table,定义量化表

    u  标记代码                          2字节            固定值0xFFDB

    u  包含9个具体字段:
     
    数据长度                  2字节            字段①和多个字段②的总长度
                                                               
    即不包括标记代码,但包括本字段
     
     量化表        数据长度-2字节

    a)         精度及量化表ID   1字节            4位:精度,只有两个可选值
                                                                  0
    8位;116
                                                   
    4位:量化表ID,取值范围为03

    b)        表项       (64×(精度+1))字节              例如8位精度的量化表
                                                   
    其表项长度为64×0+1=64字节

     

    本标记段中,字段②可以重复出现,表示多个量化表,但最多只能出现4次。

     

    l       SOF0Start of Frame,帧图像开始

    u  标记代码                   2字节     固定值0xFFC0

    u  包含9个具体字段:
     
    数据长度           2字节     ~六个字段的总长度
                                                 
    即不包括标记代码,但包括本字段
     
    精度                 1字节     每个数据样本的位数
                                                 
    通常是8位,一般软件都不支持 12位和16
     
    图像高度           2字节     图像高度(单位:像素),如果不支持 DNL 就必须 >0
     
    图像宽度           2字节     图像宽度(单位:像素),如果不支持 DNL 就必须
    >0
     
    颜色分量数        1字节     只有3个数值可选

                                                  1
    :灰度图;3YCrCbYIQ4CMYK
                                                 
    JFIF中使用YCrCb,故这里颜色分量数恒为
    3
     
    颜色分量信息      颜色分量数×3字节(通常为9字节)

    a)         颜色分量ID                 1字节    

    b)        水平/垂直采样因子      1字节            4位:水平采样因子
                                                          
    4位:垂直采样因子
                                                          
    (曾经看到某资料把这两者调转了)

    c)        量化表                         1字节            当前分量使用的量化表的ID

    本标记段中,字段⑥应该重复出现,有多少个颜色分量(字段⑤),就出现多少次(一般为3次)。

     

    l       DHTDifine Huffman Table,定义哈夫曼表

    u  标记代码                                 2字节            固定值0xFFC4

    u  包含2个具体字段:
     
    数据长度                             2字节            字段①和多个字段②的总长度
                                                                      
    即不包括标记代码,但包括本字段
     
     哈夫曼表              数据长度-2字节

    a)       ID和表类型            1字节            4位:类型,只有两个值可选
                                                                         0
    DC直流;1AC交流
                                                           
    4位:哈夫曼表ID
                                                                        
    注意,DC表和AC表分开编码

    b)      不同位数的码字数量    16字节

    c)      编码内容       16个不同位数的码字数量之和(字节)

    本标记段中,字段②可以重复出现(一般4次),也可以致出现1次。例如,Adobe Photoshop 生成的JPEG图片文件中只有1DHT标记段,里边包含了4个哈夫曼表;而Macromedia Fireworks生成的JPEG图片文件则有4DHT标记段,每个DHT标记段只有一个哈夫曼表。

     

    l       DRIDefine Restart Interval定义差分编码累计复位的间隔

    u  标记代码                                 2字节     固定值0xFFDD

    u  包含2个具体字段:
     
    数据长度                             2字节     固定值0x0004~两个字段的总长度
                                                               
    即不包括标记代码,但包括本字段
     
    MCU块的单元中的重新开始间隔
                                                  2
    字节     设其值为n,则表示每nMCU块就有一个
                                                               RSTn
    标记。第一个标记是RST0,第二个是
                                                                RST1
    等,RST7后再从RST0重复。

     

    如果没有本标记段,或间隔值为0时,就表示不存在重开始间隔和标记RST

     

    l       SOSStart of Scan,扫描开始 12字节

    u  标记代码                          2字节     固定值0xFFDA

    u  包含2个具体字段:
     
    数据长度                      2字节     ~