花一天写了个JPEG解码器,来整理一下JPEG格式的原理

192 篇文章 39 订阅

昨天花了一天的时间试着写了一下JPEG解码器,虽然遇到了一些麻烦,不过最后还是成功地解出了图像的数据。总共400行代码左右。

(解码的核心也就这50行左右,因为只是验证一下以前了解的信息,所以看起来还是有点乱,而且没有做各种错误处理,所以不要太在意啦┑( ̄Д  ̄)┍)

下面是JPEG的编码过程的整理(因为编码和解码是完全对称的所以就只说编码,解码可以自行脑补)(仔细看的话都能在上面那段代码中找到对应哦):

(图片自制) RGB转YCbCr:因为人眼对亮度比较敏感,而对于色度不那么敏感,所以,我们就先将RGB的数据转换到YCbCr色彩空间,便于下面的处理。

降采样:转到YCbCr色彩空间后,就可以将 Cb 和 Cr 这两个通道进行降采样,这里一般是将 2*2 个像素变为 1*1 个像素,虽然分辨率下降到了四分之一,但对于人眼来说差别是不大的。(这一步是有损的)

分块:顾名思义,将图像分为若干个 8*8 的小块,方便下面的处理。

DCT:这一步的目的和RGB转YCbCr有一些相似之处,都是将人眼较为敏感和不敏感的部分进行分离,然后就可以对减少人眼不敏感的部分的信息量。在这一步中,DCT可以将图像的低频(人眼敏感)和高频(人眼不敏感)部分进行分离。这样得到的结果是每个 8*8 小块得到 8*8 的系数矩阵。

量化:将DCT后得到的每个系数都除以量化矩阵中对应的值,然后进行取整。通常来说频率较高的部分对应的量化参数比较大,这样一来就能够在较好地保留图像的低频部分并去除一些高频部分。这一步下来得到的矩阵中高频部分几乎全部变为0,这也为进一步的操作提供了便利。值得注意的是,JPEG中压缩率的调整是在这一步中,量化参数越大,压缩后的大小就会越小,但信息的损失也就越多,图片的失真也会更严重。(这一步是有损的)

Huffman编码:准确地说是Huffman编码和RLE,将上一步得到的矩阵进行进一步地压缩(这一步是无损的)。量化后得到的矩阵左上角的那个数比其他数来得大得多,所以我们将它单独拿出来进行编码,称之为直流分量(DC),将剩下的称之为交流系数(AC)。这一步会将矩阵按照 zigzag 的顺序摊成一维,如下图所示:

 

这样做的好处是矩阵的高频部分(右下角)会被安排在后面,因为它们基本上全是0,所以在编码中有一个特殊的标记表示这之后的系数全是0,从而减少压缩后的大小。

(话说回来,Huffman解码这一步应该是解码中最麻烦的一部分……位的顺序搞了好久)

上面这些步骤完成之后,再加上一些必要的其他信息(量化矩阵和Huffman的信息,这两个是直接没有压缩就存储在文件中的),就得到了最终的JPEG数据。

暂时先整理这么多,以后有时间再认真写一下解码器,争取某一天能够达到 libjpeg 的水平吧 :) (以后应该会包含在 Medicat 中←某个妄图把各种图像/音频格式都自己实现一遍的轮子)

参考:

https://www.w3.org/Graphics/JPEG/itu-t81.pdf

https://en.wikipedia.org/wiki/J

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值