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

本文档详细介绍了苏泊尔耗的JPEG解码器的实现,包括解码器的数据结构、函数定义以及处理不同块的过程。解码器支持普通和渐进两种解码方式,涉及哈夫曼表、质量表等核心概念。
摘要由CSDN通过智能技术生成

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

头文件

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);
  /* 分量采样率 */

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值