精华内容
下载资源
问答
  • 基于MATLAB的JPEG压缩编程实现实例
  • jpeg压缩纯C语言实现

    2018-12-22 23:23:52
    利用visual studio 2013平台,实现了对灰度图像的JPEG压缩,纯C语言实现,可直接移植到DSP,单片机等嵌入式平台当中
  • 包含正逆运算,用到dct2函数。 其中算法步骤如下: (1)Subtract the image intensity by 128. (2)Partition the input image into 8x8 blocks (3)Apply DCT to each 8x8 block .......
  • 多重JPEG压缩图像的压缩痕迹检测
  • matlab实现jpeg压缩过程MATLAB程序,包括分块,DCT2D,哈夫曼编码,熵编码
  • 包括 JPEG 压缩 ,解压 代码 compress.m,decompress.m,img2jpg.m,jpg2img.m四个matlab程序
  • JPEG压缩的Matlab代码,可直接运行,完整版本,注释详细。功能:将输入RGB图像转化为YUV色彩空间,并执行分块DCT变换与量化,然后将直流分量与交流分量进行行程编码与霍夫曼编码获得jpeg码流,最后计算压缩率。输入...
  • 自己写的亮度JPEG压缩,verilog。内有总模块和各个分模块的仿真,除了没有对外协议包含整个压缩过程。本人实验用的是串口作为对外协议,算法下载到FPGA中输出图像有效。
  • 它显示了 jpeg 压缩的全部内容。 该函数使用矩阵运算符实现 DCT 变换。 请注意,MATLAB 有一个可能更有效的 DCT 和 iDCT 变换函数。 阅读 ReadMe.txt 以了解有关该算法的一些详细信息。 如果你喜欢这个文件,请...
  • matlab开发-灰度图像的jpeg压缩。任何质量因素下的一个简单的jpeg matlab实现
  • matlab灰色处理代码JPEG压缩 基于《多媒体工程学图像和视频压缩》第7章的Jpeg压缩算法。 该代码是针对Matlab的,其开发是一门名为“图像和视频编码系统”的大学课程的一部分。 本课程是在Pompeu Fabra大学(巴塞罗那...
  • 本代码适用于灰度图像进行JPEG压缩,生成DCT变换后需要除于的质量因子量化表,调用代码输入不同质量因子Q函数就可以输出对应的 8*8的量化表
  • jpeg压缩的matlab代码MDSForensicsChallenge-伪造定位 该存储库提供的代码结合了文章中提出的算法: -T. Bianchi,A。De Rosa和A. Piva,“改进的JPEG图像伪造定位的DCT系数分析”,2011 IEEE国际声学,语音和信号...
  • 网络上的编码表大都不全,而且有部分错误。这一份表格是从官方的文档中扣取出来的,对照lib-jpeg的C代码修改了几处错误,是完整而且正确的。亲测没有问题。
  • 基于FPGA的jpeg压缩实现
  • jpeg压缩C语言实现

    2014-09-11 09:47:20
    jpeg压缩算法的C语言实现,代码很好,可以供研究Jpeg算法的人参考!
  • jpeg压缩的matlab代码JPEG压缩 Matlab项目的主要目的是使用JPEG压缩技术压缩预加载的图像。 该图像将采用一组二进制代码(1和0)。 然后将压缩的图像解压缩以构造原始图像。 解压缩和重构将在图像中引入一些噪声,这...
  • 行程编码,JPEG压缩编码(基本系统)的源码示例,对了解低层图像编码有重要意义
  • JPEG压缩编码系统源代码.rar C语言
  • 灰度图象的jpeg压缩 matlab
  • 易于理解的用于灰度图像 Jpeg 标准压缩的 matlab 代码
  • jpeg压缩的matlab代码ece-6258-finalproj 数字图像处理最终项目:尚待开发 该项目将UNIQUE算法应用于图像压缩。 UNIQUE代表无监督的图像质量估计。 有3个文件夹: 过滤器:此文件夹包含filter.mat文件。 该文件包含...
  • FPGA实现Jpeg压缩,和视频采集程序
  • jpeg压缩源码

    热门讨论 2013-04-25 22:03:42
    这里有三个有关jpeg压缩的源代码。 1采用VC代码实现JPEG图像压缩,DCT变换,霍夫曼编码 2JPEG图象编解码代码,代码没有注释,西北大学(美国那个西北大学)放在网上供下载的,没有别的乱七八糟的东西
  • JPEG压缩编码标准

    2017-11-01 13:04:46
    大数据量的图象信息会给存储器的存储容量,通信干线信道的带宽,以及计算机的处 理速度增加极大的压力。单纯靠增加存储器容量,提高信道带宽以及计算机的处理速度等...法来解决这个问题是不现实的,这时就要考虑压缩
  • c语言jpeg压缩

    2016-12-21 10:48:28
    c语言jpeg压缩
  • JPEG压缩教程代码

    2017-08-29 09:36:15
    这是基于libjpeg的JPEG压缩代码
  • JPEG压缩原理详解

    千次阅读 多人点赞 2019-03-25 15:36:17
    举个例子,一张800X800大小的普通图片,如果未经压缩,大概在1.7MB左右,这个体积如果存放文本文件的话足够保存一部92万字的鸿篇巨著《红楼梦》,现如今互联网上绝大部分图片都使用了JPEG压缩技术,也就是大家使用.....

    转载: http://blog.csdn.net/shelldon/article/details/54234433

    图片压缩有多重要,可能很多人可能并没有一个直观上的认识,举个例子,一张800X800大小的普通图片,如果未经压缩,大概在1.7MB左右,这个体积如果存放文本文件的话足够保存一部92万字的鸿篇巨著《红楼梦》,现如今互联网上绝大部分图片都使用了JPEG压缩技术,也就是大家使用的jpg文件,通常JPEG文件相对于原始图像,能够得到1/8的压缩比,如此高的压缩率是如何做到的呢?
            JPEG能够获得如此高的压缩比是因为使用了有损压缩技术,所谓有损压缩,就是把原始数据中不重要的部分去掉,以便可以用更小的体积保存,这个原理其实很常见,比如485194.200000000001这个数,如果我们用485194.2来保存,就是一种“有损”的保存方法,因为小数点后面的那个“0.000000000001”属于不重要的部分,所以可以被忽略掉。JPEG整个压缩过程基本上也是遵循这个步骤:
            1. 把数据分为“重要部分”和“不重要部分”
            2. 滤掉不重要的部分
            3. 保存

    步骤一:图像分割


            JPEG算法的第一步,图像被分割成大小为8X8的小块,这些小块在整个压缩过程中都是单独被处理的。后面我们会以一张非常经典的图为例,这张图片名字叫做Lenna,据说是世界上第一张JPG图片,这张图片自从诞生之日开始,就和图像处理结下渊源,陪伴了无数理工宅男度过了的一个个不眠之夜,可谓功勋卓著,感兴趣的朋友可以在这里了解到这张图片的故事。

         分割=>       

    步骤二:颜色空间转换RGB->YCbCr


            所谓“颜色空间”,是指表达颜色的数学模型,比如我们常见的“RGB”模型,就是把颜色分解成红绿蓝三种分量,这样一张图片就可以分解成三张灰度图,数学表达上,每一个8X8的图案,可以表达成三个8X8的矩阵,其中的数值的范围一般在[0,255]之间。

     

            不同的颜色模型各有不同的应用场景,例如RGB模型适合于像显示器这样的自发光图案,而在印刷行业,使用油墨打印,图案的颜色是通过在反射光线时产生的,通常使用CMYK模型,而在JPEG压缩算法中,需要把图案转换成为YCbCr模型,这里的Y表示亮度(Luminance),Cb和Cr分别表示绿色和红色的“色差值”。
            “色差”这个概念起源于电视行业,最早的电视都是黑白的,那时候传输电视信号只需要传输亮度信号,也就是Y信号即可,彩色电视出现之后,人们在Y信号之外增加了两条色差信号以传输颜色信息,这么做的目的是为了兼容黑白电视机,因为黑白电视只需要处理信号中的Y信号即可。
            根据三基色原理,人们发现红绿蓝三种颜色所贡献的亮度是不同的,绿色的“亮度”最大,蓝色最暗,设红色所贡献的亮度的份额为KR,蓝色贡献的份额为KB,那么亮度为

    (1.1)

            根据经验,KR=0.299,KB=0.114,那么

    (1.2)

            蓝色和红色的色差的定义如下

    (1.3)
    (1.4)

            最终可以得到RGB转换为YCbCr的数学公式为

    (1.5)

    YCbCr模型广泛应用在图片和视频的压缩传输中,比如你可以留意一下电视或者DVD后面的接口,就可以发现色差接口。

            这是有道理的,还记得我们在文章开始时提到的有损压缩的基本原理吗?有损压缩首先要做的事情就是“把重要的信息和不重要的信息分开”,YCbCr恰好能做到这一点。对于人眼来说,图像中明暗的变化更容易被感知到,这是由于人眼的构造引起的。视网膜上有两种感光细胞,能够感知亮度变化的视杆细胞,以及能够感知颜色的视锥细胞,由于视杆细胞在数量上远大于视锥细胞,所以我们更容易感知到明暗细节。比如说下面这张图

                

           可以明显看到,亮度图的细节更加丰富。JPEG把图像转换为YCbCr之后,就可以针对数据得重要程度的不同做不同的处理。这就是为什么JPEG使用这种颜色空间的原因。

    步骤三:离散余弦变换


            这次我们来介绍JPEG算法中的核心内容,离散余弦变换(Discrete cosine transform),简称DCT。
            离散余弦变换属于傅里叶变换的另外一种形式,没错,就是大名鼎鼎的傅里叶变换。傅里叶是法国著名的数学家和物理学家,1807年,39岁的傅里叶在他的一篇论文里提出了一个想法,他认为任何周期性的函数,都可以分解为为一系列的三角函数的组合,这个想法一开始并没有得到当时科学界的承认,比如当时著名的数学家拉格朗日提出质疑,三角函数无论如何组合,都无法表达带有“尖角”的函数,一直到1822年拉格朗日死后,傅里叶的想法才正式在他的著作《热的解析理论》一书中正式发表。
             金子总会闪光,傅里叶变换如今广泛应用于数学、物理、信号处理等等领域,变换除了它在数学上的意义外,还有其哲学上的伟大意义,那就是,世上任何复杂的事物,都可以分解为简单的事物的组合,而这个过程只需要借助数学工具就可以了。但是当年拉格朗日的质疑是正确的,三角函数的确无法表达出尖角形状的函数,不过只要三角函数足够多,可以无限逼近最终结果。比如下面这张动图,就动态描述了一个矩形方波,是如何做傅里叶分析的。

     

     

            当我们要处理的不再是函数,而是一堆离散的数据时,并且这些数据是对称的话,那么傅里叶变化出来的函数只含有余弦项,这种变换称为离散余弦变换。举个例子,有一组一维数据[x0,x1,x2,…,xn-1],那么可以通过DCT变换得到n个变换级数Fi

    (2.1)

            此时原始数据Xi可以通过离散余弦变换变化的逆变换(IDCT)表达出来

    (2.2)

            也就是说,经过DCT变换,可以把一个数组分解成数个数组的和,如果我们数组视为一个一维矩阵,那么可以把结果看做是一系列矩阵的和

    (2.3)


            举个例子,我们有一个长度为8的数字,内容为50,55,67,80,-10,-5,20,30,经过DCT转换,得到8个级数为287.0,106.3,14.2,-110.8,9.2,65.7,-8.2,-43.9,根据公式2.3把这个数组转换为8个新的数组的和,如果我们使用图像来表达的话,就可以发现DCT转换的有趣之处了


    [50,55,67,80,-10,-5,20,30]
     数组0
      [35.9,35.9,35.9,35.9,35.9,35.9,35.9,35.9]
     数组1
      [26.0,22.1,14.8,5.2,-5.2,-14.8,-22.1,-26.1]
     数组2
      [3.3,1.4,-1.4,-3.3,-3.3,-1.4,1.4,3.3]
     数组3
      [-23.0,5.4,27.2,15.4,-15.4,-27.2,-5.4,23.0]
     数组4
      [1.6,-1.6,-1.6,1.6,1.6,-1.6,-1.6,1.6]
     数组5
      [9.1,-16.1,3.2,13.6,-13.6,-3.2,16.1,-9.1]
     数组6
      [-0.8,1.9,-1.9,0.8,0.8,-1.9,1.9,-0.8]
     数组7
      [-2.1,6.1,-9.1,10.8,-10.8,9.1,-6.1,2.1]

            奥妙之处在于,经过DCT,数据中隐藏的规律被发掘了出来,杂乱的数据被转换成几个工整变化的数据。DCT转换后的数组中第一个是一个直线数据,因此又被称为“直流数据”,简称DC,后面的数据被称为“交流数据”,简称AC,这个称呼起源于信号分析中的术语。
            在JPEG压缩过程中,经过颜色空间的转换,每一个8X8的图像块,在数据上表现为3个8X8的矩阵,紧接着我们对这三个矩阵做一个二维的DCT转换,二维的DCT转换公式为

           

            DCT的威力究竟有多大,我们可以做一个实际的测试,比如一个所有数值都一样的矩阵,经过DCT转换后,将所有级数组合成一个新的矩阵

            

            可以看到,经过DCT转换,矩阵的“能量”被全部集中在左上角上的直流分量F(0,0)上,其他位置都变成了0。
            在实际的JPEG压缩过程中,由于图像本身的连贯性,一个8X8的图像中的数值一般不会出现大的跳跃,经过DCT转换会有类似的效果,左上角的直流分量保存了一个大的数值,其他分量都接近于0,我们以Lenna左上角第一块图像的Y分量为例,经过变换的矩阵为

           

             可以看到,数据经过DCT变化后,被明显分成了直流分量和交流分量两部分,为后面的进一步压缩起到了充分的铺垫作用,可以说是整个JPEG中最重要的一步,后面我们会介绍数据量化。

      

    步骤四:数据量化


            经过上一节介绍的离散余弦变换,图像数据虽然已经面目全非,但仍然是处于“可逆”的状态,也就是说我们还没有进入“有损”的那一步。这次我们来玩真的,看一下数据中的细节是如何被滤去的。先来考察一下要对付的问题是什么,经过颜色空间转换和离散余弦变换,每一个8X8的图像块都变成了三个8X8的浮点数矩阵,分别表示Y,Cr,Cb数据,比如以其中某个亮度数据矩阵举例,它的数据如下

            我们的问题是,在可以损失一部分精度的情况下,如何用更少的空间存储这些浮点数?答案是使用量子化(Quantization),简称量化。“量子”这个概念来自于物理学,意思是说连续的能量可以看做是一个个单元体的组合,看起来高端大气,其实很简单,比如游戏中在处理角色面朝方向时,一般并不是使用0到2π这样的浮点数,而是把方向分成16个区间,用0到16这样的整数来表示,这样只用4个bit就足够了。JPEG提供的量子化算法如下: 

    (3.1)

            其中G是我们需要处理的图像矩阵,Q称作量化系数矩阵(Quantization matrices),JPEG算法提供了两张标准的量化系数矩阵,分别用于处理亮度数据Y和色差数据Cr以及Cb。

    标准亮度量化表

    标准亮度量化表

    标准色差量化表

    标准色差量化表


            其中round函数是取整函数,但考虑到了四舍五入,也就是说

    (3.2)

            比如上面数据,以左上角的-415.38为例,对应的量子化系数是16,那么round(-415.38/16)=round(-25.96125)=-26。最终得到的量子化后的结果为

            可以看到,一大部分数据变成了0,这非常有利于后面的压缩存储。这两张神奇的量化表也是有讲究的,还记得我们在第一节中所讲的有损压缩的基本原理吗,有损压缩就是把数据中重要的数据和不重要的数据分开,然后分别处理。DCT系数矩阵中的不同位置的值代表了图像数据中不同频率的分量,这两张表中的数据时人们根据人眼对不不同频率的敏感程度的差别所积累下的经验制定的,一般来说人眼对于低频的分量必高频分量更加敏感,所以两张量化系数矩阵左上角的数值明显小于右下角区域。在实际的压缩过程中,还可以根据需要在这些系数的基础上再乘以一个系数,以使更多或更少的数据变成0,我们平时使用的图像处理软件在省城jpg文件时,在控制压缩质量的时候,就是控制的这个系数。
            在进入下一节之前,矩阵的量化还有最后一步要做,就是把量化后的二维矩阵转变成一个一维数组,以方便后面的霍夫曼压缩,但在做这个顺序转换时,需要按照一个特定的取值顺序。

            这么做的目的只有一个,就是尽可能把0放在一起,由于0大部分集中在右下角,所以才去这种由左上角到右下角的顺序,经过这种顺序变换,最终矩阵变成一个整数数组

    -26,-3,0,-3,-2,-6,2,-4,1,-3,0,1,5,,1,2,-1,1,-1,2,0,0,0,0,0,-1,-1,0,0,0,0,…,0,0


            后面的工作就是对这个数组进行再一次的哈夫曼压缩,已得到最终的压缩数据。

      

    步骤五:哈弗曼编码


            JPEG压缩的最后一步是对数据进行哈弗曼编码(Huffman coding),哈弗曼几乎是所有压缩算法的基础,它的基本原理是根据数据中元素的使用频率,调整元素的编码长度,以得到更高的压缩比。
            举个例子,比如下面这段数据        “AABCBABBCDBBDDBAABDBBDABBBBDDEDBD”

            这段数据里面包含了33个字符,每种字符出现的次数统计如下

    字符ABCDE
    次数 6 15 2 9 1

            如果我们用我们常见的定长编码,每个字符都是3个bit。

    字符ABCDE
    编码 001 010 011 100 101

            那么这段文字共需要3*33 = 99个bit来保存,但如果我们根据字符出现的概率,使用如下的编码

    字符ABCDE
    编码 110 0 1110 10 1111

            那么这段文字共需要3*6 + 1*15 + 4*2 + 2*9 + 4*1 = 63个bit来保存,压缩比为63%,哈弗曼编码一般都是使用二叉树来生成的,这样得到的编码符合前缀规则,也就是较短的编码不能够是较长编码的前缀,比如上面这个编码,就是由下面的这颗二叉树生成的。

            我们回到JPEG压缩上,回顾上一节的内容,经过数据量化,我们现在要处理的数据是一串一维数组,举例如下:

    ①原始数据
    35,7,0,0,0,-6,-2,0,0,-9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,…,0

            在实际的压缩过程中,数据中的0出现的概率非常高,所以首先要做的事情,是对其中的0进行处理,把数据中的非零的数据,以及数据前面0的个数作为一个处理单元。

    ①原始数据
    35,7,0,0,0,-6,-2,0,0,-9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,…,0
    ②RLE编码 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0,8 0,0,…,0

            如果其中某个单元的0的个数超过16,则需要分成每16个一组,如果最后一个单元全都是0,则使用特殊字符“EOB”表示,EOB意思就是“后面的数据全都是0”,

    ①原始数据
    35,7,0,0,0,-6,-2,0,0,-9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,…,0
    ②RLE编码 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0,8 0,0,…,0 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0 0,0,8 0,0,…,0 (0,35) (0,7) (3,-6) (0,-2) (2,-9) (15,0) (2,8) EOB

           * RLE - Run-Length Encoding,即行程编码,对于连续重复出现的字符有很好的压缩率。编码后为(字符出现次数,字符)。

           * JPEG 中实际使用的是(字符出现次数 - 1,字符)

     

            其中(15,0)表示16个0,接下来我们要处理的是括号里右面的数字,这个数字的取值范围在-2047~2047之间,JPEG提供了一张标准的码表用于对这些数字编码:

    ValueSizeBits
    00
    -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 0 0000,…,0 1111 1 0000,…,1 1111 -63,…,-32 32,…,63 6 00 0000,… …,11 1111 -127,…,-64 64,…,127 7 000 0000,… …,111 1111 -255,…,-128 128,…,255 8 0000 0000,… …,1111 1111 -511,…,-256 256,…,511 9 0 0000 0000,… …,1 1111 1111 -1023,…,-512 512,…,1023 10 00 0000 0000,… …,11 1111 1111 -2047,…,-1024 1024,…,2047 11 000 0000 0000,… …,111 1111 1111

            举例来说,第一个单元中的“35”这个数字,在表中的位置是长度为6的那组,所对应的bit码是“100011”,而“-6”的编码是”001″,由于这种编码附带长度信息,所以我们的数据变成了如下的格式。

    ①原始数据
    35,7,0,0,0,-6,-2,0,0,-9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,…,0
    ②RLE编码 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0,8 0,0,…,0 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0 0,0,8 0,0,…,0 (0,35) (0,7) (3,-6) (0,-2) (2,-9) (15,0) (2,8) EOB ③BIT编码 (0,6, 100011) (0,3, 111) (3,3, 001) (0,2, 01) (2,4, 0110) (15,-) (2,4, 1000) EOB

            括号中前两个数字分都在0~15之间,所以这两个数可以合并成一个byte,高四位是前面0的个数,后四位是后面数字的位数。

    ①原始数据
    35,7,0,0,0,-6,-2,0,0,-9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,…,0
    ②RLE编码 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0,8 0,0,…,0 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0 0,0,8 0,0,…,0 (0,35) (0,7) (3,-6) (0,-2) (2,-9) (15,0) (2,8) EOB ③BIT编码 (0,6, 100011) (0,3, 111) (3,3, 001) (0,2, 01) (2,4, 0110) (15,-) (2,4, 1000) EOB (0x6,100011) (0x3,111) (0x33,001) (0x2,01) (0x24,0110) (0xF0,-) (0x24,1000) EOB

            对于括号前面的数字的编码,就要使用到我们提到的哈弗曼编码了,比如下面这张表,就是一张针对数据中的第一个单元,也就是直流(DC)部分的哈弗曼表,由于直流部分没有前置的0,所以取值范围在0~15之间。

    LengthValueBits
    3 bits04
    05
    03
    02
    06
    01
    00 (EOB)
    000
    001
    010
    011
    100
    101
    110
    4 bits 07 1110 5 bits 08 1111 0 6 bits 09 1111 10 7 bits 0A 1111 110 8 bits 0B 1111 1110

            举例来说,示例中的DC部分的数据是0x06,对应的二进制编码是“100”,而对于后面的交流部分,取值范围在0~255之间,所以对应的哈弗曼表会更大一些

    LengthValueBits
    2 bits01
    02
    00
    01
    3 bits 03 100 4 bits 00 (EOB)
    04
    11 1010
    1011
    1100 5 bits 05
    12
    21 1101 0
    1101 1
    1110 0 6 bits 31
    41 1110 10
    1110 11 … … … 12 bits 24
    33
    62
    72 1111 1111 0100
    1111 1111 0101
    1111 1111 0110
    1111 1111 0111 15 bits 82 1111 1111 1000 000 16 bits 09

    FA 1111 1111 1000 0010

    1111 1111 1111 1110

            这样经过哈弗曼编码,并且序列化后,最终数据成为如下形式

    ①原始数据
    35,7,0,0,0,-6,-2,0,0,-9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,…,0
    ②RLE编码 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0,8 0,0,…,0 35 7 0,0,0,-6 -2 0,0,-9 0,0,…,0 0,0,8 0,0,…,0 (0,35) (0,7) (3,-6) (0,-2) (2,-9) (15,0) (2,8) EOB ③BIT编码 (0,6, 100011) (0,3, 111) (3,3, 001) (0,2, 01) (2,4, 0110) (15,-) (2,4, 1000) EOB (0x6,100011) (0x3,111) (0x33,001) (0x2,01) (0x24,0110) 0xF0 (0x24,1000) EOB ④哈弗曼编码 100 100011 100 111 1111 1111 0101 001 01 01 1111 1111 0100 0110 1111 1111 001 1111 1111 0100 1000 1010 ⑤序列化
    100100011100111111111110101001010111111111010001101111111100111111111010010001010
    91 CF FE A5 7F D1 BF CF FA 45

            最终我们使用了10个字节的空间保存了原本长度为64的数组,至此JPEG的主要压缩算法结束,这些数据就是保存在jpg文件中的最终数据。


    一个JPEG图片实例分析

     我们可以打开 JPEG 文件查看里面的内容,即可看到上面的各个标记段:

    在头部有 FFD8 ,表示图像的开始;结束部分有 FFD9 ,表示图像的结束。

    在中间有两个量化表 DQT 对应的标记 FFDB ;

    还有图像大小信息对应的 FFC0

    再后面有四个 Haffman 表对应的 FFC4 ;

     

    一般一个 JPEG 文件里会有 2 类 Haffman 表:一个用于 DC 一个用于 AC ,也即实际有 4个表,亮度的 DC,AC 两个,色度的 DC,AC 两个。

    然后是图像数据段标记 FFDA;

     

    我们再来看看各个标记的细部,具体分析一下各个部分的含义。

    1、图片的识别信息

    SOI,Start of Image,图像开始,2字节,固定值0xFFD8

    JEPG APP0 应用程序保留标记0

     字段名称

    字段长度

     Comments

    标记代码 marker

    2 bytes

    固定值0xFF, 0xE0

    数据长度 length

    2 bytes

    APP0总长度,不过括marker,但是包括length本身

    标识符 identifier

    5 bytes

    固定的字符串"JFIF\0"

    版本号 version

    2 bytes

    一般为0x0101或者0x0102,表示JFIF的版本号1.1 或 1.2

    像素单位 unit

    1 bytes

    坐标单位,0没有单位; 1 pixel/inch;2 pixel/cm

    水平像素数目 Xdensity

    2 bytes

     取值范围未知

    垂直像素数目 YDensity

    2 bytes

     取值范围未知

    缩略图水平像素数目

    1 byte

     取值范围未知

    缩略图垂直像素数目

    1 byte

     取值范围未知

    缩略图RGB位图

    3n bytes

    n = Xthumbnail * Ythumbnail, 这是一个24bits/piexl的RGB位图
    如果没有微缩图像(这种情况更常见),则字段“缩略图水平像素数目”和字段“缩略图垂直像素数目”的值均为0。

     

    上面的内容,在标记 FFE0 后,即为长度16。

    然后是5字节的 JFIF 标识符号,说明这是一个 JPEG 压缩的文件。

    然后是主/次版本号码。下一个为 XY 像素的单位,这里为1,表示单位为点数/英寸。

    然后是 XY 方向的像素密度,这里是 96DPI,最后是缩略图有关信息,这里为0。

     

    2、量化表的实例

    上面这个内容,FFDB 标记后的长度值为67,接下来的是 QT 信息,占一个字节;

    这里是0,表示这个 QT 表编号为0,并且精度是8bit。然后后面就是64个8x8的 QT 表的各个 item 了。

    也即第一个 DQT 量化表的内容表示为十进制是:

    这个表即为 JPEG 亮度量化表。

     

    第二个量化表的内容为:

    这个表的内容即为 JPEG 色度量化表。

    当你打开不同的 JPEG 文件,你会看到这两个表可能也是会有区别的。这个主要是使用了不同的量化方式的结果。

     

    3、图像信息段

    上面这个内容,FFC0 标记后即是长度,为17;

    然后是一个字节的数据精度,通常是为8,代表样本位数。

    接下来是图片的高度,占两字节,这里即为8,然后是图片的宽度,也为8,这也就是我们定义的8x8的内容。

    然后是 component 的个数,这里是3,表示 YUV。接下来是三组数据,每组数据里,第一个是 component ID,第二个是采样系数,这里 Y 的采样系数为22,说明垂直是2,水平是2。

    再后面就是量化表的编号了。

     

    4、Haffman 表的实例

    上面这个内容,FFC4 标记后的内容为数据长度,再接着的1字节为 Huffman Table 的信息,低4位是 HT ID 号,第5位是 HT 表类型标记,再高三位是为0。

    第一个 DHT 表,00,类型为 DC table,HT ID 号为 0;

    第二个 DHT 表,10,类型为 AC table,HT ID 号也为 0;

    第三个 DHT 表,01,类型为 DC table,HT ID 号为 1;

    第四个 DHT 表,11,类型为 AC table,HT ID 号为 1;

    即前两个表为Y亮度分量的 DC/AC 表,后两个为 UV 色度分量的 DC/AC 表。

     

    以第一个表为例,因为长度只有 31,那么 00 后面的 16 字节,即绿色部分:

    组号为 1 的组中,代码有 0 个;

    组号为 2 的,代码有 1 个;

    组号为 3 的代码有 5 个;

    组号为 4/5/6/7/8/9 的代码各 1 个。

    总共 12 个。

    再看后续的数据:

    00 01 02 03 04 05 06 07 08 09 0A 0B

    即对应:

    其他未出现的组号,对应的数据未使用到。也就是说前面提到过的范式 Huffman 编码里,目前只使用部分数据即可,原因是这个 8x8 的图像数据很小。

    第二个 DHT 表就更复杂些了,长度有 181。

     

    5、图像数据段

    这里 SOS 段,长度为 12,后面所含有的 component 数量为 3 个,也即 Y UV。然后后面是各 component 的编号,及对应所使用的 Huffman 表的 ID 是多少。

    在这个段的后面就是所有压缩后的数据。直到结束的问题,即 FFD9,EOI(End Of Image)。

     

    展开全文
  • 通过估计未对齐的双JPEG压缩来进行图像篡改定位

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 84,267
精华内容 33,706
关键字:

jpeg压缩

友情链接: qhrbh.zip