Tiny Jpeg Decoder (JPEG解碼程序) 源代碼分析


本文轉自:http://blog.csdn.net/leixiaohua1020/article/details/12617079

Tiny Jpeg Decoder是一個可以用於嵌入式系統的JPEG解碼器。也可以在Windows上編譯通過。在此分析一下它部分的源代碼,輔助學習JPEG解碼知識。

通過TinyJpeg可以將JPEG(*.jpg)文件解碼為YUV(*.yuv)或者RGB(*.tga)文件。

真正的解碼開始於convert_one_image()函數:

/**  
 * Load one jpeg image, and decompress it, and save the result.  
 */   
int convert_one_image(LPVOID lparam,const char *infilename, const char *outfilename, int output_format)   
{   
  FILE *fp;   
  unsigned int length_of_file;   
  unsigned int width, height;   
  unsigned char *buf;   
  struct jdec_private *jdec;   
  unsigned char *components[3];   
   
  /* Load the Jpeg into memory */   
  fp = fopen(infilename, "rb");   
  if (fp == NULL)   
    exitmessage("Cannot open filename\n");   
  length_of_file = filesize(fp);   
  buf = (unsigned char *)malloc(length_of_file + 4);   
  if (buf == NULL)   
    exitmessage("Not enough memory for loading file\n");   
  fread(buf, length_of_file, 1, fp);   
  fclose(fp);   
   
  /* Decompress it */   
  //分配內存   
  jdec = tinyjpeg_init();   
  //傳入句柄--------------   
  jdec->dlg=(CSpecialVIJPGDlg *)lparam;   
   
  if (jdec == NULL)   
    exitmessage("Not enough memory to alloc the structure need for decompressing\n");   
  //解頭部   
  if (tinyjpeg_parse_header(jdec, buf, length_of_file)<0)   
    exitmessage(tinyjpeg_get_errorstring(jdec));   
  /* Get the size of the image */   
  //獲得圖像長寬   
  tinyjpeg_get_size(jdec, &width, &height);   
   
  snprintf(error_string, sizeof(error_string),"Decoding JPEG image...\n");   
  //解碼實際數據   
  if (tinyjpeg_decode(jdec, output_format) < 0)   
    exitmessage(tinyjpeg_get_errorstring(jdec));   
  /*   
   * Get address for each plane (not only max 3 planes is supported), and  
   * depending of the output mode, only some components will be filled   
   * RGB: 1 plane, YUV420P: 3 planes, GREY: 1 plane  
   */   
  tinyjpeg_get_components(jdec, components);   
   
  /* Save it */   
  switch (output_format)   
   {   
    case TINYJPEG_FMT_RGB24:   
    case TINYJPEG_FMT_BGR24:   
      write_tga(outfilename, output_format, width, height, components);   
      break;   
    case TINYJPEG_FMT_YUV420P:   
      //開始寫入成YUV420P文件   
      write_yuv(outfilename, width, height, components);   
      break;   
    case TINYJPEG_FMT_GREY:   
      //開始寫入成灰度文件   
      write_pgm(outfilename, width, height, components);   
      break;   
   }   
   
  /* Only called this if the buffers were allocated by tinyjpeg_decode() */   
//modify by lei!  tinyjpeg_free(jdec);   
  /* else called just free(jdec); */   
   
  free(buf);   
  return 0;   
}


tinyjpeg_init()用於初始化:

/**  
 * Allocate a new tinyjpeg decoder object.  
 *  
 * Before calling any other functions, an object need to be called.  
 */   
struct jdec_private *tinyjpeg_init(void)   
{   
  struct jdec_private *priv;   
    
  priv = (struct jdec_private *)calloc(1, sizeof(struct jdec_private));   
  if (priv == NULL)   
    return NULL;   
  priv->DQT_table_num=0;   
  return priv;   
}


tinyjpeg_parse_header()用於解碼JPEG文件頭,可見函數前幾句主要驗證文件是否為JPEG文件:

/**  
 * Initialize the tinyjpeg object and prepare the decoding of the stream.  
 *  
 * Check if the jpeg can be decoded with this jpeg decoder.  
 * Fill some table used for preprocessing.  
 */   
