📄 jpeg.c
字号:
#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <liboil/liboil.h>#include <liboil/liboil-stdint.h>#include <cogcompat.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include "jpeg.h"extern uint8_t jpeg_standard_tables[];extern int jpeg_standard_tables_size;void jpeg_decoder_define_huffman_tables (JpegDecoder * dec);void jpeg_decoder_define_arithmetic_conditioning (JpegDecoder *dec);void jpeg_decoder_define_quantization_tables (JpegDecoder *dec);void jpeg_decoder_define_restart_interval (JpegDecoder *dec);void jpeg_decoder_start_of_frame (JpegDecoder * dec, int marker);void jpeg_decoder_start_of_scan (JpegDecoder * dec);/* misc helper function declarations */static void jpeg_load_standard_huffman_tables (JpegDecoder * dec);static void jpeg_decoder_verify_header (JpegDecoder *dec);static void jpeg_decoder_init_decoder (JpegDecoder *dec);voidjpeg_decoder_error(JpegDecoder *dec, const char *fmt, ...){ va_list varargs; if (dec->error) return; va_start (varargs, fmt);#ifdef HAVE_VASPRINTF vasprintf(&dec->error_message, fmt, varargs);#else dec->error_message = malloc(250); vsnprintf(dec->error_message, 250 - 1, fmt, varargs); dec->error_message[250 - 1] = 0;#endif va_end (varargs); dec->error = TRUE;}#define jpeg_decoder_error(dec, ...) { \ COG_ERROR("decoder error: "__VA_ARGS__); \ jpeg_decoder_error (dec, __VA_ARGS__); \}static voidjpeg_decoder_verify_header (JpegDecoder *dec){ int max_quant_table = 0; int i; if (dec->sof_type != JPEG_MARKER_SOF_0) { COG_ERROR("only handle baseline DCT"); dec->error = TRUE; } if (dec->width < 1) { COG_ERROR("height can't be 0"); dec->error = TRUE; } switch (dec->sof_type) { case JPEG_MARKER_SOF_0: /* baseline DCT */ max_quant_table = 3; if (dec->depth != 8) { COG_ERROR("depth must be 8 (%d)", dec->depth); dec->error = TRUE; } break; case JPEG_MARKER_SOF_1: /* extended DCT */ max_quant_table = 3; if (dec->depth != 8 && dec->depth != 12) { COG_ERROR("depth must be 8 or 12 (%d)", dec->depth); dec->error = TRUE; } break; case JPEG_MARKER_SOF_2: /* progressive DCT */ max_quant_table = 3; if (dec->depth != 8 && dec->depth != 12) { COG_ERROR("depth must be 8 or 12 (%d)", dec->depth); dec->error = TRUE; } break; case JPEG_MARKER_SOF_3: /* lossless DCT */ max_quant_table = 0; if (dec->depth < 2 || dec->depth > 16) { COG_ERROR("depth must be between 2 and 16 (%d)", dec->depth); dec->error = TRUE; } break; default: break; } if (dec->n_components < 0 || dec->n_components > 255) { COG_ERROR("n_components must be in the range 0-255 (%d)", dec->n_components); dec->error = TRUE; } if (dec->sof_type == JPEG_MARKER_SOF_2 && dec->n_components > 4) { COG_ERROR("n_components must be <= 4 for progressive DCT (%d)", dec->n_components); dec->error = TRUE; } for (i = 0; i < dec->n_components; i++) { if (dec->components[i].id < 0 || dec->components[i].id > 255) { COG_ERROR("component ID out of range"); dec->error = TRUE; break; } if (dec->components[i].h_sample < 1 || dec->components[i].h_sample > 4 || dec->components[i].v_sample < 1 || dec->components[i].v_sample > 4) { COG_ERROR("sample factor(s) for component %d out of range %d %d", i, dec->components[i].h_sample, dec->components[i].v_sample); dec->error = TRUE; break; } if (dec->components[i].quant_table < 0 || dec->components[i].quant_table > max_quant_table) { COG_ERROR("quant table for component %d out of range (%d)", i, dec->components[i].quant_table); dec->error = TRUE; break; } }}static voidjpeg_decoder_init_decoder (JpegDecoder *dec){ int max_h_sample = 0; int max_v_sample = 0; int i; /* decoder limitations */ if (dec->n_components != 3) { jpeg_decoder_error(dec, "wrong number of components %d", dec->n_components); return; } if (dec->sof_type != JPEG_MARKER_SOF_0) { jpeg_decoder_error(dec, "only handle baseline DCT"); return; } for (i=0; i < dec->n_components; i++) { max_h_sample = MAX (max_h_sample, dec->components[i].h_sample); max_v_sample = MAX (max_v_sample, dec->components[i].v_sample); } dec->width_blocks = (dec->width + 8 * max_h_sample - 1) / (8 * max_h_sample); dec->height_blocks = (dec->height + 8 * max_v_sample - 1) / (8 * max_v_sample); for (i = 0; i < dec->n_components; i++) { int rowstride; int image_size; dec->components[i].h_subsample = max_h_sample / dec->components[i].h_sample; dec->components[i].v_subsample = max_v_sample / dec->components[i].v_sample; rowstride = dec->width_blocks * 8 * max_h_sample / dec->components[i].h_subsample; image_size = rowstride * (dec->height_blocks * 8 * max_v_sample / dec->components[i].v_subsample); dec->components[i].rowstride = rowstride; dec->components[i].image = malloc (image_size); }}#if 0static char *sprintbits (char *str, unsigned int bits, int n){ int i; int bit = 1 << (n - 1); for (i = 0; i < n; i++) { str[i] = (bits & bit) ? '1' : '0'; bit >>= 1; } str[i] = 0; return str;}static voidgenerate_code_table (int *huffsize){ int code; int i; int j; int k; char str[33]; //int l; code = 0; k = 0; for (i = 0; i < 16; i++) { for (j = 0; j < huffsize[i]; j++) { COG_DEBUG ("huffcode[%d] = %s", k, sprintbits (str, code >> (15 - i), i + 1)); code++; k++; } code <<= 1; }}#endifstatic inthuffman_table_init_jpeg (JpegDecoder *decoder, HuffmanTable *table, JpegBits * bits){ int n_symbols; int huffsize[16]; int i, j, k; unsigned int symbol; int n = 0; huffman_table_init (table); /* huffsize[i] is the number of symbols that have length * (i+1) bits. Maximum bit length is 16 bits, so there are * 16 entries. */ n_symbols = 0; for (i = 0; i < 16; i++) { huffsize[i] = jpeg_bits_get_u8 (bits); n++; n_symbols += huffsize[i]; } /* Build up the symbol table. The first symbol is all 0's, with * the number of bits determined by the first non-zero entry in * huffsize[]. Subsequent symbols with the same bit length are * incremented by 1. Increasing the bit length shifts the * symbol 1 bit to the left. */ symbol = 0; k = 0; for (i = 0; i < 16; i++) { for (j = 0; j < huffsize[i]; j++) { huffman_table_add (table, symbol, i + 1, jpeg_bits_get_u8 (bits)); n++; symbol++; k++; } /* This checks that our symbol is actually less than the * number of bits we think it is. This is only triggered * for bad huffsize[] arrays. */ if (symbol >= (1U << (i + 1))) { jpeg_decoder_error (decoder, "bad huffsize[] array"); return -1; } symbol <<= 1; } huffman_table_dump (table); return n;}static intjpeg_decoder_find_component_by_id (JpegDecoder * dec, int id){ int i; for (i = 0; i < dec->n_components; i++) { if (dec->components[i].id == id) return i; } COG_DEBUG ("undefined component id %d", id); return 0;}intjpeg_decoder_application0 (JpegDecoder * dec, JpegBits * bits){ int length; COG_DEBUG ("app0"); length = get_be_u16 (bits); COG_DEBUG ("length=%d", length); if (memcmp (bits->ptr, "JFIF", 4) == 0 && bits->ptr[4] == 0) { int version; int units; int x_density; int y_density; int x_thumbnail; int y_thumbnail; COG_DEBUG ("JFIF"); bits->ptr += 5; version = get_be_u16 (bits); units = get_u8 (bits); x_density = get_be_u16 (bits); y_density = get_be_u16 (bits); x_thumbnail = get_u8 (bits); y_thumbnail = get_u8 (bits); COG_DEBUG ("version = %04x", version); COG_DEBUG ("units = %d", units); COG_DEBUG ("x_density = %d", x_density); COG_DEBUG ("y_density = %d", y_density); COG_DEBUG ("x_thumbnail = %d", x_thumbnail); COG_DEBUG ("y_thumbnail = %d", y_thumbnail); } if (memcmp (bits->ptr, "JFXX", 4) == 0 && bits->ptr[4] == 0) { COG_DEBUG ("JFIF extension (not handled)"); bits->ptr += length - 2; } return length;}intjpeg_decoder_application_misc (JpegDecoder * dec, JpegBits * bits){ int length; COG_DEBUG ("appX"); length = get_be_u16 (bits); COG_DEBUG ("length=%d", length); COG_DEBUG ("JPEG application tag X ignored"); //dumpbits (bits); bits->ptr += length - 2; return length;}intjpeg_decoder_comment (JpegDecoder * dec, JpegBits * bits){ int length; COG_DEBUG ("comment"); length = get_be_u16 (bits); COG_DEBUG ("length=%d", length); //dumpbits (bits); bits->ptr += length - 2; return length;}intjpeg_decoder_restart_interval (JpegDecoder * dec, JpegBits * bits){ int length; COG_DEBUG ("comment"); length = get_be_u16 (bits); COG_DEBUG ("length=%d", length); dec->restart_interval = get_be_u16 (bits); COG_DEBUG ("restart_interval=%d", dec->restart_interval); return length;}intjpeg_decoder_restart (JpegDecoder * dec, JpegBits * bits){ COG_DEBUG ("restart"); return 0;}voidjpeg_decoder_decode_entropy_segment (JpegDecoder * dec){ JpegBits * bits = &dec->bits; JpegBits b2, *bits2 = &b2; short block[64]; short block2[64]; unsigned char *newptr; int len; int maxlen; int j; int i; int go; int x, y; int n; int ret; len = 0; maxlen = jpeg_bits_available (bits) - 1; j = 0; while (len < maxlen) { if (bits->ptr[len] == 0xff && bits->ptr[len + 1] != 0x00) { break; } len++; } COG_DEBUG ("entropy length = %d", len); /* we allocate extra space, since the getbits() code can * potentially read past the end of the buffer */ newptr = malloc (len + 2); for (i = 0; i < len; i++) { newptr[j] = bits->ptr[i]; j++; if (bits->ptr[i] == 0xff) i++; } bits->ptr += len; bits2->ptr = newptr; bits2->idx = 0; bits2->end = newptr + j; newptr[j] = 0; newptr[j + 1] = 0; dec->dc[0] = dec->dc[1] = dec->dc[2] = dec->dc[3] = 128 * 8; go = 1; x = dec->x; y = dec->y; n = dec->restart_interval; if (n == 0) n = (1<<26); /* max number of blocks */ while (go && n-- > 0) { for (i = 0; i < dec->scan_list_length; i++) { int dc_table_index; int ac_table_index; int quant_index; unsigned char *ptr; int component_index; COG_DEBUG ("%d,%d: component=%d dc_table=%d ac_table=%d", x, y, dec->scan_list[i].component_index, dec->scan_list[i].dc_table, dec->scan_list[i].ac_table); component_index = dec->scan_list[i].component_index; dc_table_index = dec->scan_list[i].dc_table; ac_table_index = dec->scan_list[i].ac_table; quant_index = dec->scan_list[i].quant_table; ret = huffman_table_decode_macroblock (dec, block, &dec->dc_huff_table[dc_table_index], &dec->ac_huff_table[ac_table_index], bits2); if (ret < 0) { COG_DEBUG ("%d,%d: component=%d dc_table=%d ac_table=%d", x, y, dec->scan_list[i].component_index, dec->scan_list[i].dc_table, dec->scan_list[i].ac_table); n = 0; break; } COG_DEBUG ("using quant table %d", quant_index); oil_mult8x8_s16 (block2, block, dec->quant_tables[quant_index].quantizer, sizeof (short) * 8, sizeof(short) * 8, sizeof (short) * 8); dec->dc[component_index] += block2[0]; block2[0] = dec->dc[component_index]; oil_unzigzag8x8_s16 (block, sizeof (short) * 8, block2, sizeof (short) * 8); oil_idct8x8_s16 (block2, sizeof (short) * 8, block, sizeof (short) * 8); oil_trans8x8_s16 (block, sizeof (short) * 8, block2, sizeof (short) * 8); ptr = dec->components[component_index].image + x * dec->components[component_index].h_sample + dec->scan_list[i].offset + dec->components[component_index].rowstride * y * dec->components[component_index].v_sample; oil_clipconv8x8_u8_s16 (ptr, dec->components[component_index].rowstride, block, sizeof (short) * 8); } x += 8; if (x * dec->scan_h_subsample >= dec->width) { x = 0; y += 8; } if (y * dec->scan_v_subsample >= dec->height) { go = 0; } } dec->x = x; dec->y = y; free (newptr);}JpegDecoder *jpeg_decoder_new (void){ JpegDecoder *dec; oil_init (); dec = malloc (sizeof(JpegDecoder)); memset (dec, 0, sizeof(JpegDecoder)); jpeg_load_standard_huffman_tables (dec); return dec;}voidjpeg_decoder_free (JpegDecoder * dec){ int i; for (i = 0; i < JPEG_LIMIT_COMPONENTS; i++) { if (dec->components[i].image) free (dec->components[i].image); } if (dec->data) free (dec->data); free (dec);}static intjpeg_decoder_get_marker (JpegDecoder *dec, int *marker){ int a,b; JpegBits *bits = &dec->bits; if (jpeg_bits_available(bits) < 2) { return FALSE; } a = jpeg_bits_get_u8(bits);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -