造轮者说
首发于造轮者说
某科学的JPEG编码函数 svjpeg()

某科学的JPEG编码函数 svjpeg()

一、前言

前一段时间看到 @Milo Yip极简的 PNG 编码函数 svpng(),于是想斗胆自己也写一个JPEG版的练练手。

于是现在有了 SuperSodaSea/svjpeg。以MIT协议发布。

与 svpng 不同的是,为了能够写得简单点(其实就是为了偷懒),使用了C++11来编写。代码本体不超过100行。

主体部分如下(详见 svjpeg.hpp):

二、用法示例

svjpeg 的用法与 svpng 类似,示例(注意,使用 svjpeg 需要支持 C++11 的编译器):

#include "svjpeg.hpp"

int main() {
    std::FILE* file = std::fopen("test.jpg", "wb");
    std::uint8_t data[256 * 256 * 3];
    std::uint8_t* p = data;
    for(int y = 0; y < 256; ++y)
        for(int x = 0; x < 256; ++x)
            *p++ = x, *p++ = y, *p++ = 128;
    svjpeg(file, 256, 256, data);
    std::fclose(file);
}

输出的 test.jpg:

大小约为14.9KB,还算可以了。(作为对比,同样内容的未压缩PNG大小约为193KB,用画图压缩的同样内容的JPEG大小约为5.5KB。)

svjpeg 的函数声明如下:

inline void svjpeg(std::FILE* file, std::uint32_t width, std::uint32_t height, std::uint8_t* data);

相信参数的意义应该很清楚了。与 svpng 相比,去掉了透明参数(因为JPEG弄不了透明嘛)。

三、设计细节

关于JPEG格式的一些介绍已经写在 花一天写了个JPEG解码器,来整理一下JPEG格式的原理 中了。

对于JPEG来说,不能像PNG那样偷懒将数据直接写入文件了,得老老实实写压缩过程。当然这也是能省就省的,比如去掉了降采样的步骤,量化表写成了全4,Huffman也是用一个特殊的表来简化编码的过程。当前,前提是保证图片能够正常解析啦。

四、后记

svjpeg 的目的是尽可能短小精湛,而并没有考虑效率以及压缩率,所以这就是一个小玩具啦。严肃一些的编码器/解码器会放在 Medicat 中。(当然这是以后的事了)

当然,欢迎 Star & Fork SuperSodaSea/svjpeg ~

五、彩蛋

下面有调试过程中生成的各种错误图片……(可能会引起不适,请选择是否观看 :))






感谢阅读。

编辑于 2017-07-26

文章被以下专栏收录