int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size)   
{   
  int ret;   
     
  /* Identify the file */   
  //0x FF D8   
  //是否是JPEG格式文件?   
  if ((buf[0] != 0xFF) || (buf[1] != SOI))   
    snprintf(error_string, sizeof(error_string),"Not a JPG file ?\n");   
  //
  char temp_str[MAX_URL_LENGTH];   
  sprintf(temp_str,"0x %X %X",buf[0],buf[1]);   
  //JPEG格式文件固定的文件頭   
  //begin指針前移2字節   
  priv->stream_begin = buf+2;   
  priv->stream_length = size-2;   
  priv->stream_end = priv->stream_begin + priv->stream_length;   
  //開始解析JFIF   
  ret = parse_JFIF(priv, priv->stream_begin);   
  return ret;   
}


parse_JFIF()用於解析各種標簽(SOF,SOS,DHT...):

//解各種不同的標簽   
static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream)   
{   
  int chuck_len;   
  int marker;   
  int sos_marker_found = 0;   
  int dht_marker_found = 0;   
  const unsigned char *next_chunck;   
   
  /* Parse marker */   
  //在Start of scan標簽之前   
  while (!sos_marker_found)   
   {   
     if (*stream++ != 0xff)   
       goto bogus_jpeg_format;   
     /* Skip any padding ff byte (this is normal) */   
     //跳過0xff字節   
     while (*stream == 0xff)   
       stream++;   
     //marker是跳過0xff字節后1個字節的內容   
     marker = *stream++;   
     //chunk_len是marker后面2個字節的內容(大端模式需要轉換)   
     //包含自身,但不包含0xff+marker2字節   
     chuck_len = be16_to_cpu(stream);   
     //指向下一個chunk的指針   
     next_chunck = stream + chuck_len;   
     //各種不同的標簽   
     switch (marker)   
      {   
       case SOF:   
     //開始解析SOF   
     if (parse_SOF(priv, stream) < 0)   
       return -1;   
     break;   
     //Define quantization table   
       case DQT:   
     //開始解析DQT   
     if (parse_DQT(priv, stream) < 0)   
       return -1;   
     break;   
       case SOS:   
     //開始解析SOS   
     if (parse_SOS(priv, stream) < 0)   
       return -1;   
     sos_marker_found = 1;   
     break;   
     //Define Huffman table   
       case DHT:   
     //開始解析DHT   
     if (parse_DHT(priv, stream) < 0)   
       return -1;   
     dht_marker_found = 1;   
     break;   
       case DRI:   
     //開始解析DRI   
     if (parse_DRI(priv, stream) < 0)   
       return -1;   
     break;   
       default:   
#if TRACE_PARAM   
    fprintf(param_trace,"> Unknown marker %2.2x\n", marker);   
    fflush(param_trace);   
#endif   
     break;   
      }   
     //解下一個segment   
     stream = next_chunck;   
   }   
   
  if (!dht_marker_found) {   
#if TRACE_PARAM   
      fprintf(param_trace,"No Huffman table loaded, using the default one\n");   
      fflush(param_trace);   
#endif   
    build_default_huffman_tables(priv);   
  }   
   
#ifdef SANITY_CHECK   
  if (   (priv->component_infos[cY].Hfactor < priv->component_infos[cCb].Hfactor)   
      || (priv->component_infos[cY].Hfactor < priv->component_infos[cCr].Hfactor))   
    snprintf(error_string, sizeof(error_string),"Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n");   
  if (   (priv->component_infos[cY].Vfactor < priv->component_infos[cCb].Vfactor)   
      || (priv->component_infos[cY].Vfactor < priv->component_infos[cCr].Vfactor))   
    snprintf(error_string, sizeof(error_string),"Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n");   
  if (   (priv->component_infos[cCb].Hfactor!=1)    
      || (priv->component_infos[cCr].Hfactor!=1)   
      || (priv->component_infos[cCb].Vfactor!=1)   
      || (priv->component_infos[cCr].Vfactor!=1))   
    snprintf(error_string, sizeof(error_string),"Sampling other than 1x1 for Cr and Cb is not supported");   
#endif   
   
  return 0;   
bogus_jpeg_format:   
#if TRACE_PARAM   
  fprintf(param_trace,"Bogus jpeg format\n");   
  fflush(param_trace);   
#endif   
  return -1;   
}


