数据压缩实验五:JPEG解码

一、基本原理

1.编码原理

JPEG规定了4种运行模式,以满足不同需要:

  • 基于DPCM的无损编码模式:压缩比可达2:1
  • 基于DCT的有损顺序编码模式:压缩比可达10:1以上
  • 基于DCT的递增编码模式
  • 基于DCT的分层编码模式

本文分析第二种,其损失都来自量化
这里写图片描述

  • 常常将输入从RGB彩色空间转到YUV
  • Level offset:零偏置,对于灰度级是2n的像素,通过减去2n-1,将无符号的整数值变成有符号数,对于n=8,即将0~255的值域,通过减去128,转换为值域在-128~127之间的值,使像素的绝对值出现3位10进制的概率大大减少
  • 将输入图像分成8*8像素的块来处理,不足8*8的,取边缘像素补齐,对每个块做DCT变换,直流系数在每个块的左上角,越右下角的分量频率越高
  • DCT变换后DC系数值较大,且相邻块变化不大,利用这个特性对其进行DPCM,对相邻块的DC差值huffman编码
  • 对AC系数做之字形扫描,即按频率高低排列,再游程编码,huffman编码。

2.解码原理

解码是编码的逆过程

  • 解码Huffman数据
  • 解码DC差值
  • 重构量化后的系数
  • DCT逆变换
  • 丢弃填充的行/列
  • 反0偏置
  • 对丢失的CbCr分量差值(下采样的逆过程)
  • YCbCr转RGB

3.JPEG文件格式

  • JPEG文件有以下段落标记符:
    这里写图片描述
  • 将一个jpg文件用二进制显示出来:
    这里写图片描述
    下面解释上图的每一个红框标记:

  • JPEG文件以FFD8开头

  • APPn是文件细节信息,看图片时,没有点进去就显示出来的缩略图就是存在这部分里,下图FFE0为APP0,从FFE0依次向后读:00 10表示该部分占16字节;4A 46 49 46 00表示JFIF0;01 01表示版本号;00 表示X和Y方向的密度单位(0:无单位、1:1像素/英寸、2:2像素/厘米);00 01表示X方向像素密度;00 01表示Y方向像素密度;最后的00和00分别表示缩略图的X和Y方向像素数,由于该文件没有缩略图,后面就没有缩略的RGB位图的数据。
  • 文件中有两个FFDB,说明有两张量化表(DQT),以第一张量化表为例,从FFDB向后读:00 43表示量化表的长度为67字节;00的低四位表示第0张量化表,高四位表示8bit的量化精度(非0则16bit);最后是8*8的量化表实际数据,按之字形保存。
  • FFC0代表帧图像的开始(SOF0),向后读:00 11表示该部分的长度17字节;08表示每个颜色分量每个像素占8bit;04 00 04 00表示图像的高和宽分别为1024和1024像素;03 表示有3个颜色分量(YCbCr);后面9个字节,每3个一组,分别表示Y、Cb、Cr的如下信息,1字节的颜色ID(01、02、03)、1字节的采样因子(高四位水平 1、低四位垂直 1,说明MCU为8*8)、该分量使用的量化表(00、01、01)。
  • 该文件有4个FFC4,表示有4张huffman码表,以第一张为例:00 1D表示这张表的长度为29字节;00高四位表示直流(1为交流),低四位表示第0张表;后面16字节为不同位数码字的数量,00 03 01 01……00等表示码字为1、2、3……16位的个数分别为0、3、1、1……0个,相加得到码字总数为10;最后是这10个码字对应的权重,表示解码时需要再读入的位数。
  • FFDA表示扫描开始(SOS):00 0C表示这部分长度12字节;03表示颜色分量数为3; 后面6个字节。每2个一组表示一种颜色分量的ID和该分量使用的直流与交流量化表,01 00表示Y分量,交流使用第0张量化表,直流使用第0张量化表,02 11表示Cb分量,交流直流均使用第1张量化表,03 11表示Cr分量,交流直流均使用第1张量化表;后面是压缩图像数据,00是固定值,表示谱选择开始,3F是固定值,表示谱选择结束,00是固定值,表示谱选择。
  • 后面是图像流的组成部分,需要进行译码,直至遇到FF D9(EOI)结束。
    这里写图片描述

二、实验流程分析

1.读取文件

2.解析 Segment Marker

(1)解析 SOI(FFD8)

(2)解析 APP0(FFE0)

检查标识JFIF及版本,得到一些参数

(3) 解析 DQT

得到量化表长度、精度、序号、内容

(4) 解析 SOF0

得到每个样本的比特数 、长宽,颜色分量的比特数、每个颜色分量的 ID 、水平垂直采样因子及使用的量化表序号

(5) 解析 DHT

得到 Huffman 表的类型(AC/DC)、序号,并根据数据重建Huffman 表

(6)解析 SOS

得到每个颜色分量的 DC 、AC 值所使用的Huffman 表序号

3. 依据每个分量的水平、垂直采样因子计算MCU(最小编码单元)的大小 ,并得到每个MCU中 8*8宏块的个数

4. 对每个 MCU解码

  • 依照各分量水平、垂直采样因子对 MCU中每个分量宏块解码
  • 对每个宏块进行Huffman 解码,得到 DCT系数
  • 对每个宏块的DCT系数进行 IDCT,得到 Y、Cb 、Cr
  • 遇到 Segment Marker RST 时,清空之前的DCT系数

5. 解析到 EOI,解码结束

6. 将 Y、Cb 、Cr 转化为需要的色彩空间并保存

三、关键代码分析

任务1:调试JPEG解码器程序,将输出文件保存为可供YUVViewer观看的YUV文件。

  • 原代码能够生成单独的Y、U、V分量文件,首先需要让程序能够解析输出YUV整体文件的命令行

在tinyjpeg.h中
定义输入参数的枚举类型enum tinyjpeg_fmt中增加TINYJPEG_FMT_YUV一项

enum tinyjpeg_fmt {
   TINYJPEG_FMT_GREY = 1,
   TINYJPEG_FMT_BGR24,
   TINYJPEG_FMT_RGB24,
   TINYJPEG_FMT_YUV420P,
   /*******************/
   TINYJPEG_FMT_YUV,//增加
   /*******************/
};

在loadjpeg.c中
convert_one_image函数的判断输出格式里增加case TINYJPEG_FMT_YUV一项

 switch (output_format)
   {
    case TINYJPEG_FMT_RGB24:
    case TINYJPEG_FMT_BGR24:
      write_tga(outfilename, output_format, width, height, components);
      break;
    case TINYJPEG_FMT_YUV420P:
      write_yuv(outfilename, width, height, components);
      break;
    /***************************************************************/
    case TINYJPEG_FMT_YUV:
        write_YUV(outfilename, width, height, components);
        break;//增加
    /***************************************************************/
    case TINYJPEG_FMT_GREY:
      write_pgm(outfilename, width, height, components);
      break;
   }

main函数里增加解析命令行的部分

 if (strcmp(argv[current_argument+1],"yuv420p")==0)
    output_format = TINYJPEG_FMT_YUV420P;
  
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值