实验5 JPEG原理分析及JPEG解码器的调试

该博客详细介绍了JPEG编解码的原理,包括编码时的RGB转YUV、DCT变换、熵编码等步骤,以及解码时的逆过程。重点是调试JPEG解码器,将JPG文件解码为YUV文件,并分析了概率分布。实验内容包括理解程序设计、调试解码器、输出量化矩阵和HUFFMAN码表,并统计DC和AC系数的概率分布。
摘要由CSDN通过智能技术生成

一、实验目的

掌握JPEG编解码系统的基本原理。初步掌握复杂的数据压缩算法实现,并能根据理论分析需要实现所对应数据的输出。

二、实验原理

1.JPEG编解码原理

 

编码原理:

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

解码原理:

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

2.JPEG文件格式
  JPEG 在文件中以 Segment 的形式组织,它具有以下特点:
均以 0xFF 开始,后跟 1 byte 的 Marker 和 2 byte 的 Segment length(包含表示 Length 本身所占用的 2 byte,不含“0xFF” + “Marker” 所占用的 2 byte);
采用 Motorola 序(相对于 Intel 序),即保存时高位在前,低位在后;
Data 部分中,0xFF 后若为 0x00,则跳过此字节不予处理


 

三、实验内容

实验要求:

1.逐步调试JPEG解码器程序。将输入的JPG文件进行解码,将输出文件保存为可供YUVViewer观看的YUV文件。

2.  程序调试过程中,应做到:

  1. 理解程序设计的整体框架
  2. 理解三个结构体的设计目的
    • struct  huffman_table
    • struct  component
    • struct  jdec_private
  3. 理解在视音频编解码调试中TRACE的目的和含义
    • 会打开和关闭TRACE
    • 会根据自己的要求修改TRACE

3.以txt文件输出所有的量化矩阵和所有的HUFFMAN码表。

  1. 输出DC图像并统计其概率分布。
  2. 输出某一个AC值图像并统计其概率分布。

调试JPEG解码器程序

将输入的JPG文件进行解码,将输出文件保存为YUV文件。

代码分析
struct  huffman_table
用来储存霍夫曼表

struct huffman_table
{
  /* Fast look up table, using HUFFMAN_HASH_NBITS bits we can have directly the symbol,
   * if the symbol is <0, then we need to look into the tree table */
  short int lookup[HUFFMAN_HASH_SIZE];
  /* code size: give the number of bits of a symbol is encoded */
  unsigned char code_size[HUFFMAN_HASH_SIZE];
  /* some place to store value that is not encoded in the lookup table 
   * FIXME: Calculate if 256 value is enough to store all values
   */
  uint16_t slowtable[16-HUFFMAN_HASH_NBITS][256];
};
struct  component
存储当前像块中关于解码的信息

struct component 
{
  unsigned int Hfactor;
  unsigned int Vfactor;
  float *Q_table;        /* Pointer to the quantisation table to use */
  struct huffman_table *AC_table;
  struct huffman_table *DC_table;
  short int previous_DC;    /* Previous DC coefficient */
  short int DCT[64];        /* DCT coef */
#if SANITY_CHECK
  unsigned int cid;
#endif
};
struct  jdec_private
存储图像宽高、码表等信息

struct jdec_private
{
  /* Public variables */
  uint8_t *components[COMPONENTS];
  unsigned int width, height;    /* Size of the image */
  unsigned int flags;
 
  /* Private variables */
  const unsigned char *stream_begin, *stream_end;
  unsigned int stream_length;
 
  const unsigned char *stream;    /* Pointer to the current stream */
  unsigned int reservoir, nbits_in_reservoir;
 
  struct component component_infos[COMPONENTS];
  float Q_tables[COMPONENTS][64];        /* quantization tables */
  struct huffman_table HTDC[HUFFMAN_TABLES];    /* DC huffman tables   */
  struct huffman_table HTAC[HUFFMAN_TABLES];    /* AC huffman tables   */
  int default_huffman_table_initialized;
  int restart_interval;
  int restarts_to_go;                /* MCUs left in this restart interval */
  int last_rst_marker_seen;            /* Rst marker is incremented each time */
 
  /* Temp space used after the IDCT to store each components */
  uint8_t Y[64*4], Cr[64], Cb[64];
 
  jmp_buf jump_state;
  /* Internal Pointer use for colorspace conversion, do not modify it !!! */
  uint8_t *plane[COMPONENTS];
 
};

main
int main(int argc, char *argv[])
{
  int output_format = TINYJPEG_FMT_YUV420P;
  char *output_filename, *input_filename;
  clock_t start_time, finish_time;
  unsigned int duration;
  int current_argument;
  int benchmark_mode = 0;
#if TRACE
  p_trace=fopen(TRACEFILE,"w");
  if (p_trace==NULL)
  {
      printf("trace file open error!");
  }
#endif
  if (argc < 3)
    usage();
 
  current_argument = 1;
  while (1)
   {
     if (strcmp(argv[current_argument], "--benchmark")==0)
       benchmark_mode = 1;
     else
       break;
     current_argument++;
   }
 
  if (argc < current_argument+2)
    usage();
 
  input_filename = argv[current_argument];//选择输出文件的格式
  if (strcmp(argv[current_argument+1],"yuv420p&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值