图片的格式与压缩

                    BMP是一种与硬件无关的图像文件格式,采用位映射的存储格式,除了图像深度可选,不采用其他的任何压缩,因此BMP图片占用的空间很大。BMP图片的图像深度可选1bit、4bit、8bit、16bit、24bit、32bit,BMP文件存储为数据时,图像的扫描方式是按从左到右、从上到下的顺序。

            典型BMP文件有三部分组成:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;位图信息数据结构,它包含有BMP图像的宽、高、压缩方法以及定义颜色等。

            JPEG是Joint Photographic Experts Group(联合去向专家组)的缩写,文件后缀名为.jpg或.jpeg,是一种有损压缩格式,能够将图像压缩在很小存储空间,图像中重复或不重要的资料会被丢失,因此造成图像数据的损伤,尤其过高的压缩比例,将事最终解压的图片质量降低。JPEG的压缩比例通常在10:1到40:1之间,压缩比越大品质越低。JPEG格式压缩的主要是高频信息,对色彩信息保留比较好,适用于互联网。

            可以使用winhex打开一个JPEG图片来查看JPEG图片的数据,0xFF,0xD8是图像开始的标记。标识数据压缩的开始,标记是用来标识压缩数据格式中不同是结构单元的,所有的标记都是有1个0xFF字节和一个不等于0或0xFF自己组成的:

                  0xFF,0xE0:应用数据的标记(APP0),标识应用数据段的开始

                  0x00,0x10:应用数据长度参数(Lp),该参数本身长度为两个字节,其值表示应用数据段包含的字节数,但是不包括APP0两个字节,长度为16个字节。

                  0x4A,0x46,0x49,0x46,0x00:文件标识符,即"JFIF"+"NUL"的ASCII码;

                  0x01,0x01:文件版本号,一般为0x01 0x01 或0x01 0x02;

                      0x01:表示X和Y的密度单位,值为0,无单位,只为1单位为“点数/英寸”,值为2 单位为"点数/厘米"

                  0x00 0x60:表示X轴方向的密度。

                  0x00  0x60:表示Y轴方向的密度。

                  

                   0xFF  0xDB:定义量化表标记(DQT)标明量化表说明参数的开始,可能有多个量化表标记,分别用量化表0、量化表1....量化表N。这里表示量化表0;

                   0x00 0x43:量化表的长度参数,其值表示量化表包含的字节个数,这里长度为67个字节。

                   0x00 :前4位为量化表元素精度参数,值为0表示元素精度为8,值为1表示量化表元素精度为16.后4位为量化表目标标识符,指定位于解码器中的4个可能目标中的1个用于安装量化表,这里只目标0;

                   0x08 0x06 0x06 .... 0x32 :量化表元素,64个字节。

                   0xFF  0xDB:量化表标记,这里表示量化表。

                   0x00 0x43:量化表长度参数。

                    0x01:前4位为量化表的精度参数,后4位为量化表的目标表示符,这里为量化表1.

                   0x09 0x09 .... 0x32 ,共64个字节的量化表元素。

                   0xFF 0xC0:帧开始标记,下标为0表示编码过程类型为DCT;

                   0x00 0x11:帧头标长度参数,该参数本身长度为两个字节,表示帧头标包含的字节数,这里的长度为17个字节。

                  0x08:采样精度,这里为8位。

                  0x00 0xB5:行数(Y),指定源图像中最大的行数,这里为181行。

                  0x01 0x40:每行样本数(X),指定源图像中每行的最大采样数320,

                  因为我保存的图像像素点数为320*240,所以这个图像的行数和列数与实际图像大小相关。

                  0x03:帧中图像的分量数(Nf),指定帧中源图像的分量数。

                  0x01:分量标记符,用来指明帧分量说明参数序列中的哪一个分量,这里是C1,即第一个分量。

                  0x22:前4位为水平的采样因子H,表示指定分量水平尺寸和最大图像尺寸X之间的关系,后4位为垂直采样因子V,指定分量垂直尺寸和最大图像尺寸Y之间的关系。

                  0x00:量化表目标选择器,用来选择4个可能量化表目标中的哪一个,从中检索用于本分量的DCT系数逆量化的量化表,这里表示本分量选择量化表0.

                   0x02:分量标记符,这里是C2,即第二个分量。

                   0x11:前4位为水平采样因子(H2);后4位为垂直采样因子(V2).

                   0x01:量化表目标选择器,这里表示本分量选择量化表1;

                   0x03:分量标记符,这里是C3,即第三个分量。

                   0x11:前4位为水平采样因子H3,后四位为垂直采样因子V3.

                   0x01:量化表目标选择器,这里表示本分量选择量化表1.

                   

                   0xFF 0xC4: 哈夫曼表定义参数的开始。

                   0x00 0x1F: 哈夫曼表的长度参数表示哈夫曼表的字节数,长度为31个字节。 

                   0x00: 前4位为表类型,值为0代表DC表或无失真,值为1 代表AC表;后4位是哈夫曼表目标标志符,指定位于解码器中的4个可能目标中的1个用于安装哈夫曼表,这表表示的是DC-0(类型-目标)哈夫曼表;

                    0x00 0x01 0x05 0x01 0x01 0x01 0x01 0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 :长度为i的哈夫曼表共16个字节,分别为JPEG说明中允许的哈夫曼代码长度为1到16的每个码长指定代码数目,这里表示代码长度为1的哈夫曼代码有0个,代码长度为2的哈夫曼代码有1个,代码长度为3的哈夫曼代码有5个等等。

                   0x00 0x01 0x02 0x3 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0B,针对代码数目列出长度为i的哈夫曼代码值,如下:

                   L1=0,没有码长为1的哈夫曼代码。

                   L2=1,码长为2的哈夫曼代码值是0x00.

                   L3=5, 码长为3的哈夫曼代码值是0x01 0x02 0x03 0x04 0x05.

                   L4=1, 码长为4的哈夫曼码值是0x6。

                   L5=1  码长为5的哈夫曼码值是0x7。              

                   L6=1  码长为6的哈夫曼码值是0x8。

                   L7=1  码长为7的哈夫曼码值是0x9。

                   L8=1  码长为8的哈夫曼码值是0xA。

                   L9=1  码长为9的哈夫曼码值是0xB。

                   L10到L16均为0,所以么有码长为10~16的哈夫曼代码。

                   

                    0xFF 0xC4:定义哈夫曼表标记。

                    0x00 0xB5:哈夫曼长度,这里长度为181个字节。

                    0x10:前4位为表类型,后4位是哈夫曼表目标标志符,这里表示的是AC-0哈夫曼表

                     0x00 0x02 0x01 。。。0x7D 表示长度为i的哈夫曼代码数目。

                     0x01 0x02 .... 列出了针对Li长度为i的哈夫曼代码值,共162个字节。

                     0xFF 0xC4 定义哈夫曼表标记。

                     0x01:前4位表示表类型,后4位是哈夫曼表目标标志符,这里表示的是DC-1哈夫曼表。


                     0xFF 0xDA:扫描开始标记,标明扫描参数开始的位置。

                      0x00 0x0C:扫描头标长度参数,12个字节。

                      0x03:扫描行中图像分量数目。

                      0x01:扫描分量选择器,这里表示第一个分量。

                      0x00:前4位为DC熵编码目标选择器,从4个可能的DC熵编码表目标中选出1个目标。后4位从AC熵编码表目标选出1个目标。

                      0x02:扫描分量选择器,这里表示第二个分量。

                       0x11:前4位为DC熵编码表目标选择器,后4位为AC熵编码表目标选择器。

                       0x00:指定Z型序列中每个块中的第一个DCT参数,对于顺序的DCT过程该参数设置为0;

                       0x3F:频谱选择参数。

                       0x00:前4位为后续近似位置高参数,后4位为后续近似位位置低或点变换参数。一般设置为0

                       0xF7 0xFA .....,压缩图像数据。


                        0xFF 0xD9:图像结束标记。

      二、JPEG的编码解码

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

             压缩算法:有损的离散余弦变换(Siscrete Consine Transform,DCT) ,无损的预测技术压缩。

             数据编码方法:哈夫曼编码、算术编码

             编码模式:基于DCT顺序模式—编/解码通过一次扫描完成;基于DCT递进模式—编/解码需要多次扫描完成,扫描效果从粗糙到精细,逐级递进;无损模式,基于DPCM,保证解码后完全精确恢复到原图像采样值;层次模式,图像在多个空间多个分辨率进行编码。

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

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

               ① 8*8分块

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

               ③ 量化(quantization)

               ④ Z字形编码(zigzag scan)

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

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

               ⑦ 熵编码

      2.1、JPEG文件格式介绍

               JPEG文件是数据存储格式有多种,最常用的格式为JPEG文件交换格式(JPIF).JPEG文件大体上分为两个部分:标记码(Tag)和压缩数据。

               标记码由两个字节构成,前一个字节是固定值0xFF,后一个字节根据不同意义有不同的数值。多个连续的0xFF可以被理解为一个0xFF并表示标记码的开始,在一个两字节标记码后,就是标记码对应的压缩数据流,记录了文件的多种信息。

                常用的标记码有SOI、APP0、DQT、SOF0、DHF、DRI、SOS、EOI。

                SOI:图像开始,固定值 0xFF 0xD8

                APP0:应用程序保留标记0,固定值0xFF 0xE0,包含9个具体字段:

                            9个字段数据长度(2个字节)、

                            标识符即字符串JPIF0(5个字节)、

                            版本号(两个字节)0x0102表示JFIF0的版本是1.2

                            X和Y的密度单位(1个字节),有三个值可选0表示无单位,1表示点数/英寸,2表示点数/厘米。

                            X方向像素密度  2字节

                            Y方向的像素密度  2个字节

                            缩略图水平像素数目  1个字节

                            缩略图垂直像素数目   1个字节

                           缩略图RGB位图      长度可能是3的倍数

                   APPn,应用程序的保留标记n,n=1~15,固定值0xFFE1~0xFFF0.

                   DQT(Define Quantization Table) 定义了量化表,固定值0xFFDB

                   SOF0(start of Frame),帧图像开始 固定值0xFFC0.

                   DHF(Define Huffman Table),定义哈夫曼表,固定值0xFFC4

                  由于0xFF具有标志性的意思,实际数据流中出现0xff,在在数据0xFF后添加一个没有意义的0xFF,如果在数据流中遇到0xFF,应该检测紧接着的字符,如果是

                     0x00:表示是图像流的组成部分。

                     0xD9:图像流结束

                     0xD0~0xD7,促成RSTn标记。需要忽视两个字节。

                     0xff,忽视当前0xFF,对后一个字节在判断

                     其他数值,忽视当前0xFF,保留此数据用于译码。

         2.2、解码过程

                 按照JPEG文件数据存储方式,设计一系列结构体对应各个标记,并存储标记内表示的信息,其中图像的长宽、多个量化表和哈夫曼表、水平/垂直的采样因子等重要信息。

                 整个GIGF0数据格式顺序为:

                      SOI(0xFFD8)

                      APP0(0xFFE0)

                      [APPn(0xFFEn)]可选

                      DQT(0xFFDB)

                      SOF0(0xFFC0)

                      DHT(0xFFC4)

                      SOS(0XFFDA)

                        压缩数据

                      EOI(0xFFD9)

             JPEG文件格式,一个字(两个字节)存储使用Motorola格式及高字节在前低字节在后。

           (1) 读哈夫曼表数据

                 在标记段DHT内,包含了一个或多个的哈夫曼表,对于单一哈夫曼表包括三个部分:

                  1)  哈夫曼表ID和表类型,这个字节的值只有四个,0x00 0x01 0x10 0x11。

                             0x00  表示DC直流0号表。

                             0x01  表示DC直流1号表

                             0x10  表示AC交流0号表

                             0x11  表示AC交流1号表

                  2)  不同位数的码字数量

                         JPEG文件的哈夫曼编码只能只能是1~16位。这个字段的16个字节分表表示1~16位的编码码字在哈夫曼树中的个数。

                  3)  编码内容

                        记录了哈夫曼树中各个叶子节点的权(不同位数的码字数量)。

            解码过程:数据流 -> 最小编码单元(MCU) -> 数据单元与颜色分量

               1) 在图片数据流中,信息被分为一段有单的最小编码单元数据流MCU。MCU是图像中一个正方矩阵像素的数据。矩阵大小是这样确定的:

                查阅标记SOF0,可以得到图像不同颜色分量的采样因子,级Y、Cr、Cb三个分量各自的水平采样因子和垂直采样因子,大多图片的采样因子为4:1:1 或1:1:1其中4:1:1即(2*2):(1*1):(1*1),1:1:1即(1*1):(1*1):(1*1),记三个分量重水平采样因子最大值为Hmax,垂直采样因子最大值为Vmax,单个MCU矩阵宽就是Hmax*8像素,高就是Vmax*8像素,这里的Hmax为2、Vmax也为2.

                 如果正个图像宽度和高度不是MCU宽度和高度的整数倍,编码时会用某些数值填充。数据流中MCU的排列方法是从左到右,从上到下。

               2) 每个MCU又分为若干个数据,数据单元大小必定是8*8,所以每个MCU数据单元个数是Hmax*Vmax。

                    JPEG的压缩方法与BMP文件有所不同,它不是把每个像素的颜色分量连续存储在一起,而是把图片分成Y、Cr、Cb三张子图分别压缩。三个颜色的采样因子可能一样(1:1:1),也可能不一样(4:1:1)。每个MCU内部,数据顺序是Y、Cr、Cb。如果一个颜色分量有多个数据单元,顺序是从左到右从上到下。

                


          1、从文件头文件读出文件的相关信息

               JPEG文件数据分为文件头和图像数据两大部分,其中文件头记录了图像的版本、长宽、采样因子、量化表、哈夫曼表等重要信息,解码前必须将文件头信息读出。

          2、从图像数据流读取一个最小编码单元(MCU),并提取出里边的各个颜色分量单元。

          3、将颜色分量单元从数据流回复成矩阵数据。

                利用文件头给出的哈夫曼表,对分割出来的颜色分量单元进行解码,把其恢复成8x8的数据矩阵。

          4、8x8数据矩阵进一步解码

                此部分解码工作以8x8数据矩阵为单位,其中包括相邻矩阵的直流系统差分解码、利用文件头给出量化表反量化数据、反Zig-zag编码、隔行正负纠正、反向离散余弦变换等5个步骤,最终仍然是一个8x8的数据矩阵。

         5、颜色系统YCrCb向RGB转换

              将一个MCU的各个颜色分量单元解码结果整合起来,将图像颜色系统从YCrCb向RGB转换。

         6、排列整合各个MCU解码数据。

               不断读取数据流中的MCU并对其解码,直至读完所有的MCU位置,将各MCU解码后的数据正确排列成完整的图像。     

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值