主控单元。包含普通和渐近两种方式的解码。
头文件
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);
/* 分量采样率 */