数据压缩原理 实验五 JPEG原理分析及JPEG解码器的调试

实验原理

JPEG编码的过程如下图所示。解码是编码的逆过程。
jpeg编码

JPEG文件解码流程:
①读入文件的相关信息
②初步了解图像数据流的结构
③颜色分量单元的内部解码
④直流系数的差分编码
⑤反量化&反zig-zag编码
⑥反离散余弦变换

JPEG文件格式:
JPEG文件格式

实验流程

1.读取文件
2.解析文件
SOI、APP0、DQT、SOF0、DHT、SOS
3.根据每个分量的水平和垂直采样因子计算最小编码单元的大小,并得到每个最小编码单元内8×8宏块的个数
4.对每个最小编码单元解码
5.解析到EOI结束
6.将Y、Cb、Cr转换为所需的色彩空间保存

代码分析

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;

  Q_table = fopen("Q_table.txt","w");       //量化表、DC AC表
  DC_table = fopen("DC_table.yuv","w");
  AC_table = fopen("AC_table.yuv","w");

#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")==0)
    output_format = TINYJPEG_FMT_YUV420P;
  else if (strcmp(argv[current_argument+1],"rgb24")==0)
    output_format = TINYJPEG_FMT_RGB24;
  else if (strcmp(argv[current_argument+1],"bgr24")==0)
    output_format = TINYJPEG_FMT_BGR24;
  else if (strcmp(argv[current_argument+1],"grey")==0)
    output_format = TINYJPEG_FMT_GREY;
  else if (strcmp(argv[current_argument+1],"yuv")==0)
    output_format = TINYJPEG_FMT_YUV;

  else
    exitmessage("Bad format: need to be one of yuv420p, rgb24, bgr24, grey\n");
  output_filename = argv[current_argument+2];

  start_time = clock();

  if (benchmark_mode)
    load_multiple_times(input_filename, output_filename, output_format);
    //加载多次
  else
    convert_one_image(input_filename, output_filename, output_format);
    //转换一个图像

  finish_time = clock();
  duration = finish_time - start_time;
  snprintf(error_string, sizeof(error_string),"Decoding finished in %u ticks\n", duration);

  fclose(Q_table);          //关文件
  fclose(DC_table);
  fclose(AC_table);

#if TRACE
  fclose(p_trace);
#endif
  return 0;
}

输出量化表

static int parse_DQT(struct jdec_private *priv, const unsigned char *stream)
{
  int i;
  int qi;
  float *table;
  const unsigned char *dqt_block_end;
#if TRACE
  fprintf(p_trace,"> DQT marker\n");
  fflush(p_trace);
#endif
  dqt_block_end = stream + be16_to_cpu(stream);
  stream += 2;  /* Skip length */
   while (stream < dqt_block_end)
   {
     qi = *stream++;
#if SANITY_CHECK
     if (qi>>4)
       snprintf(error_string, sizeof(error_string),"16 bits quantization table is not supported\n");
     if (qi>4)
       snprintf(error_string, sizeof(error_string),"No more 4 quantization table is supported (got %d)\n", qi);
#endif
     table = priv->Q_tables[qi];
     build_quantization_table(table, stream);
     /***************************************************/
    for(i=0;i<64;i++)
    {
         if((!(i%8)))
     {
         fprintf(Q_table,"\n%f",table[i]);
     }
     else 
     {
         fprintf(Q_table," %f",table[i]);
     }
    }
     fprintf(Q_table,"\n");
     /***************************************************/
     stream += 64;
        }
#if TRACE
  fprintf(p_trace,"< DQT marker\n");
  fflush(p_trace);
#endif
  return 0;
}

输出DC、AC系数

for (y=0; y < priv->height/ystride_by_mcu; y++)
   {
     //trace("Decoding row %d\n", y);
     priv->plane[0] = priv->components[0] + (y * bytes_per_blocklines[0]);
     priv->plane[1] = priv->components[1] + (y * bytes_per_blocklines[1]);
     priv->plane[2] = priv->components[2] + (y * bytes_per_blocklines[2]);
     for (x=0; x < priv->width; x+=xstride_by_mcu)
      {
    decode_MCU(priv);
    convert_to_pixfmt(priv);
    priv->plane[0] += bytes_per_mcu[0];
    priv->plane[1] += bytes_per_mcu[1];
    priv->plane[2] += bytes_per_mcu[2];

    if (priv->restarts_to_go>0)
     {
       priv->restarts_to_go--;
       if (priv->restarts_to_go == 0)
        {
          priv->stream -= (priv->nbits_in_reservoir/8);
          resync(priv);
          if (find_next_rst_marker(priv) < 0)
        return -1;
        }
     }
     DC[0]=(priv->component_infos->DCT[0]+512.0)/4;
     DCimage[0]=(unsigned char)(DC[0]+0.5);
     fwrite(DCimage,1,1,DC_table);
     //按块写DC系数
     ACimage[0]=(unsigned char)(priv->component_infos->DCT[1]+128);
     fwrite(ACimage,1,1,AC_table);
     //按块写AC系数
      }
   }

实验结果

原始图像
原始图像

部分输出文件
excel表

DC图像
DC图像
DC表

AC图像
AC图像
AC表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值