parse_SOF()用於解析SOF標簽:

注意:其中包含了部分自己寫的代碼,形如:

itoa(width,temp_str1,10);   
  priv->dlg->AppendBInfo("SOF0","",temp_str1,"圖像的寬度");

這些代碼主要用於在解碼過程中提取一些信息,比如圖像寬,高,顏色分量數等等

static int parse_SOF(struct jdec_private *priv, const unsigned char *stream)   
{   
  int i, width, height, nr_components, cid, sampling_factor;   
  int Q_table;   
  struct component *c;   
#if TRACE_PARAM   
  fprintf(param_trace,"> SOF marker\n");   
  fflush(param_trace);   
#endif   
  print_SOF(stream);   
   
  height = be16_to_cpu(stream+3);   
  width  = be16_to_cpu(stream+5);   
  nr_components = stream[7];   
#if SANITY_CHECK   
  if (stream[2] != 8)   
    snprintf(error_string, sizeof(error_string),"Precision other than 8 is not supported\n");   
  if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT)   
    snprintf(error_string, sizeof(error_string),"Width and Height (%dx%d) seems suspicious\n", width, height);   
  if (nr_components != 3)   
    snprintf(error_string, sizeof(error_string),"We only support YUV images\n");   
  if (height%16)   
    snprintf(error_string, sizeof(error_string),"Height need to be a multiple of 16 (current height is %d)\n", height);   
  if (width%16)   
    snprintf(error_string, sizeof(error_string),"Width need to be a multiple of 16 (current Width is %d)\n", width);   
#endif   
  char temp_str1[MAX_URL_LENGTH]={0};   
  itoa(width,temp_str1,10);   
  priv->dlg->AppendBInfo("SOF0","",temp_str1,"圖像的寬度");   
  itoa(height,temp_str1,10);   
  priv->dlg->AppendBInfo("SOF0","",temp_str1,"圖像的高度");   
  itoa(nr_components,temp_str1,10);   
  priv->dlg->AppendBInfo("SOF0","顏色分量數",temp_str1,"圖像的顏色分量數。一個字節,例如03,代表有三個分量,YCrCb");   
  itoa(stream[2],temp_str1,10);   
  priv->dlg->AppendBInfo("SOF0","精度",temp_str1,"圖像的精度。一個字節,例如08,即精度為一個字節。");   
  stream += 8;   
  for (i=0; i<nr_components; i++) {   
     cid = *stream++;   
     sampling_factor = *stream++;   
     Q_table = *stream++;   
     c = &priv->component_infos[i];   
#if SANITY_CHECK   
     c->cid = cid;   
     if (Q_table >= COMPONENTS)   
       snprintf(error_string, sizeof(error_string),"Bad Quantization table index (got %d, max allowed %d)\n", Q_table, COMPONENTS-1);   
#endif   
     c->Vfactor = sampling_factor&0xf;   
     c->Hfactor = sampling_factor>>4;   
     c->Q_table = priv->Q_tables[Q_table];   
     //------------   
     char temp_str2[MAX_URL_LENGTH]={0};   
     sprintf(temp_str2,"垂直采樣因子【%d】",i);   
     itoa(c->Hfactor,temp_str1,10);   
     priv->dlg->AppendBInfo("SOF0",temp_str2,temp_str1,"顏色分量信息:每個分量有三個字節,第一個為分量的ID,01:Y 02:U 03:V;第二個字節高位為水平采樣因子,低位為垂直采樣因子。");   
     sprintf(temp_str2,"水平采樣因子【%d】",i);   
     itoa(c->Hfactor,temp_str1,10);   
     priv->dlg->AppendBInfo("SOF0",temp_str2,temp_str1,"顏色分量信息:每個分量有三個字節,第一個為分量的ID,01:Y 02:U 03:V;第二個字節高位為水平采樣因子,低位為垂直采樣因子。");   
     sprintf(temp_str2,"對應量化表ID【%d】",i);   
     itoa((int)Q_table,temp_str1,10);   
     priv->dlg->AppendBInfo("SOF0",temp_str2,temp_str1,"顏色分量信息:第三個字節代表這個分量對應的量化表ID,例如,Y對應的量化表ID索引值為00,而UV對應的量化表ID都為01,即它們共用一張量化表。");   
    //-------------   
#if TRACE_PARAM   
     fprintf(param_trace,"Component:%d  factor:%dx%d  Quantization table:%d\n",   
           cid, c->Hfactor, c->Hfactor, Q_table );   
     fflush(param_trace);   
#endif   
   
  }   
   
   
  priv->width = width;   
  priv->height = height;   
#if TRACE_PARAM   
  fprintf(param_trace,"< SOF marker\n");   
  fflush(param_trace);   
#endif   
   
  return 0;   
}


parse_DHT()用於解析DHT標簽:

//解析DHT表   
static int parse_DHT(struct jdec_private *priv, const unsigned char *stream)   
{   
  unsigned int count, i,j;   
  unsigned char huff_bits[17];   
  int length, index;   
  //------------------------------------------   
  char *temp;   
  FILE *fp;   
  //------------------------------------------   
  length = be16_to_cpu(stream) - 2;   
  //跳過length字段   
  stream += 2;  /* Skip length */   
#if TRACE_PARAM   
  fprintf(param_trace,"> DHT marker (length=%d)\n", length);   
  fflush(param_trace);   
#endif   
   
  while (length>0) {   
      //跳過第1字節:   
      //Huffman 表ID號和類型,高 4 位為表的類型,0:DC 直流;1:AC交流   
      //低四位為 Huffman 表 ID。    
     index = *stream++;   
   
     /* We need to calculate the number of bytes 'vals' will takes */   
     huff_bits[0] = 0;   
     count = 0;   
   
     //不同長度 Huffman 的碼字數量:固定為 16 個字節,每個字節代表從長度為 1到長度為 16 的碼字的個數   
     for (i=1; i<17; i++) {   
    huff_bits[i] = *stream++;   
    //count記錄碼字的個數   
    count += huff_bits[i];   
     }   
#if SANITY_CHECK   
     if (count >= HUFFMAN_BITS_SIZE)   
       snprintf(error_string, sizeof(error_string),"No more than %d bytes is allowed to describe a huffman table", HUFFMAN_BITS_SIZE);   
     if ( (index &0xf) >= HUFFMAN_TABLES)   
       snprintf(error_string, sizeof(error_string),"No more than %d Huffman tables is supported (got %d)\n", HUFFMAN_TABLES, index&0xf);   
#if TRACE_PARAM   
     fprintf(param_trace,"Huffman table %s[%d] length=%d\n", (index&0xf0)?"AC":"DC", index&0xf, count);   
     fflush(param_trace);   
#endif   
#endif   
   
     if (index & 0xf0 ){   
         //---------------------   
         char temp_str1[MAX_URL_LENGTH]={0};   
         char temp_str2[MAX_URL_LENGTH]={0};   
         temp=(char *)stream;   
         //fp = fopen("DHT.txt", "a+");   
         //fwrite(temp, 16, 1, fp);   
         for(j=0;j<16;j++){   
             //fprintf(fp,"%d ",temp[j]);   
             sprintf(temp_str2,"%d ",temp[j]);   
             strcat(temp_str1,temp_str2);   
         }   
         //fprintf(fp,"\n-----------------------\n");   
         //fclose(fp);   
         //-----------------------------------------------------   
         priv->dlg->AppendBInfo("DHT","定義霍夫曼表【交流系數表】",temp_str1,"Huffman表ID號和類型:1字節,高4位為表的類型,0:DC直流;1:AC交流 可以看出這里是直流表;低四位為Huffman表ID");   
         //-----------------------------------------------------   
    //交流霍夫曼表   
       build_huffman_table(huff_bits, stream, &priv->HTAC[index&0xf]);   
     }   
     else{   
         //---------------------   
         char temp_str1[MAX_URL_LENGTH]={0};   
         char temp_str2[MAX_URL_LENGTH]={0};   
         temp=(char *)stream;   
         //fp = fopen("DHT.txt", "a+");   
         //fwrite(temp, 16, 1, fp);   
         for(j=0;j<16;j++){   
             //fprintf(fp,"%d ",temp[j]);   
             sprintf(temp_str2,"%d ",temp[j]);   
             strcat(temp_str1,temp_str2);   
         }   
         //fprintf(fp,"\n-----------------------\n");   
         //fclose(fp);   
         //-----------------------------------------------------   
         priv->dlg->AppendBInfo("DHT","定義霍夫曼表【直流系數表】",temp_str1,"Huffman表ID號和類型:1字節,高4位為表的類型,0:DC直流;1:AC交流 可以看出這里是直流表;低四位為Huffman表ID");   
         //-----------------------------------------------------   
         //直流霍夫曼表   
       build_huffman_table(huff_bits, stream, &priv->HTDC[index&0xf]);   
     }   
   
     length -= 1;   
     length -= 16;   
     length -= count;   
     stream += count;   
  }   
#if TRACE_PARAM   
  fprintf(param_trace,"< DHT marker\n");   
  fflush(param_trace);   
#endif   
  return 0;   
}


