home *** CD-ROM | disk | FTP | other *** search
- /*
- * jrdjfif.c
- *
- * Copyright (C) 1991, 1992, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- * For conditions of distribution and use, see the accompanying README file.
- *
- * This file contains routines to decode standard JPEG file headers/markers.
- * This code will handle "raw JPEG" and JFIF-convention JPEG files.
- *
- * You can also use this module to decode a raw-JPEG or JFIF-standard data
- * stream that is embedded within a larger file. To do that, you must
- * position the file to the JPEG SOI marker (0xFF/0xD8) that begins the
- * data sequence to be decoded. If nothing better is possible, you can scan
- * the file until you see the SOI marker, then use JUNGETC to push it back.
- *
- * This module relies on the JGETC macro and the read_jpeg_data method (which
- * is provided by the user interface) to read from the JPEG data stream.
- * Therefore, this module is not dependent on any particular assumption about
- * the data source; it need not be a stdio stream at all. (This fact does
- * NOT carry over to more complex JPEG file formats such as JPEG-in-TIFF;
- * those format control modules may well need to assume stdio input.)
- *
- * These routines are invoked via the methods read_file_header,
- * read_scan_header, read_jpeg_data, read_scan_trailer, and read_file_trailer.
- */
-
- #include "jinclude.h"
-
- #ifdef JFIF_SUPPORTED
-
-
- typedef enum { /* JPEG marker codes */
- M_SOF0 = 0xc0,
- M_SOF1 = 0xc1,
- M_SOF2 = 0xc2,
- M_SOF3 = 0xc3,
-
- M_SOF5 = 0xc5,
- M_SOF6 = 0xc6,
- M_SOF7 = 0xc7,
-
- M_JPG = 0xc8,
- M_SOF9 = 0xc9,
- M_SOF10 = 0xca,
- M_SOF11 = 0xcb,
-
- M_SOF13 = 0xcd,
- M_SOF14 = 0xce,
- M_SOF15 = 0xcf,
-
- M_DHT = 0xc4,
-
- M_DAC = 0xcc,
-
- M_RST0 = 0xd0,
- M_RST1 = 0xd1,
- M_RST2 = 0xd2,
- M_RST3 = 0xd3,
- M_RST4 = 0xd4,
- M_RST5 = 0xd5,
- M_RST6 = 0xd6,
- M_RST7 = 0xd7,
-
- M_SOI = 0xd8,
- M_EOI = 0xd9,
- M_SOS = 0xda,
- M_DQT = 0xdb,
- M_DNL = 0xdc,
- M_DRI = 0xdd,
- M_DHP = 0xde,
- M_EXP = 0xdf,
-
- M_APP0 = 0xe0,
- M_APP15 = 0xef,
-
- M_JPG0 = 0xf0,
- M_JPG13 = 0xfd,
- M_COM = 0xfe,
-
- M_TEM = 0x01,
-
- M_ERROR = 0x100
- } JPEG_MARKER;
-
-
- /*
- * Reload the input buffer after it's been emptied, and return the next byte.
- * This is exported for direct use by the entropy decoder.
- * See the JGETC macro for calling conditions. Note in particular that
- * read_jpeg_data may NOT return EOF. If no more data is available, it must
- * exit via ERREXIT, or perhaps synthesize fake data (such as an RST marker).
- * For error recovery purposes, synthesizing an EOI marker is probably best.
- *
- * For this header control module, read_jpeg_data is supplied by the
- * user interface. However, header formats that require random access
- * to the input file would need to supply their own code. This code is
- * left here to indicate what is required.
- */
-
- #if 0 /* not needed in this module */
-
- METHODDEF int
- read_jpeg_data (decompress_info_ptr cinfo)
- {
- cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
-
- cinfo->bytes_in_buffer = (int) JFREAD(cinfo->input_file,
- cinfo->next_input_byte,
- JPEG_BUF_SIZE);
-
- if (cinfo->bytes_in_buffer <= 0) {
- WARNMS(cinfo->emethods, "Premature EOF in JPEG file");
- cinfo->next_input_byte[0] = (char) 0xFF;
- cinfo->next_input_byte[1] = (char) M_EOI;
- cinfo->bytes_in_buffer = 2;
- }
-
- return JGETC(cinfo);
- }
-
- #endif
-
-
- /*
- * Routines to parse JPEG markers & save away the useful info.
- */
-
-
- LOCAL INT32
- get_2bytes (decompress_info_ptr cinfo)
- /* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */
- {
- INT32 a;
-
- a = JGETC(cinfo);
- return (a << 8) + JGETC(cinfo);
- }
-
-
- LOCAL void
- skip_variable (decompress_info_ptr cinfo, int code)
- /* Skip over an unknown or uninteresting variable-length marker */
- {
- INT32 length;
-
- length = get_2bytes(cinfo);
-
- TRACEMS2(cinfo->emethods, 1,
- "Skipping marker 0x%02x, length %u", code, (int) length);
-
- for (length -= 2; length > 0; length--)
- (void) JGETC(cinfo);
- }
-
-
- LOCAL void
- get_dht (decompress_info_ptr cinfo)
- /* Process a DHT marker */
- {
- INT32 length;
- UINT8 bits[17];
- UINT8 huffval[256];
- int i, index, count;
- HUFF_TBL **htblptr;
-
- length = get_2bytes(cinfo)-2;
-
- while (length > 0) {
- index = JGETC(cinfo);
-
- TRACEMS1(cinfo->emethods, 1, "Define Huffman Table 0x%02x", index);
-
- bits[0] = 0;
- count = 0;
- for (i = 1; i <= 16; i++) {
- bits[i] = (UINT8) JGETC(cinfo);
- count += bits[i];
- }
-
- TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d",
- bits[1], bits[2], bits[3], bits[4],
- bits[5], bits[6], bits[7], bits[8]);
- TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d",
- bits[9], bits[10], bits[11], bits[12],
- bits[13], bits[14], bits[15], bits[16]);
-
- if (count > 256)
- ERREXIT(cinfo->emethods, "Bogus DHT counts");
-
- for (i = 0; i < count; i++)
- huffval[i] = (UINT8) JGETC(cinfo);
-
- length -= 1 + 16 + count;
-
- if (index & 0x10) { /* AC table definition */
- index -= 0x10;
- htblptr = &cinfo->ac_huff_tbl_ptrs[index];
- } else { /* DC table definition */
- htblptr = &cinfo->dc_huff_tbl_ptrs[index];
- }
-
- if (index < 0 || index >= NUM_HUFF_TBLS)
- ERREXIT1(cinfo->emethods, "Bogus DHT index %d", index);
-
- if (*htblptr == NULL)
- *htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
-
- MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
- MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
- }
- }
-
-
- LOCAL void
- get_dac (decompress_info_ptr cinfo)
- /* Process a DAC marker */
- {
- INT32 length;
- int index, val;
-
- length = get_2bytes(cinfo)-2;
-
- while (length > 0) {
- index = JGETC(cinfo);
- val = JGETC(cinfo);
-
- TRACEMS2(cinfo->emethods, 1,
- "Define Arithmetic Table 0x%02x: 0x%02x", index, val);
-
- if (index < 0 || index >= (2*NUM_ARITH_TBLS))
- ERREXIT1(cinfo->emethods, "Bogus DAC index %d", index);
-
- if (index >= NUM_ARITH_TBLS) { /* define AC table */
- cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
- } else { /* define DC table */
- cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
- cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
- if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
- ERREXIT1(cinfo->emethods, "Bogus DAC value 0x%x", val);
- }
-
- length -= 2;
- }
- }
-
-
- LOCAL void
- get_dqt (decompress_info_ptr cinfo)
- /* Process a DQT marker */
- {
- INT32 length;
- int n, i, prec;
- UINT16 tmp;
- QUANT_TBL_PTR quant_ptr;
-
- length = get_2bytes(cinfo) - 2;
-
- while (length > 0) {
- n = JGETC(cinfo);
- prec = n >> 4;
- n &= 0x0F;
-
- TRACEMS2(cinfo->emethods, 1,
- "Define Quantization Table %d precision %d", n, prec);
-
- if (n >= NUM_QUANT_TBLS)
- ERREXIT1(cinfo->emethods, "Bogus table number %d", n);
-
- if (cinfo->quant_tbl_ptrs[n] == NULL)
- cinfo->quant_tbl_ptrs[n] = (QUANT_TBL_PTR)
- (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
- quant_ptr = cinfo->quant_tbl_ptrs[n];
-
- for (i = 0; i < DCTSIZE2; i++) {
- tmp = JGETC(cinfo);
- if (prec)
- tmp = (tmp<<8) + JGETC(cinfo);
- quant_ptr[i] = tmp;
- }
-
- for (i = 0; i < DCTSIZE2; i += 8) {
- TRACEMS8(cinfo->emethods, 2, " %4u %4u %4u %4u %4u %4u %4u %4u",
- quant_ptr[i ], quant_ptr[i+1], quant_ptr[i+2], quant_ptr[i+3],
- quant_ptr[i+4], quant_ptr[i+5], quant_ptr[i+6], quant_ptr[i+7]);
- }
-
- length -= DCTSIZE2+1;
- if (prec) length -= DCTSIZE2;
- }
- }
-
-
- LOCAL void
- get_dri (decompress_info_ptr cinfo)
- /* Process a DRI marker */
- {
- if (get_2bytes(cinfo) != 4)
- ERREXIT(cinfo->emethods, "Bogus length in DRI");
-
- cinfo->restart_interval = (UINT16) get_2bytes(cinfo);
-
- TRACEMS1(cinfo->emethods, 1,
- "Define Restart Interval %u", cinfo->restart_interval);
- }
-
-
- LOCAL void
- get_app0 (decompress_info_ptr cinfo)
- /* Process an APP0 marker */
- {
- #define JFIF_LEN 14
- INT32 length;
- UINT8 b[JFIF_LEN];
- int buffp;
-
- length = get_2bytes(cinfo) - 2;
-
- /* See if a JFIF APP0 marker is present */
-
- if (length >= JFIF_LEN) {
- for (buffp = 0; buffp < JFIF_LEN; buffp++)
- b[buffp] = (UINT8) JGETC(cinfo);
- length -= JFIF_LEN;
-
- if (b[0]==0x4A && b[1]==0x46 && b[2]==0x49 && b[3]==0x46 && b[4]==0) {
- /* Found JFIF APP0 marker: check version */
- /* Major version must be 1 */
- if (b[5] != 1)
- ERREXIT2(cinfo->emethods, "Unsupported JFIF revision number %d.%02d",
- b[5], b[6]);
- /* Minor version should be 0..2, but try to process anyway if newer */
- if (b[6] > 2)
- TRACEMS2(cinfo->emethods, 1, "Warning: unknown JFIF revision number %d.%02d",
- b[5], b[6]);
- /* Save info */
- cinfo->density_unit = b[7];
- cinfo->X_density = (b[8] << 8) + b[9];
- cinfo->Y_density = (b[10] << 8) + b[11];
- /* Assume colorspace is YCbCr, unless UI has overridden me */
- if (cinfo->jpeg_color_space == CS_UNKNOWN)
- cinfo->jpeg_color_space = CS_YCbCr;
- TRACEMS3(cinfo->emethods, 1, "JFIF APP0 marker, density %dx%d %d",
- cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
- if (b[12] | b[13])
- TRACEMS2(cinfo->emethods, 1, " with %d x %d thumbnail image",
- b[12], b[13]);
- if (length != ((INT32) b[12] * (INT32) b[13] * (INT32) 3))
- TRACEMS1(cinfo->emethods, 1,
- "Warning: thumbnail image size does not match data length %u",
- (int) length);
- } else {
- TRACEMS1(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF), length %u",
- (int) length + JFIF_LEN);
- }
- } else {
- TRACEMS1(cinfo->emethods, 1, "Short APP0 marker, length %u", (int) length);
- }
-
- while (length-- > 0) /* skip any remaining data */
- (void) JGETC(cinfo);
- }
-
-
- LOCAL void
- get_sof (decompress_info_ptr cinfo, int code)
- /* Process a SOFn marker */
- {
- INT32 length;
- short ci;
- int c;
- jpeg_component_info * compptr;
-
- length = get_2bytes(cinfo);
-
- cinfo->data_precision = JGETC(cinfo);
- cinfo->image_height = get_2bytes(cinfo);
- cinfo->image_width = get_2bytes(cinfo);
- cinfo->num_components = JGETC(cinfo);
-
- TRACEMS4(cinfo->emethods, 1,
- "Start Of Frame 0x%02x: width=%u, height=%u, components=%d",
- code, (int) cinfo->image_width, (int) cinfo->image_height,
- cinfo->num_components);
-
- /* We don't support files in which the image height is initially specified */
- /* as 0 and is later redefined by DNL. As long as we have to check that, */
- /* might as well have a general sanity check. */
- if (cinfo->image_height <= 0 || cinfo->image_width <= 0
- || cinfo->num_components <= 0)
- ERREXIT(cinfo->emethods, "Empty JPEG image (DNL not supported)");
-
- #ifdef EIGHT_BIT_SAMPLES
- if (cinfo->data_precision != 8)
- ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
- #endif
- #ifdef TWELVE_BIT_SAMPLES
- if (cinfo->data_precision != 12) /* this needs more thought?? */
- ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
- #endif
- #ifdef SIXTEEN_BIT_SAMPLES
- if (cinfo->data_precision != 16) /* this needs more thought?? */
- ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
- #endif
-
- if (length != (cinfo->num_components * 3 + 8))
- ERREXIT(cinfo->emethods, "Bogus SOF length");
-
- cinfo->comp_info = (jpeg_component_info *) (*cinfo->emethods->alloc_small)
- (cinfo->num_components * SIZEOF(jpeg_component_info));
-
- for (ci = 0; ci < cinfo->num_components; ci++) {
- compptr = &cinfo->comp_info[ci];
- compptr->component_index = ci;
- compptr->component_id = JGETC(cinfo);
- c = JGETC(cinfo);
- compptr->h_samp_factor = (c >> 4) & 15;
- compptr->v_samp_factor = (c ) & 15;
- compptr->quant_tbl_no = JGETC(cinfo);
-
- TRACEMS4(cinfo->emethods, 1, " Component %d: %dhx%dv q=%d",
- compptr->component_id, compptr->h_samp_factor,
- compptr->v_samp_factor, compptr->quant_tbl_no);
- }
- }
-
-
- LOCAL void
- get_sos (decompress_info_ptr cinfo)
- /* Process a SOS marker */
- {
- INT32 length;
- int i, ci, n, c, cc;
- jpeg_component_info * compptr;
-
- length = get_2bytes(cinfo);
-
- n = JGETC(cinfo); /* Number of components */
- cinfo->comps_in_scan = n;
- length -= 3;
-
- if (length != (n * 2 + 3) || n < 1 || n > MAX_COMPS_IN_SCAN)
- ERREXIT(cinfo->emethods, "Bogus SOS length");
-
- TRACEMS1(cinfo->emethods, 1, "Start Of Scan: %d components", n);
-
- for (i = 0; i < n; i++) {
- cc = JGETC(cinfo);
- c = JGETC(cinfo);
- length -= 2;
-
- for (ci = 0; ci < cinfo->num_components; ci++)
- if (cc == cinfo->comp_info[ci].component_id)
- break;
-
- if (ci >= cinfo->num_components)
- ERREXIT(cinfo->emethods, "Invalid component number in SOS");
-
- compptr = &cinfo->comp_info[ci];
- cinfo->cur_comp_info[i] = compptr;
- compptr->dc_tbl_no = (c >> 4) & 15;
- compptr->ac_tbl_no = (c ) & 15;
-
- TRACEMS3(cinfo->emethods, 1, " c%d: [dc=%d ac=%d]", cc,
- compptr->dc_tbl_no, compptr->ac_tbl_no);
- }
-
- while (length > 0) {
- (void) JGETC(cinfo);
- length--;
- }
- }
-
-
- LOCAL void
- get_soi (decompress_info_ptr cinfo)
- /* Process an SOI marker */
- {
- int i;
-
- TRACEMS(cinfo->emethods, 1, "Start of Image");
-
- /* Reset all parameters that are defined to be reset by SOI */
-
- for (i = 0; i < NUM_ARITH_TBLS; i++) {
- cinfo->arith_dc_L[i] = 0;
- cinfo->arith_dc_U[i] = 1;
- cinfo->arith_ac_K[i] = 5;
- }
- cinfo->restart_interval = 0;
-
- cinfo->density_unit = 0; /* set default JFIF APP0 values */
- cinfo->X_density = 1;
- cinfo->Y_density = 1;
-
- cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling */
- }
-
-
- LOCAL int
- next_marker (decompress_info_ptr cinfo)
- /* Find the next JPEG marker */
- /* Note that the output might not be a valid marker code, */
- /* but it will never be 0 or FF */
- {
- int c, nbytes;
-
- nbytes = 0;
- do {
- do { /* skip any non-FF bytes */
- nbytes++;
- c = JGETC(cinfo);
- } while (c != 0xFF);
- do { /* skip any duplicate FFs */
- /* we don't increment nbytes here since extra FFs are legal */
- c = JGETC(cinfo);
- } while (c == 0xFF);
- } while (c == 0); /* repeat if it was a stuffed FF/00 */
-
- if (nbytes != 1)
- WARNMS2(cinfo->emethods,
- "Corrupt JPEG data: %d extraneous bytes before marker 0x%02x",
- nbytes-1, c);
-
- return c;
- }
-
-
- LOCAL JPEG_MARKER
- process_tables (decompress_info_ptr cinfo)
- /* Scan and process JPEG markers that can appear in any order */
- /* Return when an SOI, EOI, SOFn, or SOS is found */
- {
- int c;
-
- while (TRUE) {
- c = next_marker(cinfo);
-
- switch (c) {
- case M_SOF0:
- case M_SOF1:
- case M_SOF2:
- case M_SOF3:
- case M_SOF5:
- case M_SOF6:
- case M_SOF7:
- case M_JPG:
- case M_SOF9:
- case M_SOF10:
- case M_SOF11:
- case M_SOF13:
- case M_SOF14:
- case M_SOF15:
- case M_SOI:
- case M_EOI:
- case M_SOS:
- return ((JPEG_MARKER) c);
-
- case M_DHT:
- get_dht(cinfo);
- break;
-
- case M_DAC:
- get_dac(cinfo);
- break;
-
- case M_DQT:
- get_dqt(cinfo);
- break;
-
- case M_DRI:
- get_dri(cinfo);
- break;
-
- case M_APP0:
- get_app0(cinfo);
- break;
-
- case M_RST0: /* these are all parameterless */
- case M_RST1:
- case M_RST2:
- case M_RST3:
- case M_RST4:
- case M_RST5:
- case M_RST6:
- case M_RST7:
- case M_TEM:
- TRACEMS1(cinfo->emethods, 1, "Unexpected marker 0x%02x", c);
- break;
-
- default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn */
- skip_variable(cinfo, c);
- break;
- }
- }
- }
-
-
-
- /*
- * Initialize and read the file header (everything through the SOF marker).
- */
-
- METHODDEF void
- read_file_header (decompress_info_ptr cinfo)
- {
- int c;
-
- /* Demand an SOI marker at the start of the file --- otherwise it's
- * probably not a JPEG file at all. If the user interface wants to support
- * nonstandard headers in front of the SOI, it must skip over them itself
- * before calling jpeg_decompress().
- */
- if (JGETC(cinfo) != 0xFF || JGETC(cinfo) != M_SOI)
- ERREXIT(cinfo->emethods, "Not a JPEG file");
-
- get_soi(cinfo); /* OK, process SOI */
-
- /* Process markers until SOF */
- c = process_tables(cinfo);
-
- switch (c) {
- case M_SOF0:
- case M_SOF1:
- get_sof(cinfo, c);
- cinfo->arith_code = FALSE;
- break;
-
- case M_SOF9:
- get_sof(cinfo, c);
- cinfo->arith_code = TRUE;
- break;
-
- default:
- ERREXIT1(cinfo->emethods, "Unsupported SOF marker type 0x%02x", c);
- break;
- }
-
- /* Figure out what colorspace we have */
- /* (too bad the JPEG committee didn't provide a real way to specify this) */
-
- switch (cinfo->num_components) {
- case 1:
- cinfo->jpeg_color_space = CS_GRAYSCALE;
- break;
-
- case 3:
- /* if we saw a JFIF marker, leave it set to YCbCr; */
- /* also leave it alone if UI has provided a value */
- if (cinfo->jpeg_color_space == CS_UNKNOWN) {
- short cid0 = cinfo->comp_info[0].component_id;
- short cid1 = cinfo->comp_info[1].component_id;
- short cid2 = cinfo->comp_info[2].component_id;
-
- if (cid0 == 1 && cid1 == 2 && cid2 == 3)
- cinfo->jpeg_color_space = CS_YCbCr; /* assume it's JFIF w/out marker */
- else if (cid0 == 1 && cid1 == 4 && cid2 == 5)
- cinfo->jpeg_color_space = CS_YIQ; /* prototype's YIQ matrix */
- else {
- TRACEMS3(cinfo->emethods, 1,
- "Unrecognized component IDs %d %d %d, assuming YCbCr",
- cid0, cid1, cid2);
- cinfo->jpeg_color_space = CS_YCbCr;
- }
- }
- break;
-
- case 4:
- cinfo->jpeg_color_space = CS_CMYK;
- break;
-
- default:
- cinfo->jpeg_color_space = CS_UNKNOWN;
- break;
- }
- }
-
-
- /*
- * Read the start of a scan (everything through the SOS marker).
- * Return TRUE if find SOS, FALSE if find EOI.
- */
-
- METHODDEF boolean
- read_scan_header (decompress_info_ptr cinfo)
- {
- int c;
-
- /* Process markers until SOS or EOI */
- c = process_tables(cinfo);
-
- switch (c) {
- case M_SOS:
- get_sos(cinfo);
- return TRUE;
-
- case M_EOI:
- TRACEMS(cinfo->emethods, 1, "End Of Image");
- return FALSE;
-
- default:
- ERREXIT1(cinfo->emethods, "Unexpected marker 0x%02x", c);
- break;
- }
- return FALSE; /* keeps lint happy */
- }
-
-
- /*
- * The entropy decoder calls this routine if it finds a marker other than
- * the restart marker it was expecting. (This code is *not* used unless
- * a nonzero restart interval has been declared.) The passed parameter is
- * the marker code actually found (might be anything, except 0 or FF).
- * The desired restart marker is that indicated by cinfo->next_restart_num.
- * This routine is supposed to apply whatever error recovery strategy seems
- * appropriate in order to position the input stream to the next data segment.
- * For some file formats (eg, TIFF) extra information such as tile boundary
- * pointers may be available to help in this decision.
- *
- * This implementation is substantially constrained by wanting to treat the
- * input as a data stream; this means we can't back up. (For instance, we
- * generally can't fseek() if the input is a Unix pipe.) Therefore, we have
- * only the following actions to work with:
- * 1. Do nothing, let the entropy decoder resume at next byte of file.
- * 2. Read forward until we find another marker, discarding intervening
- * data. (In theory we could look ahead within the current bufferload,
- * without having to discard data if we don't find the desired marker.
- * This idea is not implemented here, in part because it makes behavior
- * dependent on buffer size and chance buffer-boundary positions.)
- * 3. Push back the passed marker (with JUNGETC). This will cause the
- * entropy decoder to process an empty data segment, inserting dummy
- * zeroes, and then re-read the marker we pushed back.
- * #2 is appropriate if we think the desired marker lies ahead, while #3 is
- * appropriate if the found marker is a future restart marker (indicating
- * that we have missed the desired restart marker, probably because it got
- * corrupted).
-
- * We apply #2 or #3 if the found marker is a restart marker no more than
- * two counts behind or ahead of the expected one. We also apply #2 if the
- * found marker is not a legal JPEG marker code (it's certainly bogus data).
- * If the found marker is a restart marker more than 2 counts away, we do #1
- * (too much risk that the marker is erroneous; with luck we will be able to
- * resync at some future point).
- * For any valid non-restart JPEG marker, we apply #3. This keeps us from
- * overrunning the end of a scan. An implementation limited to single-scan
- * files might find it better to apply #2 for markers other than EOI, since
- * any other marker would have to be bogus data in that case.
- */
-
- METHODDEF void
- resync_to_restart (decompress_info_ptr cinfo, int marker)
- {
- int desired = cinfo->next_restart_num;
- int action = 1;
-
- /* Always put up a warning. */
- WARNMS2(cinfo->emethods,
- "Corrupt JPEG data: found 0x%02x marker instead of RST%d",
- marker, desired);
- /* Outer loop handles repeated decision after scanning forward. */
- for (;;) {
- if (marker < M_SOF0)
- action = 2; /* invalid marker */
- else if (marker < M_RST0 || marker > M_RST7)
- action = 3; /* valid non-restart marker */
- else {
- if (marker == (M_RST0 + ((desired+1) & 7)) ||
- marker == (M_RST0 + ((desired+2) & 7)))
- action = 3; /* one of the next two expected restarts */
- else if (marker == (M_RST0 + ((desired-1) & 7)) ||
- marker == (M_RST0 + ((desired-2) & 7)))
- action = 2; /* a prior restart, so advance */
- else
- action = 1; /* desired restart or too far away */
- }
- TRACEMS2(cinfo->emethods, 4,
- "At marker 0x%02x, recovery action %d", marker, action);
- switch (action) {
- case 1:
- /* Let entropy decoder resume processing. */
- return;
- case 2:
- /* Scan to the next marker, and repeat the decision loop. */
- marker = next_marker(cinfo);
- break;
- case 3:
- /* Put back this marker & return. */
- /* Entropy decoder will be forced to process an empty segment. */
- JUNGETC(marker, cinfo);
- JUNGETC(0xFF, cinfo);
- return;
- }
- }
- }
-
-
- /*
- * Finish up after a compressed scan (series of read_jpeg_data calls);
- * prepare for another read_scan_header call.
- */
-
- METHODDEF void
- read_scan_trailer (decompress_info_ptr cinfo)
- {
- /* no work needed */
- }
-
-
- /*
- * Finish up at the end of the file.
- */
-
- METHODDEF void
- read_file_trailer (decompress_info_ptr cinfo)
- {
- /* no work needed */
- }
-
-
- /*
- * The method selection routine for standard JPEG header reading.
- * Note that this must be called by the user interface before calling
- * jpeg_decompress. When a non-JFIF file is to be decompressed (TIFF,
- * perhaps), the user interface must discover the file type and call
- * the appropriate method selection routine.
- */
-
- GLOBAL void
- jselrjfif (decompress_info_ptr cinfo)
- {
- cinfo->methods->read_file_header = read_file_header;
- cinfo->methods->read_scan_header = read_scan_header;
- /* For JFIF/raw-JPEG format, the user interface supplies read_jpeg_data. */
- #if 0
- cinfo->methods->read_jpeg_data = read_jpeg_data;
- #endif
- cinfo->methods->resync_to_restart = resync_to_restart;
- cinfo->methods->read_scan_trailer = read_scan_trailer;
- cinfo->methods->read_file_trailer = read_file_trailer;
- }
-
- #endif /* JFIF_SUPPORTED */
-