/* Limit on marker data length to save for each marker type */ unsignedint length_limit_COM; unsignedint length_limit_APPn[16];
/* Status of COM/APPn marker saving */
jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ unsignedint bytes_read; /* data bytes read so far in marker */ /* Note: cur_marker is not linked into marker_list until it's all read. */
} my_marker_reader;
/* Unload the local copies --- do this only at a restart boundary */ #define INPUT_SYNC(cinfo) \
( datasrc->next_input_byte = next_input_byte, \
datasrc->bytes_in_buffer = bytes_in_buffer )
/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ #define INPUT_RELOAD(cinfo) \
( next_input_byte = datasrc->next_input_byte, \
bytes_in_buffer = datasrc->bytes_in_buffer )
/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. *Notewedo*not*doINPUT_SYNCbeforecallingfill_input_buffer, *butwemustreloadthelocalcopiesafterasuccessfulfill.
*/ #define MAKE_BYTE_AVAIL(cinfo,action) \ if (bytes_in_buffer == 0) { \ if (! (*datasrc->fill_input_buffer) (cinfo)) \
{ action; } \
INPUT_RELOAD(cinfo); \
}
/* Read a byte into variable V. *Ifmustsuspend,takethespecifiedaction(typically"returnFALSE").
*/ #define INPUT_BYTE(cinfo,V,action) \
MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
bytes_in_buffer--; \
V = GETJOCTET(*next_input_byte++); )
/* As above, but read two bytes interpreted as an unsigned 16-bit integer. *VshouldbedeclaredunsignedintorperhapsINT32.
*/ #define INPUT_2BYTES(cinfo,V,action) \
MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
bytes_in_buffer--; \
V = ((unsignedint) GETJOCTET(*next_input_byte++)) << 8; \
MAKE_BYTE_AVAIL(cinfo,action); \
bytes_in_buffer--; \
V += GETJOCTET(*next_input_byte++); )
if (cinfo->marker->saw_SOF)
ERREXIT(cinfo, JERR_SOF_DUPLICATE);
/* 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, JERR_EMPTY_IMAGE);
if (length != (cinfo->num_components * 3))
ERREXIT(cinfo, JERR_BAD_LENGTH);
if (cinfo->comp_info == NULL) { /* do only once, even if suspend */
cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
((j_common_ptr) cinfo, JPOOL_IMAGE,
cinfo->num_components * SIZEOF(jpeg_component_info));
MEMZERO(cinfo->comp_info,
cinfo->num_components * SIZEOF(jpeg_component_info));
}
LOCAL(boolean)
get_sos (j_decompress_ptr cinfo) /* Process a SOS marker */
{
INT32 length; int i, ci, n, c, cc;
jpeg_component_info * compptr;
INPUT_VARS(cinfo);
if (! cinfo->marker->saw_SOF)
ERREXIT(cinfo, JERR_SOS_NO_SOF);
INPUT_2BYTES(cinfo, length, returnFALSE);
INPUT_BYTE(cinfo, n, returnFALSE); /* Number of components */
TRACEMS1(cinfo, 1, JTRC_SOS, n);
if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
ERREXIT(cinfo, JERR_BAD_LENGTH);
cinfo->comps_in_scan = n;
/* Collect the component-spec parameters */
for (i = 0; i < n; i++) {
INPUT_BYTE(cinfo, cc, returnFALSE);
INPUT_BYTE(cinfo, c, returnFALSE);
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) { if (cc == compptr->component_id) goto id_found;
}
/* This CSi (cc) should differ from the previous CSi */ for (ci = 0; ci < i; ci++) { if (cinfo->cur_comp_info[ci] == compptr)
ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
}
}
/* Here we just do minimal validation of the counts to avoid walking *offtheendofourtablespace.jdhuff.cwillcheckmorecarefully.
*/ if (count > 256 || ((INT32) count) > length)
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
for (i = 0; i < count; i++)
INPUT_BYTE(cinfo, huffval[i], returnFALSE);
length -= 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, JERR_DHT_INDEX, index);
if (*htblptr == NULL)
*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
LOCAL(boolean)
get_dqt (j_decompress_ptr cinfo) /* Process a DQT marker */
{
INT32 length; int n, i, prec; unsignedint tmp;
JQUANT_TBL *quant_ptr;
INPUT_VARS(cinfo);
for (i = 0; i < DCTSIZE2; i++) { if (prec)
INPUT_2BYTES(cinfo, tmp, returnFALSE); else
INPUT_BYTE(cinfo, tmp, returnFALSE); /* We convert the zigzag-order table to natural array order. */
quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
}
if (cinfo->err->trace_level >= 2) { for (i = 0; i < DCTSIZE2; i += 8) {
TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
quant_ptr->quantval[i], quant_ptr->quantval[i+1],
quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
}
}
length -= DCTSIZE2+1; if (prec) length -= DCTSIZE2;
}
if (length != 0)
ERREXIT(cinfo, JERR_BAD_LENGTH);
INPUT_SYNC(cinfo); returnTRUE;
}
LOCAL(boolean)
get_dri (j_decompress_ptr cinfo) /* Process a DRI marker */
{
INT32 length; unsignedint tmp;
INPUT_VARS(cinfo);
#define APP0_DATA_LEN 14/* Length of interesting data in APP0 */ #define APP14_DATA_LEN 12/* Length of interesting data in APP14 */ #define APPN_DATA_LEN 14/* Must be the largest of the above!! */
LOCAL(void)
examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, unsignedint datalen, INT32 remaining) /* Examine first few bytes from an APP0. *TakeappropriateactionifitisaJFIFmarker. *datalenis#ofbytesatdata[],remainingislengthofrestofmarkerdata.
*/
{
INT32 totallen = (INT32) datalen + remaining;
LOCAL(void)
examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, unsignedint datalen, INT32 remaining) /* Examine first few bytes from an APP14. *TakeappropriateactionifitisanAdobemarker. *datalenis#ofbytesatdata[],remainingislengthofrestofmarkerdata.
*/
{ unsignedint version, flags0, flags1, transform;
if (datalen >= APP14_DATA_LEN &&
GETJOCTET(data[0]) == 0x41 &&
GETJOCTET(data[1]) == 0x64 &&
GETJOCTET(data[2]) == 0x6F &&
GETJOCTET(data[3]) == 0x62 &&
GETJOCTET(data[4]) == 0x65) { /* Found Adobe APP14 marker */
version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
transform = GETJOCTET(data[11]);
TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
cinfo->saw_Adobe_marker = TRUE;
cinfo->Adobe_transform = (UINT8) transform;
} else { /* Start of APP14 does not match "Adobe", or too short */
TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
}
}
METHODDEF(boolean)
get_interesting_appn (j_decompress_ptr cinfo) /* Process an APP0 or APP14 marker without saving it */
{
INT32 length;
JOCTET b[APPN_DATA_LEN]; unsignedint i, numtoread;
INPUT_VARS(cinfo);
/* get the interesting part of the marker data */ if (length >= APPN_DATA_LEN)
numtoread = APPN_DATA_LEN; elseif (length > 0)
numtoread = (unsignedint) length; else
numtoread = 0; for (i = 0; i < numtoread; i++)
INPUT_BYTE(cinfo, b[i], returnFALSE);
length -= numtoread;
/* process it */ switch (cinfo->unread_marker) { case M_APP0:
examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); break; case M_APP14:
examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); break; default: /* can't get here unless jpeg_save_markers chooses wrong processor */
ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); break;
}
/* skip any remaining data -- could be lots */
INPUT_SYNC(cinfo); if (length > 0)
(*cinfo->src->skip_input_data) (cinfo, (long) length);
returnTRUE;
}
#ifdef SAVE_MARKERS_SUPPORTED
METHODDEF(boolean)
save_marker (j_decompress_ptr cinfo) /* Save an APPn or COM marker into the marker list */
{
my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
jpeg_saved_marker_ptr cur_marker = marker->cur_marker; unsignedint bytes_read, data_length;
JOCTET FAR * data;
INT32 length = 0;
INPUT_VARS(cinfo);
if (cur_marker == NULL) { /* begin reading a marker */
INPUT_2BYTES(cinfo, length, returnFALSE);
length -= 2; if (length >= 0) { /* watch out for bogus length word */ /* figure out how much we want to save */ unsignedint limit; if (cinfo->unread_marker == (int) M_COM)
limit = marker->length_limit_COM; else
limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; if ((unsignedint) length < limit)
limit = (unsignedint) length; /* allocate and initialize the marker item */
cur_marker = (jpeg_saved_marker_ptr)
(*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(struct jpeg_marker_struct) + limit);
cur_marker->next = NULL;
cur_marker->marker = (UINT8) cinfo->unread_marker;
cur_marker->original_length = (unsignedint) length;
cur_marker->data_length = limit; /* data area is just beyond the jpeg_marker_struct */
data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1);
marker->cur_marker = cur_marker;
marker->bytes_read = 0;
bytes_read = 0;
data_length = limit;
} else { /* deal with bogus length word */
bytes_read = data_length = 0;
data = NULL;
}
} else { /* resume reading a marker */
bytes_read = marker->bytes_read;
data_length = cur_marker->data_length;
data = cur_marker->data + bytes_read;
}
while (bytes_read < data_length) {
INPUT_SYNC(cinfo); /* move the restart point to here */
marker->bytes_read = bytes_read; /* If there's not at least one byte in buffer, suspend */
MAKE_BYTE_AVAIL(cinfo, returnFALSE); /* Copy bytes with reasonable rapidity */ while (bytes_read < data_length && bytes_in_buffer > 0) {
*data++ = *next_input_byte++;
bytes_in_buffer--;
bytes_read++;
}
}
/* Done reading what we want to read */ if (cur_marker != NULL) { /* will be NULL if bogus length word */ /* Add new marker to end of list */ if (cinfo->marker_list == NULL) {
cinfo->marker_list = cur_marker;
} else {
jpeg_saved_marker_ptr prev = cinfo->marker_list; while (prev->next != NULL)
prev = prev->next;
prev->next = cur_marker;
} /* Reset pointer & calc remaining data length */
data = cur_marker->data;
length = cur_marker->original_length - data_length;
} /* Reset to initial state for next marker */
marker->cur_marker = NULL;
/* Process the marker if interesting; else just make a generic trace msg */ switch (cinfo->unread_marker) { case M_APP0:
examine_app0(cinfo, data, data_length, length); break; case M_APP14:
examine_app14(cinfo, data, data_length, length); break; default:
TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
(int) (data_length + length)); break;
}
/* skip any remaining data -- could be lots */
INPUT_SYNC(cinfo); /* do before skip_input_data */ if (length > 0)
(*cinfo->src->skip_input_data) (cinfo, (long) length);
returnTRUE;
}
#endif/* SAVE_MARKERS_SUPPORTED */
METHODDEF(boolean)
skip_variable (j_decompress_ptr cinfo) /* Skip over an unknown or uninteresting variable-length marker */
{
INT32 length;
INPUT_VARS(cinfo);
LOCAL(boolean)
next_marker (j_decompress_ptr cinfo)
{ int c;
INPUT_VARS(cinfo);
for (;;) {
INPUT_BYTE(cinfo, c, returnFALSE); /* Skip any non-FF bytes. *Thismaylookabitinefficient,butitwillnotoccurinavalidfile. *Wesyncaftereachdiscardedbytesothatasuspendingdatasource *candiscardthebytefromitsbuffer.
*/ while (c != 0xFF) {
cinfo->marker->discarded_bytes++;
INPUT_SYNC(cinfo);
INPUT_BYTE(cinfo, c, returnFALSE);
} /* This loop swallows any duplicate FF bytes. Extra FFs are legal as *padbytes,sodon'tcountthemindiscarded_bytes.Weassumethere *willnotbesomanyconsecutiveFFbytesastooverflowasuspending *datasource'sinputbuffer.
*/ do {
INPUT_BYTE(cinfo, c, returnFALSE);
} while (c == 0xFF); if (c != 0) break; /* found a valid marker, exit loop */ /* Reach here if we found a stuffed-zero data sequence (FF/00). *Discarditandloopbacktotryagain.
*/
cinfo->marker->discarded_bytes += 2;
INPUT_SYNC(cinfo);
}
LOCAL(boolean)
first_marker (j_decompress_ptr cinfo) /* Like next_marker, but used to obtain the initial SOI marker. */ /* For this marker, we do not allow preceding garbage or fill; otherwise, *wemightwellscananentireinputfilebeforerealizingitain'tJPEG. *Ifanapplicationwantstoprocessnon-JFIFfiles,itmustseektothe *SOIbeforecallingtheJPEGlibrary.
*/
{ int c, c2;
INPUT_VARS(cinfo);
METHODDEF(int)
read_markers (j_decompress_ptr cinfo)
{ /* Outer loop repeats once for each marker. */ for (;;) { /* Collect the marker proper, unless we already did. */ /* NB: first_marker() enforces the requirement that SOI appear first. */ if (cinfo->unread_marker == 0) { if (! cinfo->marker->saw_SOI) { if (! first_marker(cinfo)) return JPEG_SUSPENDED;
} else { if (! next_marker(cinfo)) return JPEG_SUSPENDED;
}
} /* At this point cinfo->unread_marker contains the marker code and the *inputpointisjustpastthemarkerproper,butbeforeanyparameters. *Asuspensionwillcauseustoreturnwiththisstatestilltrue.
*/ switch (cinfo->unread_marker) { case M_SOI: if (! get_soi(cinfo)) return JPEG_SUSPENDED; break;
case M_SOF0: /* Baseline */ case M_SOF1: /* Extended sequential, Huffman */ if (! get_sof(cinfo, FALSE, FALSE)) return JPEG_SUSPENDED; break;
case M_SOF2: /* Progressive, Huffman */ if (! get_sof(cinfo, TRUE, FALSE)) return JPEG_SUSPENDED; break;
case M_SOF9: /* Extended sequential, arithmetic */ if (! get_sof(cinfo, FALSE, TRUE)) return JPEG_SUSPENDED; break;
case M_SOF10: /* Progressive, arithmetic */ if (! get_sof(cinfo, TRUE, TRUE)) return JPEG_SUSPENDED; break;
/* Currently unsupported SOFn types */ case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_JPG: /* Reserved for JPEG extensions */ case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */
ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); break;
case M_SOS: if (! get_sos(cinfo)) return JPEG_SUSPENDED;
cinfo->unread_marker = 0; /* processed the marker */ return JPEG_REACHED_SOS;
case M_EOI:
TRACEMS(cinfo, 1, JTRC_EOI);
cinfo->unread_marker = 0; /* processed the marker */ return JPEG_REACHED_EOI;
case M_DAC: if (! get_dac(cinfo)) return JPEG_SUSPENDED; break;
case M_DHT: if (! get_dht(cinfo)) return JPEG_SUSPENDED; break;
case M_DQT: if (! get_dqt(cinfo)) return JPEG_SUSPENDED; break;
case M_DRI: if (! get_dri(cinfo)) return JPEG_SUSPENDED; break;
case M_APP0: case M_APP1: case M_APP2: case M_APP3: case M_APP4: case M_APP5: case M_APP6: case M_APP7: case M_APP8: case M_APP9: case M_APP10: case M_APP11: case M_APP12: case M_APP13: case M_APP14: case M_APP15: if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[
cinfo->unread_marker - (int) M_APP0]) (cinfo)) return JPEG_SUSPENDED; break;
case M_COM: if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) return JPEG_SUSPENDED; 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, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); break;
case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ if (! skip_variable(cinfo)) return JPEG_SUSPENDED; break;
default: /* must be DHP, EXP, JPGn, or RESn */ /* For now, we treat the reserved markers as fatal errors since they are *likelytobeusedtosignalincompatibleJPEGPart3extensions. *OncetheJPEG3version-numbermarkeriswelldefined,thiscode *oughttochange! *[Tobebehaviorallycompatiblewithotherpopularimagedisplay *applications,wearenowtreatingtheseunknownmarkersaswarnings, *ratherthanerrors.Thisallowsprocessingtocontinue,although *anyportionsoftheimageafterthebadmarkermaybecorrupted *and/orrenderedgray.See4511441.]
*/
WARNMS1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); break;
} /* Successfully processed marker, so reset state variable */
cinfo->unread_marker = 0;
} /* end loop */
}
METHODDEF(boolean)
read_restart_marker (j_decompress_ptr cinfo)
{ /* Obtain a marker unless we already did. */ /* Note that next_marker will complain if it skips any data. */ if (cinfo->unread_marker == 0) { if (! next_marker(cinfo)) returnFALSE;
}
if (cinfo->unread_marker ==
((int) M_RST0 + cinfo->marker->next_restart_num)) { /* Normal case --- swallow the marker and let entropy decoder continue */
TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
cinfo->unread_marker = 0;
} else { /* Uh-oh, the restart markers have been messed up. */ /* Let the data source manager determine how to resync. */ if (! (*cinfo->src->resync_to_restart) (cinfo,
cinfo->marker->next_restart_num)) returnFALSE;
}
cinfo->comp_info = NULL; /* until allocated by get_sof */
cinfo->input_scan_number = 0; /* no SOS seen yet */
cinfo->unread_marker = 0; /* no pending marker */
marker->pub.saw_SOI = FALSE; /* set internal state too */
marker->pub.saw_SOF = FALSE;
marker->pub.discarded_bytes = 0;
marker->cur_marker = NULL;
}
/* Length limit mustn't be larger than what we can allocate *(shouldonlybeaconcernina16-bitenvironment).
*/
maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); if (length_limit > maxlength)
length_limit = (unsignedint) maxlength;
/* Choose processor routine to use. *APP0/APP14havespecialrequirements.
*/ if (length_limit) {
processor = save_marker; /* If saving APP0/APP14, save at least enough for our internal use. */ if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN)
length_limit = APP0_DATA_LEN; elseif (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN)
length_limit = APP14_DATA_LEN;
} else {
processor = skip_variable; /* If discarding APP0/APP14, use our regular on-the-fly processor. */ if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14)
processor = get_interesting_appn;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.