parse_DQT()用於解析DQT標簽:

//解析Define quantization table   
static int parse_DQT(struct jdec_private *priv, const unsigned char *stream)   
{   
  int qi;   
  float *table;   
  const unsigned char *dqt_block_end;   
   
//------------------------------------------------   
    int j,k;   
    char *temp;   
    FILE *fp;   
//------------------------------------------------   
#if TRACE_PARAM   
  fprintf(param_trace,"> DQT marker\n");   
  fflush(param_trace);   
#endif   
  //該Segment末尾   
  dqt_block_end = stream + be16_to_cpu(stream);   
  //跳過標簽length(2字節)   
  stream += 2;  /* Skip length */   
  //沒到末尾   
  while (stream < dqt_block_end)   
   {   
    //跳過該Segment的第1個字節,QT信息   
    //precision: 00  (Higher 4 bit)   
    //index: 00  (Lower 4 bit)    
    //qi取1,第1張量化表(例如,亮度表),取2,第2張量化表(例如,色度表)   
     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指向jdec_private的Q_tables數組,為了在其中寫入數據   
     table = priv->Q_tables[qi];   
     //注意:一次搞定整張!寫入   
     //需要對數值進行變換!cos(k*PI/16) * sqrt(2)   
     //這樣才能得到離散余弦變換的系數   
     build_quantization_table(table, stream);   
//----------------------------------------------------------   
   
        temp=(char *)stream;   
        //fp = fopen("DQT.txt", "a+");   
        //fwrite(temp, 64, 1, fp);   
        char temp_str1[MAX_URL_LENGTH]={0};   
        char temp_str2[MAX_URL_LENGTH]={0};   
        for(j=0;j<64;j++){   
            sprintf(temp_str2,"%d ",temp[j]);   
            strcat(temp_str1,temp_str2);   
            //fprintf(fp,"%d ",temp[j]);   
        }   
        //計數   
        char temp_str3[MAX_URL_LENGTH]={0};   
        sprintf(temp_str3,"量化表【%d】",priv->DQT_table_num);   
        priv->dlg->AppendBInfo("DQT",temp_str3,temp_str1,"JPEG格式文件的量化表,一般來說第一張是亮度的,后面是色度的");   
        priv->DQT_table_num++;   
        //fprintf(fp,"\n-----------------------\n");   
        //fclose(fp);   
#if TRACE_PARAM   
        for(j=0;j<8;j++){   
            for(k=0;k<8;k++){   
                fprintf(param_trace,"%d ",temp[j*8+k]);   
            }   
            fprintf(param_trace,"\n");   
        }   
        fprintf(fp,"\n-----------------------\n");   
     fflush(param_trace);   
#endif   
//----------------------------------------------------------   
     //完事了!   
     stream += 64;   
   }   
#if TRACE_PARAM   
  fprintf(param_trace,"< DQT marker\n");   
  fflush(param_trace);   
#endif   
  return 0;   
}


其他標簽的解析不一一列舉。

 

真正的解碼數據開始於tinyjpeg_decode()函數:

注意:本代碼中包含部分自己寫的代碼,用於提取DCT系數表,解碼后亮度數據表等數據。

/**  
 * Decode and convert the jpeg image into @pixfmt@ image  
 *解碼函數  
 * Note: components will be automaticaly allocated if no memory is attached.  
 */   
int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)   
{   
  unsigned int x, y, xstride_by_mcu, ystride_by_mcu;   
  unsigned int bytes_per_blocklines[3], bytes_per_mcu[3];   
  decode_MCU_fct decode_MCU;   
  const decode_MCU_fct *decode_mcu_table;   
  const convert_colorspace_fct *colorspace_array_conv;   
  convert_colorspace_fct convert_to_pixfmt;   
   
  //-------------------------------------------   
    FILE *fp;   
    char *temp;   
    int j,k;   
  //-------------------------------------------   
   
  if (setjmp(priv->jump_state))   
    return -1;   
   
  /* To keep gcc happy initialize some array */   
  bytes_per_mcu[1] = 0;   
  bytes_per_mcu[2] = 0;   
  bytes_per_blocklines[1] = 0;   
  bytes_per_blocklines[2] = 0;   
   
  decode_mcu_table = decode_mcu_3comp_table;   
  switch (pixfmt) {   
     case TINYJPEG_FMT_YUV420P:   
       colorspace_array_conv = convert_colorspace_yuv420p;   
       if (priv->components[0] == NULL)   
     priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);   
       if (priv->components[1] == NULL)   
     priv->components[1] = (uint8_t *)malloc(priv->width * priv->height/4);   
       if (priv->components[2] == NULL)   
     priv->components[2] = (uint8_t *)malloc(priv->width * priv->height/4);   
       bytes_per_blocklines[0] = priv->width;   
       bytes_per_blocklines[1] = priv->width/4;   
       bytes_per_blocklines[2] = priv->width/4;   
       bytes_per_mcu[0] = 8;   
       bytes_per_mcu[1] = 4;   
       bytes_per_mcu[2] = 4;   
       break;   
   
     case TINYJPEG_FMT_RGB24:   
       colorspace_array_conv = convert_colorspace_rgb24;   
       if (priv->components[0] == NULL)   
     priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);   
       bytes_per_blocklines[0] = priv->width * 3;   
       bytes_per_mcu[0] = 3*8;   
       break;   
   
     case TINYJPEG_FMT_BGR24:   
       colorspace_array_conv = convert_colorspace_bgr24;   
       if (priv->components[0] == NULL)   
     priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3);   
       bytes_per_blocklines[0] = priv->width * 3;   
       bytes_per_mcu[0] = 3*8;   
       break;   
   
     case TINYJPEG_FMT_GREY:   
       decode_mcu_table = decode_mcu_1comp_table;   
       colorspace_array_conv = convert_colorspace_grey;   
       if (priv->components[0] == NULL)   
     priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);   
       bytes_per_blocklines[0] = priv->width;   
       bytes_per_mcu[0] = 8;   
       break;   
   
     default:   
#if TRACE_PARAM   
         fprintf(param_trace,"Bad pixel format\n");   
         fflush(param_trace);   
