孝感建设银行网站,知名网站开发语言,wordpress技术类模板下载,哪个地方旅游网站做的比较好JPEG文件格式简单分析
作者#xff1a;小爽
摘要#xff1a;
这篇文章大体上介绍了JPEG文件的结构信息以及它的压缩算法和编码方式。使读者能够对JPEG文件格式有大体上的了解。为读者进一步进行学习JPEG文件压缩做好准备 关键字#xff1a;十六进制#xff0c;段格式小爽
摘要
这篇文章大体上介绍了JPEG文件的结构信息以及它的压缩算法和编码方式。使读者能够对JPEG文件格式有大体上的了解。为读者进一步进行学习JPEG文件压缩做好准备 关键字十六进制段格式编码 一、 JPEG文件格式概述
图像和动画的存储方式是一个很重要的问题。幸好我们有了数据压缩有了JPEG等多种压缩存储图像的文件格式我们今天才能够拿着小小的一个存储器却存上许多张色彩鲜艳的图片。如果没有图像压缩算法也许我们的多媒体时代就会晚到来许多年。
JPEG图像存储格式一个比较成熟的图像有损压缩格式虽然一个图片经过转化为JPEG图像后一些数据会丢失但是人眼是很不容易分辨出来这种差别的。也就是说JPEG图像存储格式既满足了人眼对色彩和分辨率的要求又适当的去除了图像中很难被人眼所分辨出的色彩在图像的清晰与大小中JPEG找到了一个很好的平衡点。
虽然图像转化为JPEG格式会减小很多但是并不是文件就变得简单了相反JPEG文件的格式是比较复杂的。不经过认真地分析是不容易弄懂它的。 二、 JPEG文件的存储方式
JPEG文件的格式是分为一个一个的段来存储的但并不是全部都是段段的多少和长度并不是一定的。只要包含了足够的信息该JPEG文件就能够被打开呈现给人们。JPEG文件的每个段都一定包含两部分一个是段的标识它由两个字节构成第一个字节是十六进制0xFF第二个字节对于不同的段这个值是不同的。紧接着的两个字节存放的是这个段的长度除了前面的两个字节0xFF和0xXXX表示不确定。他们是不算到段的长度中的。注意这个长度的表示方法是按照高位在前低位在后的与Intel的表示方法不同。比方说一个段的长度是0x12AB那么它会按照0x120xAB的顺序存储。但是如果按照Intel的方式高位在后低位在前的方式会存储成0xAB0x12而这样的存储方法对于JPEG是不对的。这样的话如果一个程序不认识JPEG文件某个段它就可以读取后两个字节得到这个段的长度并跳过忽略它。
本人曾经编写过一个读取JPEG文件信息的程序该程序能够读取JPEG文件中包含的段的信息并显示出来。下面是一个JPEG图片的信息片断 SOI APP0 Length: 0x10 DQT DQT [0]: 8 6 5 8 12 20 26 31 6 6 7 10 13 29 30 28 7 7 8 12 20 29 35 60 7 9 11 15 26 44 50 31 9 11 19 28 34 56 52 0 12 18 28 32 61 52 0 46 25 32 39 57 52 0 60 0 36 46 39 49 253 50 0 50 Length: 0x43 DQT DQT [1]: 9 9 12 24 50 50 50 50 9 11 13 33 50 50 50 50 12 13 28 50 50 50 50 50 24 33 50 50 50 50 50 50 50 50 50 50 50 50 50 0 50 50 50 50 50 50 0 50 50 50 50 50 50 0 50 0 50 50 50 50 253 50 0 50 Length: 0x43 SOF0 Image Height: 173 Image Width: 401 Number of Frame(s): 3 **************** Content ID: 1 H Factor: 2 V Factor: 2 QT ID: 0 **************** Content ID: 2 H Factor: 1 V Factor: 1 QT ID: 1 **************** Content ID: 3 H Factor: 1 V Factor: 1 QT ID: 1 Length: 0x11 DHT Type: DC TABLE ID: 0 Length: 0x1f DHT Type: AC TABLE ID: 0 Length: 0xb5 DHT Type: DC TABLE ID: 1 Length: 0x1f DHT Type: AC TABLE ID: 1 Length: 0xb5 SOS Length: 0xc -Will Not Process This Seg.
FATAL ERROR: File Structure Does NOT Support. 你首先会想到为什么最后会出现一个错误的信息呢这是因为在SOSStart Of Scan段的后面就是编码后的一行一行的图像信息。不再是段的结构了。在开始的SOIStart Of Image不是一个段它是文件的开始它的值也是类似于0xFF0xXX的结构SOI的具体数值清自己察看相关书籍本文章中将不作重点介绍但是后面没有段的长度。在文件的最后有一个EOIEnd Of Image的标识它的结构和SOI是类似的。它标志着文件的结束。
在这中间包含了APP0段DQT段SOF0段DHT段SOS段。有的段的个数是不唯一的比方说DQT段。我们现在重点地介绍各个段的作用。 三、 JPEG文件中段的介绍
APP0段中主要存储的是图片的识别信息字符串”JFIF\0”、一些分辨率的信息以及缩略图的信息。在我的实际测试中发现并不是所有的JPEG文件都有APP0段的有的仅是有APP2之类的其他段但是每个文件中肯定是包含APPX的段X可以取得的值可以查阅相关文档。我个人估计这些APPX的段的信息应该是大同小异。这个的验证还有待本人进一步的学习目前只能说到这里。
DQT段的内容是量化表的信息。众所周知一个颜色可以分为RGB红、绿、兰三个分量这三色光组成了我们可以见到的所有色彩。但是在JPEG文件中RGB色彩格式需要先转化为YUV的格式。Y分量代表了亮度信息UV分量代表了色差信息。相比之下人眼对于Y分量更为敏感。量化表的作用就是对于一些不需要的量进行去除这也是JPEG有损压缩损失数据的关键。上面的输出可以看到两个量化表一个给Y分量另一个给UV分量。其实他们也可以共用一个量化表。一个量化的结果如下所示摘自《JPEG压缩编码标准》
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
我们可以看到量化后出现了大量的0这种结果很有利于我们进行下一步的数据压缩的。至于为什么是8x8的大小待会你就知道了。
SOF0段的内容是图像的大小信息每个像素的位数信息以及YUV每个分量分别得的采样信息这部分如果读者想要进一步学习请参考相应书籍和文档。JPEG文件图像的编码是一个方块一个方块进行的每块的大小为8x8大小如果图像不是整数个方块的大小那么就对图像补齐为整数个大小。简略地说采样信息就是如何按组记录YUV的信息即若干个Y方块若干个U方块若干个V方块经过量化的数据再次经过编码后组成一组记录保存在SOS段结束后。
DHT段的内容是一个重头戏如果没有它JPEG压缩效率就不会那么高了。它内部定义的是一个Huffman表不同的DHT段定义不同的Huffman表有的是直流量的表有的是交流量的表。什么是直流量什么是交流量呢待会我再作介绍。最多的Huffman表示几个呢YUV各一个直流交流各一个因为YUV每个分量都有直流和交流所以最多时Huffman表有3x2个也就是可以有6个DHT段。该文件中有4个DHT表您可以大概猜出来是哪几个表么Y的直流和交流各一个Huffman表UV和起来直流和交流各一个Huffman表。这样说应该比较合理吧。
好了现在我们应该弄明白什么是交流量什么是直流量了。还举上面那个有许多个0的8x8的表的例子说所谓交流量是经过量化后的块内部除了左上角15那个值的其余值。实际上块与块之间左上角那个值是用直流Huffman表来单独编码的。不与块内部一同编码。虽然不同的编码但是要注意的事不同的编码方式并不意味着它们是不在一起的具体的存储编码后的数据的时候还是按照若干个Y方块若干个U方块若干个V方块经过量化的数据再次经过编码后组成一组记录来存储的。
SOS段的内容是关于YUV每个分量的直流和交流各使用那个Huffman表来编码的。
四、 JPEG文件十六进制代码解析
我觉得如果想要的了解JPEG对十六进制代码的观察是必不可少的。不要认为这样有多难我会让你知道这是很简单的。目前我们只需要了解我们能够了解的东西就可以了。要记住每个段的开始是0xFF0xXX紧接着两个字节是长度信息。 可以看到上图被选定的标记是SOI标记。 上图被选定的段是APP0段。 紧接着的段是DQT段这个JPEG文件有两个DQT段。这里需要强调一点的是包括量化表在内8x8的块的值是按照Z形来保存量化表8x8的数据的。而不是按照一行一行的保存的。这样做的好处是能够让实际上相邻的像素点保存后也排列得比较近便于压缩和编码。如下图所示 摘自《JPEG压缩编码标准》 上图标记的段是DHT段一共有4个DHT段。 这个段是SOS段在这个段的后面就是所有压缩后的数据。
每段的具体信息在这里我就不详细介绍了网上有很多相关的文章如果有兴趣的话可以去查找阅读。 五、 图像数据块内的编码方式
其实图像数据块的编码是比较麻烦的它涉及到了行程编码Huffman编码等编码方式。这部分很多文档说得都不是很清楚我力求去除内部比较麻烦的部分再通过简单的语言让大家明白原理这样大家如果有兴趣进行下一步的研究也会比较容易上手的。
我们还是使用那刚才那个包含很多0的量化后的8x8的数据块来说明。我们把块内剩余的63个数据用行程编码来编码。经过行程编码后的数据的格式是x,y。x表示的是从当前位置开始有多少个连续的零y表示这些连续的0的后面的第一个非零的数是多少。但是为了解决存储的问题和进行进一步的压缩。最后的压缩格式变为x,yz。xy占有一个字节的长度。z的长度不固定需要根据y的值来判断。x仍代表从当前位置开始有几个连续的零但是因为x只能占有四位的长度也就是它的最大值是15所以当多于16个连续的零的时候。会用一个字节的(15,0)来代替前面的16个0然后继续编码注意这时候没有z部分。当块结束或者当前块后面剩余的都是零的时候就用0,0即EOB代替同样也是没有z部分。前面说到z的长度不固定需要根据y的值来判断这是为什么呢简单的来说z的长度是不一定的在1~15的范围内。Y的作用简单的来说表示的是z的二进制位数1~15也正好是4位二进制的值能够表示的。然后把xy合成的一个字节单独提取出来利用DHT里面的Huffman表来进行编码。这样编码的长度又能够被压缩了。