实战JPEG图像格式编解码中的几个问题

因为网络上关于JPEG格式文件的编解码的文档很多,也因为时间的关系,我不再重复那些JPEG文件的结构、编解码的流程之类的知识点。在我这次完成JPEG图像的解码和BMP格式文件转换为JPEG格式的编码过程中,就遇到的问题及最后的解决方案做一些说明。

1、熵编解码解流程。

       为了提高压缩率,JPEG采用了三个算法对数据进行编码:把经过DCT变换后的DCU二维8x8矩阵,先ZIGZGAG的方法线性化为一维数组,然后使用量化表量化,其中DC分量(数组的第一个元素),使用DPCM(自适应)编码,之后的AC分量,使用游程编码。游程编码的每一个编码是一个数对如(10,-1),前面的10是连0的个数,-1是之后遇到的非0值,编码时,这个-1要使用VLI编码,VLI是可变长整数编码,正整数时,如9,编码为1001,长4比特,注意这里是反码,而-1的反码为0,长度为1比特,请注意这里的单位是比特。所以,如果一个VLI的编码的第一位是0,说明是负数,值的计算方法是:0-2^{1}+1。其它的数,按这个公式进行计算,正数时,最高位是1,直接计算。之后,就是进行Huffman的编码:编码值长度为1字节:高4位是连0的个数(显然不能超过15个0),低位就是VLI编码的长度,也不会超过15位。所以,那个(10,-1)的Huffman编码值是(A1), 查询AC Huffman表,得到相应的编码(01f8h)。请注意,实际写入文件中的比特流是这个编码的从左到右遇到的第一个非0开始的比特流,然后加上那个-1的编码0,其比特流是:【1 1111 1000 0】。解码是这个过程的逆过程。最后,需要特别说明的是,DC部分的编码是DPCM,亮度和色度的初始值均为512。DC的Huffman的编码方式和AC类似,不过其编码值高四位一直是0,低四位是DPCM编码的VLI编码长度,然后查询DC的Huffman表。结束解码的条件:(1)解码过程中,遇到00,一个DCU的解码就结束,不足64字节的数据全部为0。

          (2)已经获取了64个数据字节。

            在解码的过程中,原始数据中如果遇到FF 00,表示FF参加解码,00应该跳过。FF对应JPEG是特殊标志,而在待解码的数据流,可能多次出现,要特别注意检查。

2、数据流的问题。

     就是解码出来的8x8的数据矩阵,是按什么顺序输出的问题,JPEG的颜色空间是YCbCr,采样模式为4:1:1,所以,每6个DCU数据矩阵,有4个亮度数据DCU,1个Cb数据DCU,1个CrDCU,按Y1,Y2,Y3,Y4,Cb,Cr的顺序输出,亮度按由左到右,由上到下的形式排列为一个MCU,1个Cb和1个Cr,每个数据元素向右和向下扩展为4个相同的数据,从而得到16x16的色度MCU,与亮度数据形成YUV的MCU。之后就可以根据YUV到RGB的转换公式转到RGB色彩空间。

3、RGB和YUV的转换公式。

     网上各种的公式,经常出现错误,所以,这里再列一次,实践证明是正确的。

    Y=0.299R+0.587G+0.114B;Cb=0.564(B-Y)+128;Cr=0.713(R-Y)+128

    R=Y+1.402(Cr-128);G=Y-0.34414(Cb-128)-0.71414(Cr-128);B=Y+1.772(Cb-128)。

   特别注意的是:YUV转换为RGB时,如果超过255截断为255,小于0时,截断为0。

4、输出为BMP文件

      应该注意,BMP文件中,宽度像素的数据字节的长度应该是4的整数倍。如果不是需要填充到4的倍数,否则,得到的文件不能正常解码。

5、未解决的问题。

      对于有些博客中提到的ZRL, 就是16个0的情况,尚不足如何进行编码处理。

6、结语。

      整个解码过程,程序还是比较复杂,用到多种数据结构,知识点较大,有较高的技术含量,对程序设计水平是个挑战,个人认为,学习图像图像处理的同学们,应该亲自完成,收益一定不菲。

你可能感兴趣的:(算法,图像处理,JPEG解码)