#endif   
       return -1;   
  }   
   
  xstride_by_mcu = ystride_by_mcu = 8;   
  if ((priv->component_infos[cY].Hfactor | priv->component_infos[cY].Vfactor) == 1) {   
     decode_MCU = decode_mcu_table[0];   
     convert_to_pixfmt = colorspace_array_conv[0];   
#if TRACE_PARAM   
     fprintf(param_trace,"Use decode 1x1 sampling\n");   
     fflush(param_trace);   
#endif   
  } else if (priv->component_infos[cY].Hfactor == 1) {   
     decode_MCU = decode_mcu_table[1];   
     convert_to_pixfmt = colorspace_array_conv[1];   
     ystride_by_mcu = 16;   
#if TRACE_PARAM   
     fprintf(param_trace,"Use decode 1x2 sampling (not supported)\n");   
     fflush(param_trace);   
#endif   
  } else if (priv->component_infos[cY].Vfactor == 2) {   
     decode_MCU = decode_mcu_table[3];   
     convert_to_pixfmt = colorspace_array_conv[3];   
     xstride_by_mcu = 16;   
     ystride_by_mcu = 16;   
#if TRACE_PARAM    
     fprintf(param_trace,"Use decode 2x2 sampling\n");   
     fflush(param_trace);   
#endif   
  } else {   
     decode_MCU = decode_mcu_table[2];   
     convert_to_pixfmt = colorspace_array_conv[2];   
     xstride_by_mcu = 16;   
#if TRACE_PARAM   
     fprintf(param_trace,"Use decode 2x1 sampling\n");   
     fflush(param_trace);   
#endif   
  }   
   
  resync(priv);   
   
  /* Don't forget to that block can be either 8 or 16 lines */   
  bytes_per_blocklines[0] *= ystride_by_mcu;   
  bytes_per_blocklines[1] *= ystride_by_mcu;   
  bytes_per_blocklines[2] *= ystride_by_mcu;   
   
  bytes_per_mcu[0] *= xstride_by_mcu/8;   
  bytes_per_mcu[1] *= xstride_by_mcu/8;   
  bytes_per_mcu[2] *= xstride_by_mcu/8;   
   
  /* Just the decode the image by macroblock (size is 8x8, 8x16, or 16x16) */   
  //縱向   
  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);   
   
//DCT系數-----------------------------------------------------------   
        //temp=(char *)priv->component_infos->DCT;   
        //if(y==4&&x==xstride_by_mcu*3){   
        if(priv->dlg->m_vijpgoutputdct.GetCheck()==1){   
            fp = fopen("DCT系數表.txt", "a+");   
            //fwrite(temp,64,1,fp);   
            fprintf(fp,"第%d行,第%d列\n",y,x/xstride_by_mcu);   
            for(j=0;j<64;j++){   
            fprintf(fp,"%d ",priv->component_infos[cY].DCT[j]);   
            }   
            fprintf(fp,"\n");   
            fclose(fp);   
        }   
#if TRACE_PARAM   
        fprintf(param_trace,"\n第3行,第4列\n");   
        for(j=0;j<8;j++){   
            for(k=0;k<8;k++){   
                fprintf(param_trace,"%d ",priv->component_infos[cY].DCT[j*8+k]);   
            }   
            fprintf(param_trace,"\n");   
        }   
        fprintf(fp,"\n-----------------------\n");   
        fflush(param_trace);   
#endif   
        //}   
   
//解碼后系數(Y)---------------------------------------------------   
        //temp=(char *)priv->Y;   
        //if(y==4&&x==xstride_by_mcu*3){   
        if(priv->dlg->m_vijpgoutputy.GetCheck()==1){   
            fp = fopen("解碼后Y系數表.txt", "a+");   
            //fwrite(temp,64*4,1,fp);   
            fprintf(fp,"第%d行,第%d列\n",y,x/xstride_by_mcu);   
            for(j=0;j<64*4;j++){   
            fprintf(fp,"%d ",priv->Y[j]);   
            }   
            fprintf(fp,"\n");   
            fclose(fp);   
        }   
#if TRACE_PARAM   
        fprintf(param_trace,"第3行,第4列\n");   
        for(j=0;j<8;j++){   
            for(k=0;k<8;k++){   
                fprintf(param_trace,"%d ",priv->Y[j*8+k]);   
            }   
            fprintf(param_trace,"\n");   
        }   
        fprintf(fp,"\n-----------------------\n");   
        fflush(param_trace);   
#endif   
        //}   
   
//------------------------------------------------------------------   
        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;   
            }   
         }   
      }   
   }   
#if TRACE_PARAM   
  fprintf(param_trace,"Input file size: %d\n", priv->stream_length+2);   
  fprintf(param_trace,"Input bytes actually read: %d\n", priv->stream - priv->stream_begin + 2);   
  fflush(param_trace);   
#endif   
   
  return 0;   
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM