苏泊尔耗的JPEG解码器[三]

news/2024/11/29 8:58:23/

主控单元。包含普通和渐近两种方式的解码。

头文件

jpegdec2.h(为什么是2呢?因为两年前有一个一代的版本,不过还没问市就被卡嚓了-___-b 默哀ing...)

/**************************************************************************************************

  superarhow's JPEG decoder

  by superarhow(superarhow@hotmail.com).  All rights reserved.

 **************************************************************************************************/

#pragma once

#ifdef _MSC_VER
#pragma warning( push )
#pragma warning(disable: 4142)
#endif

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef int INT32;
typedef short SHORT;

#ifdef _MSC_VER
#pragma warning( pop )
#endif

typedef struct _tag_jpeg_huff_table
{
 /* 1-16位码长的代码的数量 */
 BYTE n_counts[16];
 /* 代码 */
 BYTE codes[256];
 /* 用于从codes中检索代码的索引 */
 BYTE start_code_indexes[16];
 /* 1-16位码长的代码最小值(generated) */
 WORD huff_min_codes[16];
 /* 1-16位码长的代码最大值(generated) */
 WORD huff_max_codes[16];
 /* 总代码数量 */
 WORD n_code_count;
 /* 当一个代码被确认为N位哈夫曼编码(Bits)时,其对应的Code由以下公式取得:
 code = codes[Bits - huff_min_codes[N] + start_code_indexes[N]] */
} jpeg_huff_table, *p_jpeg_huff_table;

typedef struct _tag_jpeg_quality_table
{
 /* 量化精度标志。0表示8位,否则表示16位(有的文档上讲12位?) */
 BYTE precision;
 /* 值为非0表示在idct函数中处理 */
 BYTE process_in_idct;
 /* 量化表元素,64个,定义为DWORD是为了AA&N的需要保留精度 */
 DWORD values[64];
} jpeg_quality_table, *p_jpeg_quality_table;

typedef struct _tag_jpeg_dec_rec
{
 /* 数据流指针 */
 BYTE    *p_data;
 /* 数据流最尾指针+1(pdata不得大于或等于此值) */
 BYTE    *p_data_limit;
 /* 剩余字节,第0到(left_bit_count-1)位有效 */
 BYTE    left_bits;
 /* 剩余位数 */
 BYTE    n_left_bit_count;
 /* 当前扫描的SS(Scan Start),用于渐近操作模式 */
 BYTE    n_curr_scan_ss;
 /* 当前扫描的SE(Scan End),用于渐近操作模式 */
 BYTE    n_curr_scan_se;
 /* 当前扫描的AH(上一行渐近的位数) */
 BYTE    n_curr_scan_ah;
 /* 当前扫描的AL(本行渐近的位数) */
 BYTE    n_curr_scan_al;
 /* 剩余的EOB数量,用于渐近操作模式 */
 WORD    n_eob_count;
 /* 目标位图每行字节数 */
 DWORD    n_bytes_per_line;
 /* 目标缓冲区,由jpeg_make_xxx_buffer函数分配 */
 BYTE    *p_bgr_buffer;
 /* 哈夫曼表。[0][0-3]为DC table, [1][0-3]为AC table */
 jpeg_huff_table  huff_tables[2][4];
 /* 量化表 */
 jpeg_quality_table quality_tables[4];
 /* 所有DU的数量 */
 DWORD    n_du_count;
 /* 所有工作矩阵,需释放(仅针对渐近模式) */
 SHORT    *p_dus;
 /* 采样精度(8,12 or 16, 只支持8) */
 BYTE    n_bits_per_sample;
 /* (当前帧)components 数量(1 byte), 灰度图是 1, YCbCr/YIQ 彩色图是 3, CMYK 彩色图是 4
 component id (1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q) 对应索引号需减1 */
 BYTE    n_components;
 /* 每个分量的ID */
 BYTE    i_component_ids[4];
 /* 纵向采样系数 */
 BYTE    n_vert_sample_coes[4];
 /* 横向采样系数 */
 BYTE    n_horz_sample_coes[4];
 /* 纵向采样系数最大值 */
 BYTE    n_vert_sample_coes_max;
 /* 横向采样系数最大值 */
 BYTE    n_horz_sample_coes_max;
 /* 纵向采样系数最小值 */
 BYTE    n_vert_sample_coes_min;
 /* 横向采样系数最小值 */
 BYTE    n_horz_sample_coes_min;
 /* 当前各组件选用的量化表0-3 */
 BYTE    n_quality_table_indexes[4];
 /* 当前各组件选用的哈夫曼表[0-1][0-3] 0 DC 1 AC */
 BYTE    n_huff_tables_indexes[2][4];
 /* 图片宽度 */
 WORD    n_width;
 /* 图片高度(为0表示用DNL段指出) */
 WORD    n_height;
 /* 由DRI段指出的重启动间隔。为0表示无此信息。此信息用于纠错处理。 */
 WORD    n_reset_size;
 /* 当前重启动MCU数,初始化为n_reset_size */
 WORD    n_reset_cnt;
 /* 当前DC分量 */
 SHORT    i_dc;
 /* 是否渐近方式 */
 BYTE    i_progressive;
} jpeg_dec_rec, *p_jpeg_dec_rec;

/*
 * jpeg_decode_next_block函数返回码 
 */
#define JPEG_FAIL_UNEXPECTED_BYTE  -1  /* unexpected byte (0ffh expected) */
#define JPEG_FAIL_UNKNOWN_BLOCK_TYPE -2  /* unknown block type 未知类型块 */
#define JPEG_FAIL_DECODE_ERROR   -3  /* 已知块,但解码失败 */
#define JPEG_SUCCESS_NEXTBLOCK   0  /* 成功,等待下一个块的解码 */
#define JPEG_SUCCESS_LASTBLOCK   1  /* 成功,且已是最后一块 */
#define JPEG_SUCCESS_IGNORED   2  /* unsupported block type 不支持的块,已忽略 */

/* 初始化解码器 */
void jpeg_init_decoder(p_jpeg_dec_rec p_rec);
/*
 *  处理下一个块。返回值
 * JPEG_FAIL_UNEXPECTED_BYTE  unexpected byte (0ffh expected)
 * JPEG_FAIL_UNKNOWN_BLOCK_TYPE unknown block type 未知类型块
 * JPEG_FAIL_DECODE_ERROR   已知块,但解码失败
 * JPEG_SUCCESS_NEXTBLOCK   成功,等待下一个块的解码
 * JPEG_SUCCESS_LASTBLOCK   成功,且已是最后一块
 * JPEG_SUCCESS_IGNORED   unsupported block type 不支持的块,已忽略
 * 在处理每个块时,将先过滤掉前面的0xff。因此在各明确的块处理段将无0xff
 */
int jpeg_decode_next_block(p_jpeg_dec_rec p_rec);
/* 反初始化解码器 */
void jpeg_clear_up(p_jpeg_dec_rec p_rec);
/* RST,内部使用 */
void jpeg_reset(p_jpeg_dec_rec p_rec);

******************************************* 广告位招租 *******************************************

jpegdec2.c(代码非常长,因为jpeg的格式实在是……其实最麻烦的不是什么哈夫曼编码、色彩

空间变换和IDCT…最麻烦的是处理扫描的过程,分量、分量的分块、Z字型、渐近,吐血啊……)

****************************************************************************************************

/**************************************************************************************************

  superarhow's JPEG decoder

  by superarhow(superarhow@hotmail.com).  All rights reserved.

 **************************************************************************************************/

#include "jpegdec2.h"
#include "jpeghuff.h"
#include "jpegbuf.h"
#include "jpegidct.h"


#include "stdio.h"
#include "windows.h"

#define NextByte(p) (*(p->p_data++))
#define CurByte(p) (*(p->p_data))
#define PrevByte(p) (*(--p->p_data))
#define WORD_ALIGN(p) (p) = (((p) + 1) / 2) * 2
#define DWORD_ALIGN(p) (p) = (((p) + 3) / 4) * 4

void jpeg_reset(p_jpeg_dec_rec p_rec)
{
 p_rec->n_left_bit_count = 0;
 p_rec->n_reset_cnt = p_rec->n_reset_size;
 p_rec->i_dc = 0;
 p_rec->n_eob_count = 0;
}

BYTE jpeg_next_byte(p_jpeg_dec_rec p_rec)
{
 BYTE b;
 for ( ;; ) {
  b = *p_rec->p_data++;
  if (b == 0xFF) {
   b = *p_rec->p_data++;
   if (b == 0) return 0xFF;
   if (b >= 0xD0 && b <= 0xD7) {
    /* RSTn */
    jpeg_reset(p_rec);
   } else return b;
  } else return b;
 }
 return 0;
}

WORD jpeg_next_word(p_jpeg_dec_rec p_rec)
{
 WORD w = (p_rec->p_data[0] << 8) | (p_rec->p_data[1]);
 p_rec->p_data += 2;
 return w;
}

/* 初始化解码器 */
void jpeg_init_decoder(p_jpeg_dec_rec p_rec)
{
 p_rec->n_width = 0;
 p_rec->n_height = 0;
 p_rec->n_reset_size = 0;
 p_rec->left_bits = 0;
 p_rec->n_left_bit_count = 0;
 p_rec->n_horz_sample_coes_max = 0;
 p_rec->n_vert_sample_coes_max = 0;
 p_rec->n_horz_sample_coes_min = 0xff;
 p_rec->n_vert_sample_coes_min = 0xff;
 p_rec->p_bgr_buffer = NULL;
 p_rec->p_data = NULL;
 p_rec->i_dc = 0;
 p_rec->i_progressive = 0;
 p_rec->p_dus = NULL;
 p_rec->n_eob_count = 0;
}

/* 反初始化解码器 */
void jpeg_clear_up(p_jpeg_dec_rec p_rec)
{
}

/*
 * 跳过下一个块
 *  返回非0表示成功
 */
int jpeg_skip_next_block(p_jpeg_dec_rec p_rec)
{
 BYTE b;
 WORD n;
 b = NextByte(p_rec);
 if (b == 0x01 /* TEM 结束标志*/ || (b >= 0xd0 && b <= 0xd9 /* RSTn OR SOI OR EOI*/)) return 1;
 n = jpeg_next_word(p_rec);
 p_rec->p_data += (n - 2);
 return 1;
}

/*
 * 处理帧开始标记
 *  返回非0表示成功
 */
int jpeg_decode_SOF0(p_jpeg_dec_rec p_rec)
{
 BYTE b, index, n;

 /* skip tag */
 NextByte(p_rec);
 jpeg_next_word(p_rec);

 /* 采样精度 */
 p_rec->n_bits_per_sample = NextByte(p_rec);
 /* 图像高度(为0表示通过DNL标记指定) */
 p_rec->n_height = jpeg_next_word(p_rec);
 /* 图像宽度 */
 p_rec->n_width = jpeg_next_word(p_rec);
 /* 每行字节数 */
 p_rec->n_bytes_per_line = ((DWORD)p_rec->n_width) * 3;
 DWORD_ALIGN(p_rec->n_bytes_per_line);

 /* 分量数 */
 p_rec->n_components = NextByte(p_rec);

 if (p_rec->n_components <= 0 || p_rec->n_components > 4) return 0; /* 不支持的分量数 */

 for ( n = 0; n < p_rec->n_components; ++n ) {
  /* 分量ID */
  p_rec->i_component_ids[n] = jpeg_next_byte(p_rec);
  /*
   * Note!!!!
   * Our index here doesn't mean component ids, its only an index
   * We also reference our huffman-table & quanlity-table by index not by component id.
   */
  index = n;
  if ( index >= p_rec->n_components ) return 0; /* 出现了错误的分量ID */
  b = jpeg_next_byte(p_rec);
  /* 分量采样率 */
  p_rec->n_vert_sample_coes[index] = b & 0xf;
  p_rec->n_horz_sample_coes[index] = b >> 4;
  /* 计算分量采样率最大值 */
  if (p_rec->n_vert_sample_coes[index] > p_rec->n_vert_sample_coes_max) p_rec->n_vert_sample_coes_max = p_rec->n_vert_sample_coes[index];
  if (p_rec->n_horz_sample_coes[index] > p_rec->n_horz_sample_coes_max) p_rec->n_horz_sample_coes_max = p_rec->n_horz_sample_coes[index];
  if (p_rec->n_vert_sample_coes[index] < p_rec->n_vert_sample_coes_min) p_rec->n_vert_sample_coes_min = p_rec->n_vert_sample_coes[index];
  if (p_rec->n_horz_sample_coes[index] < p_rec->n_horz_sample_coes_min) p_rec->n_horz_sample_coes_min = p_rec->n_horz_sample_coes[index];
  b = jpeg_next_byte(p_rec);
  if (b >= 4) return 0; /* 出现了错误的量化表ID */
  p_rec->n_quality_table_indexes[index] = b;
 }

 return 1;
}

/*
 * 处理定义重启动段标志
 *  返回非0表示成功
 */
int jpeg_decode_DRI(p_jpeg_dec_rec p_rec)
{
 NextByte(p_rec);
 jpeg_next_word(p_rec);
 p_rec->n_reset_size = jpeg_next_word(p_rec);
 p_rec->n_reset_cnt = jpeg_next_word(p_rec);
 return 1;
}

/*
 * 处理定义量化表标志
 */
int jpeg_decode_DQT(p_jpeg_dec_rec p_rec)
{
 WORD size;
 BYTE b, index, coe;
 WORD i;
 NextByte(p_rec);
 size = jpeg_next_word(p_rec) - 2;
 while ( size > 0 ) {
  b = jpeg_next_byte(p_rec);
  index = b & 0xf;
  if ( index >= 4 ) return 0;  /* 出现了非法的量化表ID */
  coe = b >> 4;
  if ( coe != 0 ) coe = 1;
  /* 量化表精度,0:8位 非0:16位 */
  p_rec->quality_tables[index].precision = coe;
  if ( coe == 0 ) {
   /* 8位量化表 */
   for ( i = 0; i < 64; i++ ) {
    p_rec->quality_tables[index].values[i] = jpeg_next_byte(p_rec);
   }
   p_rec->quality_tables[index].process_in_idct = 0;
   jpeg_idct_prepare_qualitytable(&p_rec->quality_tables[index]);
   size -= (64 + 1);
  } else {
   /* 16位量化表 */
   for ( i = 0; i < 64; i++ ) {
    p_rec->quality_tables[index].values[i] = jpeg_next_word(p_rec);
   }
   p_rec->quality_tables[index].process_in_idct = 0;
   jpeg_idct_prepare_qualitytable(&p_rec->quality_tables[index]);
   size -= (64 * 2 + 1);
  }
 }
 return 1;
}

/*
 * 生成解码用哈夫曼表
 */
void jpeg_make_huff_table(p_jpeg_huff_table p_table)
{
 WORD mask;
 WORD i, j, k;
 p_table->huff_min_codes[0] = 0;
 for ( i = 0, mask = 0, j = 0, k = 0; i < p_table->n_code_count; ) {

  if ( j >= p_table->n_counts[k] ) {

   if ( j == 0 ) {
    /* 无k位Huffman码,则置huff_max_codes[k]为0、huff_min_codes[k]为0xffff以示区别 */
    p_table->huff_min_codes[k] = 0xffff;
    p_table->huff_max_codes[k] = 0;
   } else {
    j = 0;
   }

   mask <<= 1;
   k++;
   if ( k < 16 ) p_table->huff_min_codes[k] = mask;

  } else {

   p_table->huff_max_codes[k] = mask;
   mask++;
   j++;
   i++;

  }

 } /* end of for(...) */
}

/*
 * 处理定义哈夫曼表标志
 */
int jpeg_decode_DHT(p_jpeg_dec_rec p_rec)
{
 BYTE b, index, type;
 WORD size, total, i;
 NextByte(p_rec);
 size = jpeg_next_word(p_rec) - 2;
 while ( size > 0 ) {
  b = jpeg_next_byte(p_rec);
  index = b & 0xf;
  if (index >= 4) return 0; /* 出现了非法的哈夫曼表ID */

  type = b >> 4;
  if (type > 1) return 0; /* 非法的哈夫曼表类型 */

  total = 0;
  for ( i = 0; i < 16; i++ ) {
   b = jpeg_next_byte(p_rec);
   p_rec->huff_tables[type][index].n_counts[i] = b;
   p_rec->huff_tables[type][index].start_code_indexes[i] = (BYTE)total;
   total += b;
  }

  p_rec->huff_tables[type][index].n_code_count = total;
  memcpy(p_rec->huff_tables[type][index].codes, p_rec->p_data, total);
  jpeg_make_huff_table( &(p_rec->huff_tables[type][index]) );
  
  p_rec->p_data += total;
  if ( p_rec->p_data >= p_rec->p_data_limit ) return 0; /* 数据不够 */
  size -= (total + 16 + 1);
 }
 return 1;
}

/*
 * 查找EOI标记。找到返回非0
 */
int jpeg_scan_for_eoi( p_jpeg_dec_rec p_rec )
{
 BYTE *p = p_rec->p_data;
 for ( ;; ) {
  if ( p + 1 >= p_rec->p_data_limit ) break;
  if ( *p == 0xff ) {
   if ( p[1] == 0xD9 ) break;
   else {
    if ( p[1] >= 0xD0 && p[1] <= 0xD7 ) {
     /* RSTn */
     p += 2;
    } else if ( p[1] == 0 ) {
     return 0;
    } else {
     jpeg_decode_next_block(p_rec);
    }
   }
  } else {
   return 0;
  }
 }
 return 1;
}

/*
 * 解码帧(非渐近方式)
 *  返回非0表示成功
 */
int jpeg_decode_scanlines(p_jpeg_dec_rec p_rec)
{
 static BYTE _un_zig_zag[64] = {
   0, 1, 8, 16, 9, 2, 3,10,
   17,24,32,25,18,11, 4, 5,
   12,19,26,33,40,48,41,34,
   27,20,13, 6, 7,14,21,28,
   35,42,49,56,57,50,43,36,
   29,22,15,23,30,37,44,51,
   58,59,52,45,38,31,39,46,
   53,60,61,54,47,55,62,63
 };
 /* 工作矩阵(Data Unit) */
 SHORT    du[64];
 /* 指向当前量化表数值 */
 DWORD    *pw_quality_values;
 /* 各组件DC分量值 */
 SHORT    dc[5] = { 0, 0, 0, 0, 0 };
 /* 各组件缓冲区,需释放 */
 BYTE*    p_com_bufs[5] = { NULL, NULL, NULL, NULL, NULL };
 /* 每段每组件扫描完后地址偏移量,需释放 */
 int*    p_com_buf_incs[5] = { NULL, NULL, NULL, NULL, NULL };
 /* 指向p_com_bufs的当前地址(当p_com_bufs被重新分配时,应当重新计算!!!) */
 BYTE*    p_com_ptrs[5] = { NULL, NULL, NULL, NULL, NULL };
 /* 组件宽度(像素) */
 WORD    w_com_widths[5] = { 0, 0, 0, 0, 0 };
 /* 组件宽度(像素),若w_scanlines为0,则此值持续变动 */
 WORD    w_com_heights[5] = { 0, 0, 0, 0, 0 };
 /* 每组件长宽方向上的数量 */
 BYTE    n_com_counts[5] = { 0, 0, 0, 0, 0 };
 /* 每组件每像素行扫描完后地址增加字节数 */
 DWORD    dw_com_line_incs[5] = { 0, 0, 0, 0, 0 };
 /* 每组件每扫描行扫描完后地址增加字节数 */
 DWORD    dw_com_scanline_incs[5] = { 0, 0, 0, 0, 0 };
 /* 段数,扫描行数(为0表示在扫描过程中指定),剩余行数 */
 WORD    w_segments, w_scanlines, w_leftlines;
 /* 当w_scanlines为0时,此值表示当前已分配的扫描行数 */
 WORD    w_alloc_scanlines;
 /* 当前AC哈夫曼表,当前DC哈夫曼表 */
 p_jpeg_huff_table p_ac_huff_table, p_dc_huff_table;
 /* 当前量化表 */
 p_jpeg_quality_table p_quality_table;
 /* RS(游程码) */
 BYTE    RS;
 /* BITS(剩余位) */
 WORD    BITS;
 /* RRRR(RS的高4位), SSSS(RS的低4位) */
 BYTE    RRRR, SSSS;
 DWORD    dw_offset, dw_old_offset;
 BYTE    i, j, m, n, cnt;
 BYTE    *p;
 SHORT    *p_i;
 SHORT    i_ac;
 WORD    k;

 w_segments = (WORD)( (p_rec->n_width + p_rec->n_horz_sample_coes_max * 8 - 1) / (p_rec->n_horz_sample_coes_max * 8) );
 if ( p_rec->n_height != 0 ) {
  w_scanlines = (WORD)( (p_rec->n_height + p_rec->n_vert_sample_coes_max * 8 - 1) / (p_rec->n_vert_sample_coes_max * 8) );
  w_alloc_scanlines = w_scanlines;
  w_leftlines = w_scanlines;
 } else w_scanlines = 0;

 /* 预分配各组件扫描临时区域 */
 for ( i = 0; i < p_rec->n_components; i++ ) {
  n_com_counts[i] = p_rec->n_horz_sample_coes[i] * p_rec->n_vert_sample_coes[i];
  w_com_widths[i] = (WORD)(w_segments * p_rec->n_horz_sample_coes[i] * 8);
  dw_com_line_incs[i] = w_com_widths[i] - 8;
  dw_com_scanline_incs[i] = (DWORD)w_com_widths[i] * p_rec->n_vert_sample_coes[i] * 8 - w_com_widths[i];  

  p_com_buf_incs[i] = (int*)malloc( w_com_widths[i] * sizeof(int*) );
  if ( w_scanlines == 0 ) {
   /* 宽度不定,先分配1行 */
   w_alloc_scanlines = 1;
   w_com_heights[i] = (WORD)(w_alloc_scanlines * p_rec->n_vert_sample_coes[i] * 8);
   p_com_bufs[i] = (BYTE*)malloc( (DWORD)w_com_widths[i] * (DWORD)w_com_heights[i] );
  } else {
   /* 宽度已知 */
   w_com_heights[i] = (WORD)(w_scanlines * p_rec->n_vert_sample_coes[i] * 8);
   p_com_bufs[i] = (BYTE*)malloc( (DWORD)w_com_widths[i] * (DWORD)w_com_heights[i] );
  }
  if ( p_com_buf_incs[i] != NULL ) {
   dw_old_offset = dw_offset = 0;
   for ( j = 0, n = 0; n < p_rec->n_vert_sample_coes[i]; ++n ) {
    for ( m = 0; m < p_rec->n_vert_sample_coes[i]; ++m, ++j ) {
     dw_offset = (DWORD)n * 8 * w_com_widths[i] + m * 8;
     if ( j > 0 ) p_com_buf_incs[i][j - 1] = dw_offset - dw_old_offset;
     dw_old_offset = dw_offset;
    }
   }
   dw_offset = (DWORD)p_rec->n_horz_sample_coes[i] * 8;
   p_com_buf_incs[i][j - 1] = dw_offset - dw_old_offset;
  }
  p_com_ptrs[i] = p_com_bufs[i];
 }

 /* Check for invalid buffers */
 for ( i = 0; i < p_rec->n_components; ++i )
 {
  /* 有缓冲区未正确分配? */
  if (p_com_bufs[i] == NULL || p_com_buf_incs[i] == NULL)
  {
   // 释放所有已分配的缓冲区并返回失败
   for ( j = 0; j < p_rec->n_components; ++j )
   {
    if (p_com_bufs[j] != NULL) free(p_com_bufs[j]);
    if (p_com_buf_incs[j] != NULL) free(p_com_buf_incs[j]);
   }
   return 0;
  }
 }

 /* 行扫描 */
 for ( ;; ) {
  /* 段扫描 */
  for ( k = 0; k < w_segments; ++k ) {
   /* 交错扫描方式:组件1,组件2,组件3... */
   for ( i = 0; i < p_rec->n_components; ++i ) {
    /* 组件i使用的DC表 */
    p_dc_huff_table = &p_rec->huff_tables[0][p_rec->n_huff_tables_indexes[0][i]];
    /* 组件i使用的AC表 */
    p_ac_huff_table = &p_rec->huff_tables[1][p_rec->n_huff_tables_indexes[1][i]];
    for ( cnt = 0; cnt < n_com_counts[i]; ++cnt ) {
     /* 初始化工作矩阵 */
     memset(du, 0, 64 * sizeof(SHORT));

     /* 当前DC系数 */
     p_rec->i_dc = dc[i];
     /* 当前量化表 */
     p_quality_table = &p_rec->quality_tables[p_rec->n_quality_table_indexes[i]];
     /* 当前量化表值 */
     pw_quality_values = p_quality_table->values;

     /* 解码RS(流程码值) */
     RS = jpeg_dec_next_huff_code(p_rec, p_dc_huff_table);
     /* 对于DC,RS直接指出位数 */
     if (RS > 0) BITS = jpeg_get_next_bits(p_rec, RS);
     else BITS = 0;
     p_rec->i_dc += BITS;
     if ( RS != 0 ) {
      if ( BITS < (1 << (RS - 1)) ) p_rec->i_dc -= ((1 << RS) - 1);
     }
     dc[i] = p_rec->i_dc;
     if ( !p_quality_table->process_in_idct ) {
      /* 反量化 */
      du[0] = p_rec->i_dc * (*pw_quality_values);
      ++pw_quality_values;
     } else {
      du[0] = p_rec->i_dc;
     }
     

     j = 1;
     /* 解Z字型地址 */
     p = &_un_zig_zag[j];

     while ( j < 64 ) {
      RS = jpeg_dec_next_huff_code(p_rec, p_ac_huff_table);
      if ( !RS ) {
       /* EOB */
       break;
      }
      RRRR = RS >> 4;
      /* 跳过的0分量数 */
      j += RRRR;
      p += RRRR;
      pw_quality_values += RRRR;
      if ( j >= 64 ) break;
      SSSS = RS & 0xf;
      if ( !SSSS ) {
       /* 分量为0 */
       ++j; ++p; ++pw_quality_values;
      } else {
       i_ac = jpeg_get_next_bits(p_rec, SSSS);
       if ( i_ac < (1 << (SSSS - 1)) ) i_ac -= ((1 << SSSS) - 1);
       if ( !p_quality_table->process_in_idct ) {
        i_ac *= *pw_quality_values;
        ++pw_quality_values;
       } else {

       }
       du[*p] = i_ac;
       ++j; ++p;
      }
     } /* DU 解码(+反量化)完成 */

     /* IDCT */
     jpeg_idct(p_quality_table, du);

     p = p_com_ptrs[i];
     p_i = du;
     for ( n = 0; n < 8; ++n ) {
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      p += dw_com_line_incs[i];
     }
     p_com_ptrs[i] += p_com_buf_incs[i][cnt];
    } /* cnt */
   } /* i */
   
   if ( p_rec->n_reset_size != 0 && --p_rec->n_reset_cnt == 0 ) {
    /* RESET间隔已到,检查RSTn标志 */
    if ( p_rec->p_data + 1 >= p_rec->p_data_limit ) goto _exit;
    if ( CurByte(p_rec) == 0xff && p_rec->p_data[1] >= 0xD0 && p_rec->p_data[1] <= 0xD7 ) {
     /* RSTn标志出现 */
     p_rec->p_data += 2;
     jpeg_reset(p_rec);
     memset(dc, 0, 4 * sizeof(SHORT));
    } else {
     /* next??? */
     ++p_rec->n_reset_cnt;
    }
   }
  } /* k */
  /* 下一行 */
  for ( i = 0; i < p_rec->n_components; ++i ) p_com_ptrs[i] += dw_com_scanline_incs[i];
  /* 动态高度? */
  if ( w_scanlines == 0 ) {
   /* 检查并重新分配各组件缓冲区,并调整指针 */
   p_rec->n_height += p_rec->n_horz_sample_coes_max * 8;
   while ( (WORD)( (p_rec->n_height + p_rec->n_vert_sample_coes_max * 8 - 1) / (p_rec->n_vert_sample_coes_max * 8) ) > w_alloc_scanlines ) {
    w_alloc_scanlines *= 2;
    for ( i = 0; i < p_rec->n_components; ++i ) {
     w_com_heights[i] = (WORD)(w_alloc_scanlines * p_rec->n_vert_sample_coes[i] * 8);
     p = p_com_bufs[i];
     /* 重新分配 */
     p_com_bufs[i] = (BYTE*)realloc( p_com_bufs[i], (DWORD)w_com_widths[i] * (DWORD)w_com_heights[i] );
     if ( p_com_ptrs[i] == NULL ) goto _exit;
     /* 重新计算偏移 */
     p_com_ptrs[i] = p_com_bufs[i] + (p_com_ptrs[i] - p);
    }
   }
   /* TODO: parse the DNL */
  } else {
   /* 高度已知 */
   if ( --w_leftlines == 0 ) break;
  }
 } /* scanlines */
 /* 生成位图 */
 if ( p_rec->n_components == 3 ) jpeg_make_rgb_buffer(p_rec, p_com_bufs, w_com_widths);
 else if ( p_rec->n_components == 1 ) jpeg_make_gray_buffer(p_rec, p_com_bufs, w_com_widths);
 //else if ( p_rec->n_components == 4 )
_exit:
 for ( i = 0; i < p_rec->n_components; ++i )
 {
  if (p_com_bufs[i] != NULL) free(p_com_bufs[i]);
  if (p_com_buf_incs[i] != NULL) free(p_com_buf_incs[i]);
 }
 return 1;
}

int jpeg_check_for_scan_end(p_jpeg_dec_rec p_rec)
{
 if ( *p_rec->p_data == 0xFF ) {
  if ( p_rec->p_data + 1 >= p_rec->p_data_limit ) return 1;
  if ( p_rec->p_data[1] == 0 ) return 0;
  if ( p_rec->p_data[1] >= 0xD0 && p_rec->p_data[1] <= 0xD7 ) return 0;
  return 1;
 }
 return 0;
}

#define CEIL_DIV(p, q)  (((p) + (q) - 1) / (q))

/*
* 解码帧(渐近方式)
*  返回非0表示成功
*/
int jpeg_decode_scanlines_progressive(p_jpeg_dec_rec p_rec, BYTE *component_indexes, BYTE n_curr_scan_components)
{
 /* Z字型->DU顺序索引 */
 static BYTE _un_zig_zag[64] = {
  0, 1, 8, 16, 9, 2, 3,10,
  17,24,32,25,18,11, 4, 5,
  12,19,26,33,40,48,41,34,
  27,20,13, 6, 7,14,21,28,
  35,42,49,56,57,50,43,36,
  29,22,15,23,30,37,44,51,
  58,59,52,45,38,31,39,46,
  53,60,61,54,47,55,62,63
 };
 /* 当前工作矩阵(Data Unit) */
 SHORT    *p_curr_du;
 /* 各组件DC分量值 */
 SHORT    dc[5] = { 0, 0, 0, 0, 0 };
 /* 每组件长宽方向上的数量 */
 BYTE    n_com_counts[5] = { 0, 0, 0, 0, 0 };
 BYTE    n_com_offsets[5] = { 0, 0, 0, 0, 0 };
 BYTE    n_com_total_count = 0;
 BYTE    n_curr_scan_component_index;
 DWORD    n_com_offset;
 WORD    w_segments, w_scanlines, w_leftlines, w_max_segments, w_max_scanlines;
 /* 当前AC哈夫曼表,当前DC哈夫曼表 */
 p_jpeg_huff_table p_ac_huff_table, p_dc_huff_table;
 /* RS(游程码) */
 BYTE    RS;
 /* BITS(剩余位) */
 WORD    BITS;
 /* RRRR(RS的高4位), SSSS(RS的低4位) */
 BYTE    RRRR, SSSS;
 BYTE    i, j, index, cnt;
 BYTE    i_first_scan;
 BYTE    *p;
 SHORT    i_ac, i_dc_diff;
 WORD    k, du_index, x_block, y_block, du_cnt, x_inc, y_inc, x_pos, y_pos, x, y;
 /* 渐近方式,du索引转换表 */
 WORD    *progressive_du_indexes = NULL;

 /* 渐近方式不支持动态高度 */
 if ( p_rec->n_height == 0 ) return 0;

 w_max_segments = (WORD)CEIL_DIV(p_rec->n_width, p_rec->n_horz_sample_coes_max * 8);
 w_max_scanlines = (WORD)CEIL_DIV(p_rec->n_height, p_rec->n_vert_sample_coes_max * 8);

 if ( n_curr_scan_components == 1 ) {
  for ( i = 0; i < p_rec->n_components; ++i ) {
   if ( component_indexes[i] <= 3 ) {
    /* curr scan component index */
    j = component_indexes[i];
    n_curr_scan_component_index = j;
    w_segments = (WORD)CEIL_DIV(p_rec->n_width, p_rec->n_horz_sample_coes_max / p_rec->n_horz_sample_coes[j] * 8);
    w_scanlines = (WORD)CEIL_DIV(p_rec->n_height, p_rec->n_vert_sample_coes_max / p_rec->n_vert_sample_coes[j] * 8);
    x_inc = p_rec->n_horz_sample_coes[j];
    y_inc = p_rec->n_vert_sample_coes[j];
    break;
   }
  }
  progressive_du_indexes = (WORD*)malloc( w_segments * w_scanlines * sizeof(WORD) );
  du_index = 0;
  du_cnt = 0;
  for ( i = 0; i < p_rec->n_components; i++ ) {
   n_com_counts[i] = p_rec->n_horz_sample_coes[i] * p_rec->n_vert_sample_coes[i];
  }
  for ( y_block = 0, y_pos = 0; y_block < w_max_scanlines; ++y_block, y_pos += y_inc ) {
   for ( x_block = 0, x_pos = 0; x_block < w_max_segments; ++x_block, x_pos += x_inc ) {
    x = x_pos;
    y = y_pos;
    for ( i = 0; i < p_rec->n_components; ++i ) {
     for ( j = 0; j < n_com_counts[i]; ++j, ++du_cnt ) {
      du_index = y * w_segments + x;
      if ( i == n_curr_scan_component_index ) {
       if ( y < w_scanlines && x < w_segments ) {
        progressive_du_indexes[du_index] = du_cnt;
       }
       ++x;
       if ( x >= x_pos + x_inc ) {
        x = x_pos;
        ++y;
       }
      }
     }
    }
   }
  }
 } else {
  w_segments = w_max_segments;
  w_scanlines = w_max_scanlines;
 }
 w_leftlines = w_scanlines;

 /* 预分配各组件扫描临时区域 */
 p_rec->n_du_count = 0;
 n_com_total_count = 0;
 for ( i = 0; i < p_rec->n_components; i++ ) {
  n_com_counts[i] = p_rec->n_horz_sample_coes[i] * p_rec->n_vert_sample_coes[i];
  n_com_offsets[i] = n_com_total_count;
  n_com_total_count += n_com_counts[i];
  p_rec->n_du_count += (DWORD)w_max_segments * p_rec->n_horz_sample_coes[i] * w_max_scanlines * p_rec->n_vert_sample_coes[i];
 }

 /* Allocate DUs */
 if ( !p_rec->p_dus ) {
  p_rec->p_dus = (SHORT*)malloc( p_rec->n_du_count * sizeof(SHORT) * 64 );
  memset( p_rec->p_dus, 0, p_rec->n_du_count * sizeof(SHORT) * 64 );
 }

 /* Check for invalid buffer */
 if (p_rec->p_dus == NULL) return 0;

 i_first_scan = p_rec->n_curr_scan_ah == 0;
 p_curr_du = p_rec->p_dus;
 /* TODO: reorder the scan process */
 /* 行扫描 */
 du_index = 0;
 for ( ;; ) {
  /* 段扫描 */
  for ( k = 0; k < w_segments; ++k ) {
   /* 交错扫描方式:组件1,组件2,组件3... */
   for ( i = 0; i < p_rec->n_components; ++i ) {

    index = component_indexes[i];
    /* 本次没有扫描此组件 */
    if ( index >= 4 ) {
     p_curr_du += 64 * n_com_counts[i];
     continue;
    }

    if ( n_curr_scan_components == 1 ) {
     n_com_offset = progressive_du_indexes[du_index];
     p_curr_du = p_rec->p_dus + (DWORD)n_com_offset * 64;
    }

    /* 组件i使用的DC表 */
    p_dc_huff_table = &p_rec->huff_tables[0][p_rec->n_huff_tables_indexes[0][index]];
    /* 组件i使用的AC表 */
    p_ac_huff_table = &p_rec->huff_tables[1][p_rec->n_huff_tables_indexes[1][index]];    

    cnt = n_com_counts[index];
    if ( n_curr_scan_components == 1 ) cnt = 1;
    for ( ; cnt > 0; --cnt ) {

     if ( p_rec->n_curr_scan_ss == 0 /* DC扫描行 */ ) {

      /* 第一次DC扫描 */
      if ( i_first_scan ) {
       /* 当前DC系数 */
       p_rec->i_dc = dc[index];

       /* 解码RS(流程码值) */
       RS = jpeg_dec_next_huff_code(p_rec, p_dc_huff_table);
       /* 对于DC,RS直接指出位数 */
       if (RS > 0) BITS = jpeg_get_next_bits(p_rec, RS);
       else BITS = 0;
       i_dc_diff = BITS;
       if ( RS != 0 ) {
        if ( BITS < (1 << (RS - 1)) ) i_dc_diff -= ((1 << RS) - 1);
       }
       p_rec->i_dc += i_dc_diff;
       p_curr_du[0] = p_rec->i_dc << p_rec->n_curr_scan_al;
       dc[index] = p_rec->i_dc;
      } else {
       /* 后续DC扫描行 */
       if ( jpeg_get_next_bits(p_rec, 1) != 0 ) {
        p_curr_du[0] |= (1 << p_rec->n_curr_scan_al);
       }
      }

     } else {

      j = p_rec->n_curr_scan_ss;
      /* 解Z字型地址 */
      p = &_un_zig_zag[j];

      while ( j <= p_rec->n_curr_scan_se ) {

       /* 处理EOB */
       if ( p_rec->n_eob_count > 0 ) {
        --p_rec->n_eob_count;
        if ( !i_first_scan ) {
         /* 处理在0串中的带有非0历史的系数的校正位 */
         while ( j <= p_rec->n_curr_scan_se ) {
          if ( p_curr_du[*p] != 0 ) {
           if ( jpeg_get_next_bits(p_rec, 1) ) {
            /* 有校正 */
            if ( p_curr_du[*p] >= 0 ) p_curr_du[*p] += (1 << p_rec->n_curr_scan_al);
            else p_curr_du[*p] -= (1 << p_rec->n_curr_scan_al);
           } /* else 没有校正 */
          }
          ++j; ++p;
         }
        }
        break;
       }

       RS = jpeg_dec_next_huff_code(p_rec, p_ac_huff_table);

       if ( !RS ) {        
        if ( !i_first_scan ) {
         /* 处理在0串中的带有非0历史的系数的校正位 */
         while ( j <= p_rec->n_curr_scan_se ) {
          if ( p_curr_du[*p] != 0 ) {
           if ( jpeg_get_next_bits(p_rec, 1) ) {
            /* 有校正 */
            if ( p_curr_du[*p] >= 0 ) p_curr_du[*p] += (1 << p_rec->n_curr_scan_al);
            else p_curr_du[*p] -= (1 << p_rec->n_curr_scan_al);
           } /* else 没有校正 */
          }
          ++j; ++p;
         }
        }
        break;
       }

       RRRR = RS >> 4;
       SSSS = RS & 0xf;

       if ( (!SSSS) && (RRRR < 15) ) {

        /* EOBn */
        if ( RRRR == 0 ) BITS = 1;
        else {
         BITS = jpeg_get_next_bits(p_rec, RRRR);
         BITS += (1 << RRRR);
        }
        p_rec->n_eob_count = BITS;
        continue;

       }

       if ( SSSS ) {
        i_ac = jpeg_get_next_bits(p_rec, SSSS);
       }

       /* 跳过的0分量数 */
       if ( i_first_scan ) {
        j += RRRR;
        p += RRRR;
       } else {
        if ( SSSS != 1 && SSSS != 0 ) _asm int 3;

        /* 处理在0串中的带有非0历史的系数的校正位 */
        while ( j <= p_rec->n_curr_scan_se ) {
         if ( p_curr_du[*p] != 0 ) {
          if ( jpeg_get_next_bits(p_rec, 1) ) {
           /* 有校正 */
           if ( p_curr_du[*p] >= 0 ) p_curr_du[*p] += (1 << p_rec->n_curr_scan_al);
           else p_curr_du[*p] -= (1 << p_rec->n_curr_scan_al);
          } /* else 没有校正 */
         } else {
          /* !!! 校正扫描中,在计算行程时忽略非0值 */
          if ( RRRR-- == 0 ) break;
         }
         ++j; ++p;
        }
       }
       if ( j > p_rec->n_curr_scan_se )
        break;
       
       if ( !SSSS ) {

        ++j; ++p;

       } else {

        if ( i_first_scan ) {

         if ( i_ac < (1 << (SSSS - 1)) ) i_ac -= ((1 << SSSS) - 1);

         p_curr_du[*p] = (i_ac << p_rec->n_curr_scan_al);

        } else {

         /* SSSS must equals 1 here */
         /* p_curr_du[*p] must equals 0 here */
         /* 1位符号位 */
         if ( i_ac ) {
          /* 正 */
          p_curr_du[*p] = 1 << p_rec->n_curr_scan_al;
         } else {
          /* 负 */
          p_curr_du[*p] = -(1 << p_rec->n_curr_scan_al);
         }
        }
        ++j; ++p;

       }
      } /* DU 解码(+反量化)完成 */
     }
     p_curr_du += 64;
     if ( n_curr_scan_components == 1 ) {
      ++du_index;
     }
    } /* cnt */
   } /* i */

   if ( p_rec->n_reset_size != 0 && --p_rec->n_reset_cnt == 0 ) {
    /* RESET间隔已到,检查RSTn标志 */
    if ( p_rec->p_data + 1 >= p_rec->p_data_limit ) goto _exit;
    if ( CurByte(p_rec) == 0xff && p_rec->p_data[1] >= 0xD0 && p_rec->p_data[1] <= 0xD7 ) {
     /* RSTn标志出现 */     
     p_rec->p_data += 2;
     jpeg_reset(p_rec);
     memset(dc, 0, 4 * sizeof(SHORT));
    } else {
     /* next??? */
     ++p_rec->n_reset_cnt;
    }
   }
  } /* k */
  if ( --w_leftlines == 0 )
  {
   if ( p_rec->n_left_bit_count != 0 ) {
    p_rec->n_left_bit_count = 0;
   }
   p_rec->n_reset_cnt = p_rec->n_reset_size;
   p_rec->i_dc = 0;
   memset(dc, 0, 4 * sizeof(SHORT));
   break;
  }
 } /* scanlines */
_exit:
 if ( progressive_du_indexes ) free(progressive_du_indexes);
 return 1;
}

int jpeg_make_buf_progressive(p_jpeg_dec_rec p_rec)
{
 /* 当前工作矩阵(Data Unit) */
 SHORT    *p_curr_du;
 /* 各组件缓冲区,需释放 */
 BYTE*    p_com_bufs[5] = { NULL, NULL, NULL, NULL, NULL };
 /* 每段每组件扫描完后地址偏移量,需释放 */
 int*    p_com_buf_incs[5] = { NULL, NULL, NULL, NULL, NULL };
 /* 指向p_com_bufs的当前地址(当p_com_bufs被重新分配时,应当重新计算!!!) */
 BYTE*    p_com_ptrs[5] = { NULL, NULL, NULL, NULL, NULL };
 /* 组件宽度(像素) */
 WORD    w_com_widths[5] = { 0, 0, 0, 0, 0 };
 /* 组件宽度(像素),若w_scanlines为0,则此值持续变动 */
 WORD    w_com_heights[5] = { 0, 0, 0, 0, 0 };
 /* 每组件长宽方向上的数量 */
 BYTE    n_com_counts[5] = { 0, 0, 0, 0, 0 };
 /* 每组件每像素行扫描完后地址增加字节数 */
 DWORD    dw_com_line_incs[5] = { 0, 0, 0, 0, 0 };
 /* 每组件每扫描行扫描完后地址增加字节数 */
 DWORD    dw_com_scanline_incs[5] = { 0, 0, 0, 0, 0 };
 /* 段数,扫描行数(为0表示在扫描过程中指定),剩余行数 */
 WORD    w_segments, w_scanlines, w_leftlines;
 /* 当前量化表 */
 p_jpeg_quality_table p_quality_table;
 /* 当前量化表数值 */
 DWORD    *pw_quality_values;
 DWORD    dw_offset, dw_old_offset;
 DWORD    n_du_count;
 BYTE    i, j, m, n, cnt;
 BYTE    *p;
 SHORT    *p_i;
 WORD    k;

 /* 渐近方式不支持动态高度 */
 if ( p_rec->n_height == 0 ) return 0;

 w_segments = (WORD)( (p_rec->n_width + p_rec->n_horz_sample_coes_max * 8 - 1) / (p_rec->n_horz_sample_coes_max * 8) );
 w_scanlines = (WORD)( (p_rec->n_height + p_rec->n_vert_sample_coes_max * 8 - 1) / (p_rec->n_vert_sample_coes_max * 8) );
 w_leftlines = w_scanlines;

 /* 预分配各组件扫描临时区域 */
 for ( i = 0; i < p_rec->n_components; i++ ) {
  n_com_counts[i] = p_rec->n_horz_sample_coes[i] * p_rec->n_vert_sample_coes[i];
  w_com_widths[i] = (WORD)(w_segments * p_rec->n_horz_sample_coes[i] * 8);
  dw_com_line_incs[i] = w_com_widths[i] - 8;
  dw_com_scanline_incs[i] = (DWORD)w_com_widths[i] * p_rec->n_vert_sample_coes[i] * 8 - w_com_widths[i];  

  p_com_buf_incs[i] = (int*)malloc( w_com_widths[i] * sizeof(int*) );
  w_com_heights[i] = (WORD)(w_scanlines * p_rec->n_vert_sample_coes[i] * 8);
  p_com_bufs[i] = (BYTE*)malloc( (DWORD)w_com_widths[i] * (DWORD)w_com_heights[i] );

  if ( p_com_buf_incs[i] != NULL ) {
   dw_old_offset = dw_offset = 0;
   for ( j = 0, n = 0; n < p_rec->n_vert_sample_coes[i]; ++n ) {
    for ( m = 0; m < p_rec->n_vert_sample_coes[i]; ++m, ++j ) {
     dw_offset = (DWORD)n * 8 * w_com_widths[i] + m * 8;
     if ( j > 0 ) p_com_buf_incs[i][j - 1] = dw_offset - dw_old_offset;
     dw_old_offset = dw_offset;
    }
   }
   dw_offset = (DWORD)p_rec->n_horz_sample_coes[i] * 8;
   p_com_buf_incs[i][j - 1] = dw_offset - dw_old_offset;
  }
  p_com_ptrs[i] = p_com_bufs[i];
 }

 p_curr_du = p_rec->p_dus;
 n_du_count = p_rec->n_du_count;
 for ( w_leftlines = w_scanlines; w_leftlines > 0; --w_leftlines ) {
  /* 段扫描 */
  for ( k = 0; k < w_segments; ++k ) {
   /* 交错扫描方式:组件1,组件2,组件3... */
   for ( i = 0; i < p_rec->n_components; ++i ) {
    for ( cnt = 0; cnt < n_com_counts[i]; ++cnt ) {
     /* 当前量化表 */
     p_quality_table = &p_rec->quality_tables[p_rec->n_quality_table_indexes[i]];
     if ( !p_quality_table->process_in_idct ) {
      /* 当前量化表值 */
      pw_quality_values = p_quality_table->values;
      /* 反量化 */
      for ( j = 0; j < 64; ++j ) {
       p_curr_du[j] *= (*pw_quality_values);
       ++pw_quality_values;
      }
     }
     /* IDCT */
     jpeg_idct( p_quality_table, p_curr_du );
     p_curr_du += 64;
    }
   }
  }
 }
 p_curr_du = p_rec->p_dus;
 for ( w_leftlines = w_scanlines; w_leftlines > 0; --w_leftlines ) {
  /* 段扫描 */
  for ( k = 0; k < w_segments; ++k ) {
   /* 交错扫描方式:组件1,组件2,组件3... */
   for ( i = 0; i < p_rec->n_components; ++i ) {
    for ( cnt = 0; cnt < n_com_counts[i]; ++cnt ) {
     p = p_com_ptrs[i];
     p_i = p_curr_du;
     for ( n = 0; n < 8; ++n ) {
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      *p++ = (BYTE)*p_i++;
      p += dw_com_line_incs[i];
     }
     p_com_ptrs[i] += p_com_buf_incs[i][cnt];
     p_curr_du += 64;
    } /* cnt */
   } /* i */
  } /* k */
  /* 下一行 */
  for ( i = 0; i < p_rec->n_components; ++i ) p_com_ptrs[i] += dw_com_scanline_incs[i];
 }

 free(p_rec->p_dus);
 p_rec->p_dus = NULL;

 /* 生成位图 */
 if ( p_rec->n_components == 3 ) jpeg_make_rgb_buffer(p_rec, p_com_bufs, w_com_widths);
 else if ( p_rec->n_components == 1 ) jpeg_make_gray_buffer(p_rec, p_com_bufs, w_com_widths);
 //else if ( p_rec->n_components == 4 )
 for ( i = 0; i < p_rec->n_components; ++i )
 {
  if (p_com_bufs[i] != NULL) free(p_com_bufs[i]);
  if (p_com_buf_incs[i] != NULL) free(p_com_buf_incs[i]);
 }
 return 1;
}


/*
 * 解码SOS(Start Of Scan)标记,并解码帧
 *  成功返回非0
 */
int jpeg_decode_SOS(p_jpeg_dec_rec p_rec)
{
 BYTE i, j, b, index, id;
 BYTE component_indexes[4];
 BYTE n_curr_scan_components;
 
 NextByte(p_rec);
 jpeg_next_word(p_rec);

 n_curr_scan_components = jpeg_next_byte(p_rec);
 if ( n_curr_scan_components <= 0 || n_curr_scan_components > 4 ) return 0;

 /* 0xFF means this component does not appear in the scan */
 component_indexes[0] = component_indexes[1] = component_indexes[2] = component_indexes[3] = 0xFF;

 for ( i = 0; i < n_curr_scan_components; ++i ) {
  /* component id */
  id = jpeg_next_byte(p_rec);
  for ( j = 0; j < 4; ++j ) {
   if ( p_rec->i_component_ids[j] == id ) {
    component_indexes[i] = j;
    break;
   }
  }
  if ( j == 4 ) return 0;
  index = j;
  b = jpeg_next_byte(p_rec);
  p_rec->n_huff_tables_indexes[0][index] = b >> 4;
  p_rec->n_huff_tables_indexes[1][index] = b & 0xf;
 }

 p_rec->n_curr_scan_ss = NextByte(p_rec);
 p_rec->n_curr_scan_se = NextByte(p_rec);
 b = NextByte(p_rec);
 p_rec->n_curr_scan_ah = b >> 4;
 p_rec->n_curr_scan_al = b & 0xf;

 if ( p_rec->i_progressive ) jpeg_decode_scanlines_progressive(p_rec, component_indexes, n_curr_scan_components);
 else jpeg_decode_scanlines(p_rec);

 return 1;
}

/*
 *  处理下一个块。返回值
 * JPEG_FAIL_UNEXPECTED_BYTE  unexpected byte (0ffh expected)
 * JPEG_FAIL_UNKNOWN_BLOCK_TYPE unknown block type 未知类型块
 * JPEG_FAIL_DECODE_ERROR   已知块,但解码失败
 * JPEG_SUCCESS_NEXTBLOCK   成功,等待下一个块的解码
 * JPEG_SUCCESS_LASTBLOCK   成功,且已是最后一块
 * JPEG_SUCCESS_IGNORED   unsupported block type 不支持的块,已忽略
 * 在处理每个块时,将先过滤掉前面的0xff。因此在各明确的块处理段将无0xff
 */
int jpeg_decode_next_block(p_jpeg_dec_rec p_rec)
{
 BYTE b, curb;
 b = NextByte(p_rec);
 if ( b != 0xff )
 {
  return JPEG_FAIL_UNEXPECTED_BYTE;
 }
 curb = CurByte(p_rec);
 switch( curb ) {
  case 0xD8:  /* SOI */
   jpeg_skip_next_block(p_rec);
   break;
  case 0xD9:  /* EOI */
   jpeg_skip_next_block(p_rec);
   if ( p_rec->i_progressive ) {
    jpeg_make_buf_progressive(p_rec);
   }
   return JPEG_SUCCESS_LASTBLOCK;
  case 0xC0:  /* SOF0 */
  case 0xC2:
   if ( curb == 0xC2 ) p_rec->i_progressive = 1;
   if ( !jpeg_decode_SOF0(p_rec)) return JPEG_FAIL_DECODE_ERROR;
   break;
  case 0xDD:  /* DRI */
   if ( !jpeg_decode_DRI(p_rec) ) return JPEG_FAIL_DECODE_ERROR;
   break;
  case 0xDB:  /* DQT */
   if ( !jpeg_decode_DQT(p_rec) ) return JPEG_FAIL_DECODE_ERROR;
   break;
  case 0xC4:  /* DHT */
   if ( !jpeg_decode_DHT(p_rec) ) return JPEG_FAIL_DECODE_ERROR;
   break;
  case 0xE0:  /* APP0-APPF */
  case 0xE1:
  case 0xE2:
  case 0xE3:
  case 0xE4:
  case 0xE5:
  case 0xE6:
  case 0xE7:
  case 0xE8:
  case 0xE9:
  case 0xEA:
  case 0xEB:
  case 0xEC:
  case 0xED:
  case 0xEE:
  case 0xEF:
  case 0xFE:  /* COM */
   jpeg_skip_next_block(p_rec);
   break;
  case 0xDA:  /* SOS */
   if ( !jpeg_decode_SOS(p_rec) ) return JPEG_FAIL_DECODE_ERROR;
   break;
  case 0xFF:  /* 段之间无论有多少 $ff 都是合法的, 必须被忽略掉 */
   break;
  default:
   jpeg_skip_next_block(p_rec);
   return JPEG_SUCCESS_IGNORED;
 }
 return JPEG_SUCCESS_NEXTBLOCK;
}


http://www.ppmy.cn/news/245315.html

相关文章

苏泊尔H1快报:增收不增利,小家电也焦虑

随着国民经济的快速发展&#xff0c;我国消费逐渐升级&#xff0c;消费者在满足了大家电的传统需求后&#xff0c;对小家电的消费需求也在逐渐上涨。今年苏泊尔的股价却出现了大幅下降&#xff0c;从今年上半年最高点81.47元跌至7月26日的收盘价52.75元&#xff0c;另外从5月27…

gitlab基本操作

1.gitlab 基本操作 git branch // 查看分支 git branch dev //新建dev 分支 git checkout dev //切换到dev 分支修改 **** git status // 查看哪些文件被修改 git add . //修改了文件需要提交添加上去&#xff08;注意 . 点号&#xff09; git commit -m “update”…

没素材也可以剪辑,根据画面描述搜索影片素材!

随着社交媒体的普及&#xff0c;越来越多的人开始喜欢用短视频分享自己的生活。但是&#xff0c;在剪辑过程中&#xff0c;素材的质量和多样性是很重要的。如果你缺乏素材&#xff0c;可以考虑根据画面描述去搜索一些适合的影片素材。 首先&#xff0c;你需要确定自己需要什么…

TCP/IP 教程02--- 寻址

TCP/IP 寻址 TCP/IP 使用 32 个比特或者 4 组 0 到 255 之间的数字来为计算机编址。 IP地址 每个计算机必须有一个 IP 地址才能够连入因特网。 每个 IP 包必须有一个地址才能够发送到另一台计算机。 在本教程下一节&#xff0c;您会学习到更多关于 IP 地址和 IP 名称的知识…

SSM 框架

ssm框架是spring MVC &#xff0c;spring和mybatis框架的整合&#xff0c;是标准的MVC模式&#xff0c;将整个系统划分为表现层&#xff0c;controller层&#xff0c;service层&#xff0c;DAO层四层。ssm框架是目前比较主流的Java EE企业级框架&#xff0c;适用于搭建各种大型…

性能测试指标

一、性能测试指标 性能测试是通过测试工具模拟多种正常、峰值及异常负载条件来对系统的各项性能指标进行测试; 目的:验证软件系统是否能够达到用户提出的性能指标,发现系统中存在的性能瓶颈并加以优化。 性能指标分为两个方面: 系统指标(与用户场景和需求相关指标) …

漫威蜘蛛侠Mac动态壁纸

蜘蛛侠是美国漫威漫画旗下的一个超级英雄&#xff0c;彼得帕克因为被一只受过放射性 感染的蜘蛛咬伤&#xff0c;所以拥有了超能力&#xff0c;被称之为蜘蛛侠&#xff01;本次未来软件园为您带来漫威蜘蛛侠Mac动态壁纸&#xff0c;这是蜘蛛侠动态壁纸适用于10.14及更高系统。 …

大黄蜂视频加密软件_大黄蜂

大黄蜂视频加密软件 The small person found an enormous wasp in her bedroom today. I don’t like wasps much, I especially don’t like wasps that are twice the size of your average, irritating with a mission to sit on your icecream, garden wasp. Drew was desp…