📄 jp3.txt
字号:
新一篇: 苏泊尔耗的JPEG解码器[四] | 旧一篇: 苏泊尔耗的JPEG解码器[二]
主控单元。包含普通和渐近两种方式的解码。
头文件
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 = p_rec->n_reset_size; /* *NOT* 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -