📄 jrdjfif.c
字号:
{
/* ERREXIT(cinfo->emethods, "Bogus SOF length"); */
send_command(ERR12);
receive_command();
exit();
}
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"); */
send_command(ERR12);
receive_command();
exit();
}
/* 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"); */
send_command(ERR12);
receive_command();
exit();
}
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); */
send_command(ERR13);
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"); */
send_command(ERR12);
receive_command();
exit();
}
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); */
send_command(ERR12);
receive_command();
exit();
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); */
send_command(ERR12);
receive_command();
exit();
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); */
send_command(ERR13);
/* 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -