📄 jp3.txt
字号:
/* * 生成解码用哈夫曼表 */ 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];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -