Jpeg图片与Bitmap图片一样分为两部分: 文件头 + 数据部分(压缩)
文件头由各个段构成,详情可参考博文:http://blog.csdn.net/lpt19832003/article/details/1713718
其中哈夫曼表一般是固定的,可以在文件中读取,也可以自己不在文件中读取
1.图像分块
在采用前先将图像分块(8x8),如上图所示,也就是每块包含64个像素点,以24位真彩色为例,那么每个像素就包含 RGB 三个字节
2.颜色空间
Jpeg编码使用的 YCbCr颜色空间,其转换方程如下图
3.采样因子 与 最小编码单元(MCU, Minimum Coded Unit)
采样因子包含 水平采样因子 和 垂直采样因子 , 通常使用的采样因子是 Y : Cr : Cb = 2*2 : 1*1 : 1*1 = 4 : 1 : 1
即每 4 个像素采样 4 个 Y 分量,采样 1 个 Cb 分量, 采样一个 Cr 分量。
假设有一副图像有208个像素,如上图所示,可以分为4块,每块8*8=64个像素(不足的补齐)。对其使用 4 : 1 : 1采样,最后的结果就是产生6个数据块【Y1, Y2, Y3, Y4, Cb1, Cr1】,每块有8*8=64个像素,而用于采样生成这6个数据块的原始图像数据就是 MCU(最小编码单元),也就是说 每个 MCU 包含256个像素
4.离散余弦变换 与 逆离散余弦变换
参考:http://blog.csdn.net/luoweifu/article/details/8214959
5.量化
每个分量 * 对应的系数
6.熵编码
查哈夫曼表,解码。需要注意的是解码得到的是标准哈夫曼编码,需要进行一次转换
/* 获取标准哈夫曼编码的真实值 */
int JpegDecoder::GetRealValue(int length)
{
int retVal = 0;
for (int i = 0; i < length; i++)
{
retVal = (retVal << 1) + NextBit();
}
return (retVal >= pow(2, length -1) ? retVal : retVal - pow(2, length) + 1);
}
源码:
https://git.oschina.net/SilentCode/tinyjepgdecoder
运行示例:
没有使用任何加速算法,所以解码一张大图需要大约3秒钟的时间,下图是使用OpenCV库函数 imshow() 来显示解码后的位图数据
下面是原图