📄 jpege_encode.c
字号:
//////////////////////////////////////////////////////////////////////////////////////////////////////// jpege_encode.c (JPEG Encoder Functions 'C' File)//// Notice: COPYRIGHT (C) STREAM PROCESSORS, INC. 2005-2007// THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE SPI// END-USER LICENSE AGREEMENT (EULA). THE PROGRAM MAY ONLY// BE USED IN A MANNER EXPLICITLY SPECIFIED IN THE EULA,// WHICH INCLUDES LIMITATIONS ON COPYING, MODIFYING,// REDISTRIBUTION AND WARANTIES. UNAUTHORIZED USE OF THIS// PROGRAM IS STRICTLY PROHIBITED. YOU MAY OBTAIN A COPY OF// THE EULA FROM WWW.STREAMPROCESSORS.COM. // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #includes ////////////////////////////////////////////////////////////////////////////////#include <stdio.h>#include "spi_common.h"#include "jpege_context.h"#include "jpege_tables.h"#include "write_bits.h"////////////////////////////////////////////////////////////////////////////////// Constants////////////////////////////////////////////////////////////////////////////////#define MAX_COEF_BITS 10#ifdef OUTPUT_DEBUG_TO_FILE FILE *debug_out;#endifvoid huffman_encode_one_block_ref( BIT_BUFFER *p_bit_buffer, short *p_block, short last_dc_val, DERIVED_HUFF_TBL *p_dc_tbl, DERIVED_HUFF_TBL *p_ac_tbl, int insert_zero_byte){ short dc_diff; short temp; int num_bits; short run; short level; int k, index; short zz_block[BLOCK_SIZE]; // Do the zigzag first. This will match kernel code better for (k = 0; k < BLOCK_SIZE; k++) { zz_block[k] = p_block[zigzag[k]]; } // Encode the DC coefficient difference per section F.1.2.1 dc_diff = temp = zz_block[0] - last_dc_val; if (dc_diff < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want dc_diff = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ dc_diff--; } // Find the number of bits needed for the magnitude of the coefficient num_bits = 0; while (temp) { num_bits++; temp >>= 1; } // Check for out-of-range coefficient values. // Since we're encoding a difference, the range limit is twice as much. if (num_bits > MAX_COEF_BITS + 1) { spi_printf ("Magnitute of dct dc coefficient exceed 11 bits\n"); exit (1); } write_bits_ref (p_bit_buffer, p_dc_tbl->code_word[num_bits], p_dc_tbl->code_length[num_bits], insert_zero_byte); // Emit that number of bits of the value, if positive, // or the complement of its magnitude, if negative. write_bits_ref (p_bit_buffer, (unsigned short) dc_diff, num_bits, insert_zero_byte); // Encode the AC coefficients per section F.1.2.2 run = 0; // r = run length of zeros for (k = 1; k < BLOCK_SIZE; k++) { if ((temp = zz_block[k]) == 0) { run++; } else { // if run length > 15, must emit special run-length-16 codes (0xF0) */ while (run > 15) { write_bits_ref (p_bit_buffer, p_ac_tbl->code_word[0xF0], p_ac_tbl->code_length[0xF0], insert_zero_byte); run -= 16; } level = temp; if (level < 0) { temp = -temp; // temp is abs value of input // This code assumes we are on a two's complement machine level--; } // Find the number of bits needed for the magnitude of the coefficient num_bits = 1; // there must be at least one 1 bit while (temp >>= 1) { num_bits++; } // Check for out-of-range coefficient values if (num_bits > MAX_COEF_BITS) { spi_printf ("ac coefficient out of range\n"); exit (1); } // Emit Huffman symbol for run length / number of bits index = (run << 4) + num_bits; write_bits_ref (p_bit_buffer, p_ac_tbl->code_word[index], p_ac_tbl->code_length[index], insert_zero_byte); // Emit that number of bits of the value, if positive, // or the complement of its magnitude, if negative. write_bits_ref (p_bit_buffer, (unsigned short) level, num_bits, insert_zero_byte); run = 0; } } // If the last coef(s) were zero, emit an end-of-block code */ if (run > 0) { write_bits_ref (p_bit_buffer, p_ac_tbl->code_word[0], p_ac_tbl->code_length[0], insert_zero_byte); }}void encode_block ( char *p_in_data, unsigned short *p_quant_divisor, DERIVED_HUFF_TBL *p_dc_huff_tbl, DERIVED_HUFF_TBL *p_ac_huff_tbl, short *last_dc, BIT_BUFFER *p_buffer ){ short coefs[64]; // Forward dct and quantization fdct_and_quantize_aan_ref (p_in_data, coefs, p_quant_divisor); #ifdef OUTPUT_DEBUG_TO_FILE { int i; fprintf (debug_out, "-------------------\n"); for (i = 0; i < 64; i++) { fprintf (debug_out, "%d: %x\n", i, coefs[i]); } } #endif huffman_encode_one_block_ref (p_buffer, coefs, *last_dc, p_dc_huff_tbl, p_ac_huff_tbl, false); *last_dc = coefs[0];}void compose_block (char *p_dst_block, unsigned char *p_src_block, int src_stride){ int i, j; unsigned char *p_src; for (j = 0; j < BLOCK_HEIGHT; j++) { p_src = p_src_block + j * src_stride; for (i = 0; i < BLOCK_WIDTH; i++) { *p_dst_block++ = *p_src - 128; p_src++; } }}void encode_one_component_ref (JPEGE_CONTEXT *p_jenc, int component_index){ int i, j; short dc; unsigned char *p_input; unsigned char *p_src; JPEGE_COMPONENT_INFO *p_comp; char block[BLOCK_SIZE]; BIT_BUFFER *p_bit_buffer; p_input = p_jenc->p_input_buffer[component_index]; p_comp = &p_jenc->comp_info[component_index]; p_bit_buffer = p_comp->p_bit_buffers; for (i = 0; i < p_comp->width_in_blocks * p_comp->height_in_blocks; i++) { reset_bit_buffer (p_bit_buffer++); } p_bit_buffer = p_comp->p_bit_buffers; dc = 0; #ifdef OUTPUT_DEBUG_TO_FILE debug_out = fopen ("dbg_out.txt", "w"); #endif for (j = 0; j < p_comp->height_in_blocks; j++) { for (i = 0; i < p_comp->width_in_blocks; i++) { p_src = p_input + j * p_comp->scaled_width * BLOCK_HEIGHT + i * BLOCK_WIDTH; compose_block ( block, p_src, p_comp->scaled_width ); #ifdef OUTPUT_DEBUG_TO_FILE fprintf (debug_out, "--------- block # %d ----------\n", j * p_comp->width_in_blocks + i); #endif encode_block ( block, p_jenc->quant_tbl[p_comp->quant_tbl_num].aan_divisor, &p_comp->d_dc_huff_tbl, &p_comp->d_ac_huff_tbl, &dc, p_bit_buffer ); p_bit_buffer++; } dc = 0; } #ifdef OUTPUT_DEBUG_TO_FILE fclose(debug_out); #endif}void pack_one_bit_buffer (BIT_BUFFER *p_output_buffer, BIT_BUFFER *p_bit_buffer){ int n; for (n = 0; n < (int)p_bit_buffer->byte_pos; n++) { write_bits_ref (p_output_buffer, p_bit_buffer->p_buffer[n], 8, true); } write_bits_ref (p_output_buffer, p_bit_buffer->cur_byte >> (8 - p_bit_buffer->bit_pos), p_bit_buffer->bit_pos, true);}void pack_bits (JPEGE_CONTEXT *p_jenc){ int i, k, blocks_per_row, marker, marker_count; BIT_BUFFER *p_dest_buffer; JPEGE_COMPONENT_INFO *p_cur_comp; p_dest_buffer = &p_jenc->output_buffer;#if defined(DEBUG1) spi_printf("\n Before pack_bits. \n");#endif for (k = 0; k < p_jenc->num_components; k++) { write_single_component_scan_header (p_jenc, k); p_cur_comp = &p_jenc->comp_info[k]; blocks_per_row = p_cur_comp->scaled_width / BLOCK_WIDTH; marker_count = 0; for (i = 0; i < p_cur_comp->num_blocks; i++) { if ((i != 0) && ((i % blocks_per_row) == 0)) { write_fill_bits_at_reset(p_jenc); word_align_byte_pos(p_dest_buffer); // Add the marker for next interval marker = 0xFFD0 | marker_count; marker_count = (marker_count + 1) & 0x7; write_bytes (p_dest_buffer, 0xFFFF, 2); // This is inserted to make it one word & thus keep the byte_pos word aligned write_bytes (p_dest_buffer, marker, 2); } pack_one_bit_buffer (p_dest_buffer, &p_cur_comp->p_bit_buffers[i]); } write_fill_bits_at_reset (p_jenc); word_align_byte_pos(p_dest_buffer);#if defined(DEBUG1) spi_printf("\n After one component : %d \n", k);#endif }#if defined(DEBUG1) spi_printf("\n After pack_bits \n");#endif #ifdef OUTPUT_DEBUG_TO_FILE { int n; BIT_BUFFER *p_bit_buffer; #ifdef USE_JPEG_KERNELS debug_out = fopen ("bit_buf_out_k.txt", "w"); #else debug_out = fopen ("bit_buf_out_r.txt", "w"); #endif for (k = 0; k < p_jenc->num_components; k++) { fprintf (debug_out, "xxxxx Componet # %d xxxxxxxx\n", k); p_cur_comp = &p_jenc->comp_info[k]; for (i = 0; i < (int)p_cur_comp->num_blocks; i++) { fprintf (debug_out, "--------- block # %d --------\n", i); p_bit_buffer = &p_cur_comp->p_bit_buffers[i]; for (n = 0; n < (int)p_bit_buffer->byte_pos; n++) { fprintf (debug_out, "%d: %x\n", n, p_bit_buffer->p_buffer[n]); } fprintf (debug_out, "%d: %x\n", n, p_bit_buffer->cur_byte); } } fclose (debug_out); } #endif}void encode_frame(JPEGE_CONTEXT *p_jenc){ int k;#if (defined(PROFILE_KERNELS) && (defined(SPI_TARGET_DEVICE))) spi_safe_mode(2);#endif#if (defined(PROFILE_COMPONENTS) && (defined(SPI_TARGET_DEVICE))) SPI_PERF_T enc_component_timer ; SPI_PERF_T pack_rows_timer ;#endif // This is a two stage process. // 1. Encode each component // 2. Pack bits for (k = 0; k < p_jenc->num_components; k++) {#if (defined(PROFILE_COMPONENTS) && (defined(SPI_TARGET_DEVICE))) spi_perf_init (&enc_component_timer , "enc_component_timer") ; spi_perf_start (&enc_component_timer) ;#endif #ifndef USE_JPEG_KERNELS encode_one_component_ref (p_jenc, k); #else encode_one_component (p_jenc, k); #endif#if (defined(PROFILE_COMPONENTS) && (defined(SPI_TARGET_DEVICE))) spi_perf_stop (&enc_component_timer) ; spi_perf_print (&enc_component_timer, 1) ;#endif#if (defined(PROFILE_KERNELS) && (defined(SPI_TARGET_DEVICE))) spi_runtime_kernel_dpu_perf_print(1);#endif }#if (defined(PROFILE_COMPONENTS) && (defined(SPI_TARGET_DEVICE))) spi_perf_init (&pack_rows_timer , "pack_rows_timer") ; spi_perf_start (&pack_rows_timer) ;#endif#if defined (REF) pack_bits (p_jenc);#else pack_bits_sc(p_jenc);#endif#if (defined(PROFILE_COMPONENTS) && (defined(SPI_TARGET_DEVICE))) spi_perf_stop (&pack_rows_timer) ; spi_perf_print (&pack_rows_timer, 1) ;#endif}void jpege_encode (JPEGE_CONTEXT *p_jenc){ write_soi (p_jenc); // FFD8 - SOI write_JFIF_header(p_jenc); // APP0 write_quant_tables(p_jenc); // DQT write_frame_header(p_jenc); // SOF write_huffman_tables(p_jenc); // DHT encode_frame (p_jenc);#if defined(DEBUG1) spi_printf("\n After encode_frame. \n");#endif write_fill_bits (p_jenc);#if defined(DEBUG1) spi_printf("\n After final fill bits. \n");#endif write_eoi (p_jenc);#if defined(DEBUG1) spi_printf("\n After writing end of image. \n");#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -