/** Documented at declaration */ int gpujpeg_table_huffman_decoder_init(struct gpujpeg_table_huffman_decoder* table, struct gpujpeg_table_huffman_decoder* d_table, enum gpujpeg_component_type comp_type, enum gpujpeg_huffman_type huff_type) { assert(comp_type == GPUJPEG_COMPONENT_LUMINANCE || comp_type == GPUJPEG_COMPONENT_CHROMINANCE); assert(huff_type == GPUJPEG_HUFFMAN_DC || huff_type == GPUJPEG_HUFFMAN_AC); if ( comp_type == GPUJPEG_COMPONENT_LUMINANCE ) { if ( huff_type == GPUJPEG_HUFFMAN_DC ) { memcpy(table->bits, gpujpeg_table_huffman_y_dc_bits, sizeof(table->bits)); memcpy(table->huffval, gpujpeg_table_huffman_y_dc_value, sizeof(table->huffval)); } else { memcpy(table->bits, gpujpeg_table_huffman_y_ac_bits, sizeof(table->bits)); memcpy(table->huffval, gpujpeg_table_huffman_y_ac_value, sizeof(table->huffval)); } } else if ( comp_type == GPUJPEG_COMPONENT_CHROMINANCE ) { if ( huff_type == GPUJPEG_HUFFMAN_DC ) { memcpy(table->bits, gpujpeg_table_huffman_cbcr_dc_bits, sizeof(table->bits)); memcpy(table->huffval, gpujpeg_table_huffman_cbcr_dc_value, sizeof(table->huffval)); } else { memcpy(table->bits, gpujpeg_table_huffman_cbcr_ac_bits, sizeof(table->bits)); memcpy(table->huffval, gpujpeg_table_huffman_cbcr_ac_value, sizeof(table->huffval)); } } gpujpeg_table_huffman_decoder_compute(table, d_table); return 0; }
/** * Read huffman table definition block from image * * @param decoder * @param image * @return 0 if succeeds, otherwise nonzero */ int gpujpeg_reader_read_dht(struct gpujpeg_decoder* decoder, uint8_t** image) { int length = (int)gpujpeg_reader_read_2byte(*image); length -= 2; int index = gpujpeg_reader_read_byte(*image); struct gpujpeg_table_huffman_decoder* table = NULL; struct gpujpeg_table_huffman_decoder* d_table = NULL; switch(index) { case 0: table = &decoder->table_huffman[GPUJPEG_COMPONENT_LUMINANCE][GPUJPEG_HUFFMAN_DC]; d_table = decoder->d_table_huffman[GPUJPEG_COMPONENT_LUMINANCE][GPUJPEG_HUFFMAN_DC]; break; case 16: table = &decoder->table_huffman[GPUJPEG_COMPONENT_LUMINANCE][GPUJPEG_HUFFMAN_AC]; d_table = decoder->d_table_huffman[GPUJPEG_COMPONENT_LUMINANCE][GPUJPEG_HUFFMAN_AC]; break; case 1: table = &decoder->table_huffman[GPUJPEG_COMPONENT_CHROMINANCE][GPUJPEG_HUFFMAN_DC]; d_table = decoder->d_table_huffman[GPUJPEG_COMPONENT_CHROMINANCE][GPUJPEG_HUFFMAN_DC]; break; case 17: table = &decoder->table_huffman[GPUJPEG_COMPONENT_CHROMINANCE][GPUJPEG_HUFFMAN_AC]; d_table = decoder->d_table_huffman[GPUJPEG_COMPONENT_CHROMINANCE][GPUJPEG_HUFFMAN_AC]; break; default: fprintf(stderr, "[GPUJPEG] [Error] DHT marker index should be 0, 1, 16 or 17 but %d was presented!\n", index); return -1; } length -= 1; // Read in bits[] table->bits[0] = 0; int count = 0; for ( int i = 1; i <= 16; i++ ) { table->bits[i] = gpujpeg_reader_read_byte(*image); count += table->bits[i]; if ( length > 0 ) { length--; } else { fprintf(stderr, "[GPUJPEG] [Error] DHT marker unexpected end when reading bit counts!\n", index); return -1; } } // Read in huffval for ( int i = 0; i < count; i++ ){ table->huffval[i] = gpujpeg_reader_read_byte(*image); if ( length > 0 ) { length--; } else { fprintf(stderr, "[GPUJPEG] [Error] DHT marker unexpected end when reading huffman values!\n", index); return -1; } } // Check length if ( length > 0 ) { fprintf(stderr, "[GPUJPEG] [Warning] DHT marker contains %d more bytes than needed!\n", length); *image += length; } // Compute huffman table for read values gpujpeg_table_huffman_decoder_compute(table, d_table); return 0; }