主控单元。包含普通和渐近两种方式的解码。
头文件
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;
}