📄 jpeg.c
字号:
if (a != 0xff) { jpeg_decoder_error(dec, "expected marker, not 0x%02x", a); return FALSE; } do { b = jpeg_bits_get_u8 (bits); } while (b == 0xff && jpeg_bits_error(bits)); *marker = b; return TRUE;}static voidjpeg_decoder_skip (JpegDecoder *dec){ int length; length = jpeg_bits_get_u16_be (&dec->bits); jpeg_bits_skip (&dec->bits, length - 2);}intjpeg_decoder_decode (JpegDecoder *dec){ JpegBits *bits; int marker; dec->error = FALSE; bits = &dec->bits; /* Note: The spec is ambiguous as to whether fill bytes can come * before the first marker. We'll assume yes. */ if (!jpeg_decoder_get_marker (dec, &marker)) { return FALSE; } if (dec->strict && marker != JPEG_MARKER_SOI) { jpeg_decoder_error(dec, "not a JPEG image"); return FALSE; } /* Interpret markers up to the start of frame */ while (!dec->error) { if (!jpeg_decoder_get_marker (dec, &marker)) { return FALSE; } if (marker == JPEG_MARKER_DEFINE_HUFFMAN_TABLES) { jpeg_decoder_define_huffman_tables (dec); } else if (marker == JPEG_MARKER_DEFINE_ARITHMETIC_CONDITIONING) { jpeg_decoder_define_arithmetic_conditioning (dec); } else if (marker == JPEG_MARKER_DEFINE_QUANTIZATION_TABLES) { jpeg_decoder_define_quantization_tables (dec); } else if (marker == JPEG_MARKER_DEFINE_RESTART_INTERVAL) { jpeg_decoder_define_restart_interval (dec); } else if (JPEG_MARKER_IS_APP(marker)) { /* FIXME decode app segment */ jpeg_decoder_skip (dec); } else if (marker == JPEG_MARKER_COMMENT) { jpeg_decoder_skip (dec); } else if (JPEG_MARKER_IS_START_OF_FRAME(marker)) { break; } else if (marker == JPEG_MARKER_SOI) { if (dec->strict) { jpeg_decoder_error (dec, "unexpected SOI"); return FALSE; } } else if (marker == JPEG_MARKER_EOI) { if (dec->strict) { jpeg_decoder_error (dec, "unexpected EOI"); return FALSE; } } else { jpeg_decoder_error(dec, "unexpected marker 0x%02x", marker); return FALSE; } } if (dec->error) { return FALSE; } jpeg_decoder_start_of_frame(dec, marker); jpeg_decoder_verify_header (dec); if (dec->error) { return FALSE; } jpeg_decoder_init_decoder (dec); if (dec->error) { return FALSE; } /* In this section, we loop over parse units until we reach the end * of the image. */ while (!dec->error) { if (!jpeg_decoder_get_marker (dec, &marker)) { return FALSE; } if (marker == JPEG_MARKER_DEFINE_HUFFMAN_TABLES) { jpeg_decoder_define_huffman_tables (dec); } else if (marker == JPEG_MARKER_DEFINE_ARITHMETIC_CONDITIONING) { jpeg_decoder_define_arithmetic_conditioning (dec); } else if (marker == JPEG_MARKER_DEFINE_QUANTIZATION_TABLES) { jpeg_decoder_define_quantization_tables (dec); } else if (marker == JPEG_MARKER_DEFINE_RESTART_INTERVAL) { jpeg_decoder_define_restart_interval (dec); } else if (JPEG_MARKER_IS_APP(marker)) { jpeg_decoder_skip (dec); } else if (marker == JPEG_MARKER_COMMENT) { jpeg_decoder_skip (dec); } else if (marker == JPEG_MARKER_SOS) { jpeg_decoder_start_of_scan (dec); if (dec->error) { return FALSE; } jpeg_decoder_decode_entropy_segment (dec); } else if (JPEG_MARKER_IS_RESET(marker)) { jpeg_decoder_decode_entropy_segment (dec); } else if (marker == JPEG_MARKER_SOI) { if (dec->strict) { jpeg_decoder_error (dec, "unexpected SOI"); return FALSE; } } else if (marker == JPEG_MARKER_EOI) { if (dec->strict) { jpeg_decoder_error (dec, "unexpected EOI"); return FALSE; } else { break; } } else { jpeg_decoder_error(dec, "unexpected marker 0x%02x", marker); return FALSE; } } if (dec->error) { return FALSE; } return TRUE;}/* handle markers */voidjpeg_decoder_define_huffman_tables (JpegDecoder * dec){ JpegBits *bits = &dec->bits; int length; int tc; int th; int x; HuffmanTable *hufftab; COG_DEBUG ("define huffman tables"); length = jpeg_bits_get_u16_be (bits); if (length < 2) { jpeg_decoder_error(dec, "length too short"); return; } length -= 2; while (length > 0) { x = jpeg_bits_get_u8 (bits); length--; tc = x >> 4; th = x & 0xf; COG_DEBUG ("huff table type %d (%s) idx %d", tc, tc ? "ac" : "dc", th); if (tc > 1 || th > 3) { jpeg_decoder_error(dec, "huffman table type or idx out of range"); return; } if (tc) { hufftab = &dec->ac_huff_table[th]; length -= huffman_table_init_jpeg (dec, hufftab, bits); } else { hufftab = &dec->dc_huff_table[th]; length -= huffman_table_init_jpeg (dec, hufftab, bits); } if (dec->error) { return; } } if (length < 0) { jpeg_decoder_error(dec, "huffman table overran available bytes"); return; }}voidjpeg_decoder_define_quantization_tables (JpegDecoder *dec){ JpegBits *bits = &dec->bits; JpegQuantTable *table; int length; int pq; int tq; int i; COG_INFO ("define quantization table"); length = jpeg_bits_get_u16_be (bits); if (length < 2) { jpeg_decoder_error(dec, "length too short"); return; } length -= 2; while (length > 0) { int x; x = jpeg_bits_get_u8 (bits); length--; pq = x >> 4; tq = x & 0xf; if (pq > 1) { jpeg_decoder_error (dec, "bad pq value"); return; } if (tq > 3) { jpeg_decoder_error (dec, "bad tq value"); return; } table = &dec->quant_tables[tq]; if (pq) { for (i = 0; i < 64; i++) { table->quantizer[i] = jpeg_bits_get_u16_be (bits); length -= 2; } } else { for (i = 0; i < 64; i++) { table->quantizer[i] = jpeg_bits_get_u8 (bits); length -= 1; } } } if (length < 0) { jpeg_decoder_error(dec, "quantization table overran available bytes"); return; }}voidjpeg_decoder_define_restart_interval (JpegDecoder *dec){ JpegBits *bits = &dec->bits; int length; length = jpeg_bits_get_u16_be (bits); if (length != 4) { jpeg_decoder_error(dec, "length supposed to be 4 (%d)", length); return; } /* FIXME this needs to be checked somewhere */ dec->restart_interval = jpeg_bits_get_u16_be (bits);}voidjpeg_decoder_define_arithmetic_conditioning (JpegDecoder *dec){ /* we don't handle arithmetic coding, so skip it */ jpeg_decoder_skip (dec);}voidjpeg_decoder_start_of_frame (JpegDecoder * dec, int marker){ JpegBits *bits = &dec->bits; int i; int length; COG_INFO ("start of frame"); dec->sof_type = marker; length = jpeg_bits_get_u16_be (bits); if (jpeg_bits_available(bits) < length) { jpeg_decoder_error(dec, "not enough data for start_of_frame (%d < %d)", length, jpeg_bits_available(bits)); return; } dec->depth = jpeg_bits_get_u8 (bits); dec->height = jpeg_bits_get_u16_be (bits); dec->width = jpeg_bits_get_u16_be (bits); dec->n_components = jpeg_bits_get_u8 (bits); COG_DEBUG ( "frame_length=%d depth=%d height=%d width=%d n_components=%d", length, dec->depth, dec->height, dec->width, dec->n_components); if (dec->n_components * 3 + 8 != length) { jpeg_decoder_error(dec, "inconsistent header"); return; } for (i = 0; i < dec->n_components; i++) { dec->components[i].id = get_u8 (bits); dec->components[i].h_sample = getbits (bits, 4); dec->components[i].v_sample = getbits (bits, 4); dec->components[i].quant_table = get_u8 (bits); COG_DEBUG ( "[%d] id=%d h_sample=%d v_sample=%d quant_table=%d", i, dec->components[i].id, dec->components[i].h_sample, dec->components[i].v_sample, dec->components[i].quant_table); }}voidjpeg_decoder_start_of_scan (JpegDecoder * dec){ JpegBits *bits = &dec->bits; int length; int i; int spectral_start; int spectral_end; int approx_high; int approx_low; int n; int tmp; int n_components; COG_DEBUG ("start of scan"); length = jpeg_bits_get_u16_be (bits); COG_DEBUG ("length=%d", length); n_components = jpeg_bits_get_u8 (bits); n = 0; dec->scan_h_subsample = 0; dec->scan_v_subsample = 0; for (i = 0; i < n_components; i++) { int component_id; int dc_table; int ac_table; int x; int y; int idx; int h_subsample; int v_subsample; int quant_index; component_id = jpeg_bits_get_u8 (bits); tmp = jpeg_bits_get_u8 (bits); dc_table = tmp >> 4; ac_table = tmp & 0xf; idx = jpeg_decoder_find_component_by_id (dec, component_id); h_subsample = dec->components[idx].h_sample; v_subsample = dec->components[idx].v_sample; quant_index = dec->components[idx].quant_table; for (y = 0; y < v_subsample; y++) { for (x = 0; x < h_subsample; x++) { dec->scan_list[n].component_index = idx; dec->scan_list[n].dc_table = dc_table; dec->scan_list[n].ac_table = ac_table; dec->scan_list[n].quant_table = quant_index; dec->scan_list[n].x = x; dec->scan_list[n].y = y; dec->scan_list[n].offset = y * 8 * dec->components[idx].rowstride + x * 8; n++; if (n > JPEG_LIMIT_SCAN_LIST_LENGTH) { jpeg_decoder_error(dec, "scan list too long"); return; } } } dec->scan_h_subsample = MAX (dec->scan_h_subsample, h_subsample); dec->scan_v_subsample = MAX (dec->scan_v_subsample, v_subsample); COG_DEBUG ("component %d: idx=%d dc_table=%d ac_table=%d n=%d", component_id, idx, dc_table, ac_table, n); } dec->scan_list_length = n; spectral_start = jpeg_bits_get_u8 (bits); spectral_end = jpeg_bits_get_u8 (bits); COG_DEBUG ("spectral range [%d,%d]", spectral_start, spectral_end); tmp = jpeg_bits_get_u8 (bits); approx_high = tmp >> 4; approx_low = tmp & 0xf; COG_DEBUG ("approx range [%d,%d]", approx_low, approx_high); dec->x = 0; dec->y = 0; dec->dc[0] = dec->dc[1] = dec->dc[2] = dec->dc[3] = 128 * 8;}intjpeg_decoder_addbits (JpegDecoder * dec, unsigned char *data, unsigned int len){ unsigned int offset; offset = dec->bits.ptr - dec->data; dec->data = realloc (dec->data, dec->data_len + len); memcpy (dec->data + dec->data_len, data, len); dec->data_len += len; dec->bits.ptr = dec->data + offset; dec->bits.end = dec->data + dec->data_len; return 0;}intjpeg_decoder_get_image_size (JpegDecoder * dec, int *width, int *height){ if (width) *width = dec->width; if (height) *height = dec->height; return 0;}intjpeg_decoder_get_component_ptr (JpegDecoder * dec, int id, unsigned char **image, int *rowstride){ int i; i = jpeg_decoder_find_component_by_id (dec, id); if (image) *image = dec->components[i].image; if (rowstride) *rowstride = dec->components[i].rowstride; return 0;}intjpeg_decoder_get_component_size (JpegDecoder * dec, int id, int *width, int *height){ int i; /* subsampling sizes are rounded up */ i = jpeg_decoder_find_component_by_id (dec, id); if (width) *width = (dec->width - 1) / dec->components[i].h_subsample + 1; if (height) *height = (dec->height - 1) / dec->components[i].v_subsample + 1; return 0;}intjpeg_decoder_get_component_subsampling (JpegDecoder * dec, int id, int *h_subsample, int *v_subsample){ int i; i = jpeg_decoder_find_component_by_id (dec, id); if (h_subsample) *h_subsample = dec->components[i].h_subsample; if (v_subsample) *v_subsample = dec->components[i].v_subsample; return 0;}#if 0intjpeg_decoder_parse (JpegDecoder * dec){ JpegBits *bits = &dec->bits; JpegBits b2; unsigned int x; unsigned int tag; int i; while (bits->ptr < bits->end) { x = get_u8 (bits); if (x != 0xff) { int n = 0; while (x != 0xff) { x = get_u8 (bits); n++; } OIL_DEBUG ("lost sync, skipped %d bytes", n); } while (x == 0xff) { x = get_u8 (bits); } tag = x; OIL_DEBUG ("tag %02x", tag); b2 = *bits; for (i = 0; i < n_jpeg_markers - 1; i++) { if (tag == jpeg_markers[i].tag) { break; } } OIL_DEBUG ("tag: %s", jpeg_markers[i].name); if (jpeg_markers[i].func) { jpeg_markers[i].func (dec, &b2); } else { OIL_DEBUG ("unhandled or illegal JPEG marker (0x%02x)", tag); dumpbits (&b2); } if (jpeg_markers[i].flags & JPEG_ENTROPY_SEGMENT) { jpeg_decoder_decode_entropy_segment (dec, &b2); } syncbits (&b2); bits->ptr = b2.ptr; } return 0;}#endif/* misc helper functins */static voidjpeg_load_standard_huffman_tables (JpegDecoder * dec){ JpegBits b, *bits = &b; bits->ptr = jpeg_standard_tables; bits->idx = 0; bits->end = jpeg_standard_tables + jpeg_standard_tables_size; huffman_table_init_jpeg (dec, &dec->dc_huff_table[0], bits); huffman_table_init_jpeg (dec, &dec->ac_huff_table[0], bits); huffman_table_init_jpeg (dec, &dec->dc_huff_table[1], bits); huffman_table_init_jpeg (dec, &dec->ac_huff_table[1], bits);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -