ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

jdmarker.c
Go to the documentation of this file.
00001 /*
00002  * jdmarker.c
00003  *
00004  * Copyright (C) 1991-1998, Thomas G. Lane.
00005  * Modified 2009 by Guido Vollbeding.
00006  * This file is part of the Independent JPEG Group's software.
00007  * For conditions of distribution and use, see the accompanying README file.
00008  *
00009  * This file contains routines to decode JPEG datastream markers.
00010  * Most of the complexity arises from our desire to support input
00011  * suspension: if not all of the data for a marker is available,
00012  * we must exit back to the application.  On resumption, we reprocess
00013  * the marker.
00014  */
00015 
00016 #define JPEG_INTERNALS
00017 #include "jinclude.h"
00018 #include "jpeglib.h"
00019 
00020 
00021 typedef enum {          /* JPEG marker codes */
00022   M_SOF0  = 0xc0,
00023   M_SOF1  = 0xc1,
00024   M_SOF2  = 0xc2,
00025   M_SOF3  = 0xc3,
00026   
00027   M_SOF5  = 0xc5,
00028   M_SOF6  = 0xc6,
00029   M_SOF7  = 0xc7,
00030   
00031   M_JPG   = 0xc8,
00032   M_SOF9  = 0xc9,
00033   M_SOF10 = 0xca,
00034   M_SOF11 = 0xcb,
00035   
00036   M_SOF13 = 0xcd,
00037   M_SOF14 = 0xce,
00038   M_SOF15 = 0xcf,
00039   
00040   M_DHT   = 0xc4,
00041   
00042   M_DAC   = 0xcc,
00043   
00044   M_RST0  = 0xd0,
00045   M_RST1  = 0xd1,
00046   M_RST2  = 0xd2,
00047   M_RST3  = 0xd3,
00048   M_RST4  = 0xd4,
00049   M_RST5  = 0xd5,
00050   M_RST6  = 0xd6,
00051   M_RST7  = 0xd7,
00052   
00053   M_SOI   = 0xd8,
00054   M_EOI   = 0xd9,
00055   M_SOS   = 0xda,
00056   M_DQT   = 0xdb,
00057   M_DNL   = 0xdc,
00058   M_DRI   = 0xdd,
00059   M_DHP   = 0xde,
00060   M_EXP   = 0xdf,
00061   
00062   M_APP0  = 0xe0,
00063   M_APP1  = 0xe1,
00064   M_APP2  = 0xe2,
00065   M_APP3  = 0xe3,
00066   M_APP4  = 0xe4,
00067   M_APP5  = 0xe5,
00068   M_APP6  = 0xe6,
00069   M_APP7  = 0xe7,
00070   M_APP8  = 0xe8,
00071   M_APP9  = 0xe9,
00072   M_APP10 = 0xea,
00073   M_APP11 = 0xeb,
00074   M_APP12 = 0xec,
00075   M_APP13 = 0xed,
00076   M_APP14 = 0xee,
00077   M_APP15 = 0xef,
00078   
00079   M_JPG0  = 0xf0,
00080   M_JPG13 = 0xfd,
00081   M_COM   = 0xfe,
00082   
00083   M_TEM   = 0x01,
00084   
00085   M_ERROR = 0x100
00086 } JPEG_MARKER;
00087 
00088 
00089 /* Private state */
00090 
00091 typedef struct {
00092   struct jpeg_marker_reader pub; /* public fields */
00093 
00094   /* Application-overridable marker processing methods */
00095   jpeg_marker_parser_method process_COM;
00096   jpeg_marker_parser_method process_APPn[16];
00097 
00098   /* Limit on marker data length to save for each marker type */
00099   unsigned int length_limit_COM;
00100   unsigned int length_limit_APPn[16];
00101 
00102   /* Status of COM/APPn marker saving */
00103   jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */
00104   unsigned int bytes_read;      /* data bytes read so far in marker */
00105   /* Note: cur_marker is not linked into marker_list until it's all read. */
00106 } my_marker_reader;
00107 
00108 typedef my_marker_reader * my_marker_ptr;
00109 
00110 
00111 /*
00112  * Macros for fetching data from the data source module.
00113  *
00114  * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect
00115  * the current restart point; we update them only when we have reached a
00116  * suitable place to restart if a suspension occurs.
00117  */
00118 
00119 /* Declare and initialize local copies of input pointer/count */
00120 #define INPUT_VARS(cinfo)  \
00121     struct jpeg_source_mgr * datasrc = (cinfo)->src;  \
00122     const JOCTET * next_input_byte = datasrc->next_input_byte;  \
00123     size_t bytes_in_buffer = datasrc->bytes_in_buffer
00124 
00125 /* Unload the local copies --- do this only at a restart boundary */
00126 #define INPUT_SYNC(cinfo)  \
00127     ( datasrc->next_input_byte = next_input_byte,  \
00128       datasrc->bytes_in_buffer = bytes_in_buffer )
00129 
00130 /* Reload the local copies --- used only in MAKE_BYTE_AVAIL */
00131 #define INPUT_RELOAD(cinfo)  \
00132     ( next_input_byte = datasrc->next_input_byte,  \
00133       bytes_in_buffer = datasrc->bytes_in_buffer )
00134 
00135 /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
00136  * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
00137  * but we must reload the local copies after a successful fill.
00138  */
00139 #define MAKE_BYTE_AVAIL(cinfo,action)  \
00140     if (bytes_in_buffer == 0) {  \
00141       if (! (*datasrc->fill_input_buffer) (cinfo))  \
00142         { action; }  \
00143       INPUT_RELOAD(cinfo);  \
00144     }
00145 
00146 /* Read a byte into variable V.
00147  * If must suspend, take the specified action (typically "return FALSE").
00148  */
00149 #define INPUT_BYTE(cinfo,V,action)  \
00150     MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
00151           bytes_in_buffer--; \
00152           V = GETJOCTET(*next_input_byte++); )
00153 
00154 /* As above, but read two bytes interpreted as an unsigned 16-bit integer.
00155  * V should be declared unsigned int or perhaps INT32.
00156  */
00157 #define INPUT_2BYTES(cinfo,V,action)  \
00158     MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
00159           bytes_in_buffer--; \
00160           V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
00161           MAKE_BYTE_AVAIL(cinfo,action); \
00162           bytes_in_buffer--; \
00163           V += GETJOCTET(*next_input_byte++); )
00164 
00165 
00166 /*
00167  * Routines to process JPEG markers.
00168  *
00169  * Entry condition: JPEG marker itself has been read and its code saved
00170  *   in cinfo->unread_marker; input restart point is just after the marker.
00171  *
00172  * Exit: if return TRUE, have read and processed any parameters, and have
00173  *   updated the restart point to point after the parameters.
00174  *   If return FALSE, was forced to suspend before reaching end of
00175  *   marker parameters; restart point has not been moved.  Same routine
00176  *   will be called again after application supplies more input data.
00177  *
00178  * This approach to suspension assumes that all of a marker's parameters
00179  * can fit into a single input bufferload.  This should hold for "normal"
00180  * markers.  Some COM/APPn markers might have large parameter segments
00181  * that might not fit.  If we are simply dropping such a marker, we use
00182  * skip_input_data to get past it, and thereby put the problem on the
00183  * source manager's shoulders.  If we are saving the marker's contents
00184  * into memory, we use a slightly different convention: when forced to
00185  * suspend, the marker processor updates the restart point to the end of
00186  * what it's consumed (ie, the end of the buffer) before returning FALSE.
00187  * On resumption, cinfo->unread_marker still contains the marker code,
00188  * but the data source will point to the next chunk of marker data.
00189  * The marker processor must retain internal state to deal with this.
00190  *
00191  * Note that we don't bother to avoid duplicate trace messages if a
00192  * suspension occurs within marker parameters.  Other side effects
00193  * require more care.
00194  */
00195 
00196 
00197 LOCAL(boolean)
00198 get_soi (j_decompress_ptr cinfo)
00199 /* Process an SOI marker */
00200 {
00201   int i;
00202   
00203   TRACEMS(cinfo, 1, JTRC_SOI);
00204 
00205   if (cinfo->marker->saw_SOI)
00206     ERREXIT(cinfo, JERR_SOI_DUPLICATE);
00207 
00208   /* Reset all parameters that are defined to be reset by SOI */
00209 
00210   for (i = 0; i < NUM_ARITH_TBLS; i++) {
00211     cinfo->arith_dc_L[i] = 0;
00212     cinfo->arith_dc_U[i] = 1;
00213     cinfo->arith_ac_K[i] = 5;
00214   }
00215   cinfo->restart_interval = 0;
00216 
00217   /* Set initial assumptions for colorspace etc */
00218 
00219   cinfo->jpeg_color_space = JCS_UNKNOWN;
00220   cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */
00221 
00222   cinfo->saw_JFIF_marker = FALSE;
00223   cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */
00224   cinfo->JFIF_minor_version = 1;
00225   cinfo->density_unit = 0;
00226   cinfo->X_density = 1;
00227   cinfo->Y_density = 1;
00228   cinfo->saw_Adobe_marker = FALSE;
00229   cinfo->Adobe_transform = 0;
00230 
00231   cinfo->marker->saw_SOI = TRUE;
00232 
00233   return TRUE;
00234 }
00235 
00236 
00237 LOCAL(boolean)
00238 get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog,
00239      boolean is_arith)
00240 /* Process a SOFn marker */
00241 {
00242   INT32 length;
00243   int c, ci;
00244   jpeg_component_info * compptr;
00245   INPUT_VARS(cinfo);
00246 
00247   cinfo->is_baseline = is_baseline;
00248   cinfo->progressive_mode = is_prog;
00249   cinfo->arith_code = is_arith;
00250 
00251   INPUT_2BYTES(cinfo, length, return FALSE);
00252 
00253   INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE);
00254   INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE);
00255   INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE);
00256   INPUT_BYTE(cinfo, cinfo->num_components, return FALSE);
00257 
00258   length -= 8;
00259 
00260   TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
00261        (int) cinfo->image_width, (int) cinfo->image_height,
00262        cinfo->num_components);
00263 
00264   if (cinfo->marker->saw_SOF)
00265     ERREXIT(cinfo, JERR_SOF_DUPLICATE);
00266 
00267   /* We don't support files in which the image height is initially specified */
00268   /* as 0 and is later redefined by DNL.  As long as we have to check that,  */
00269   /* might as well have a general sanity check. */
00270   if (cinfo->image_height <= 0 || cinfo->image_width <= 0
00271       || cinfo->num_components <= 0)
00272     ERREXIT(cinfo, JERR_EMPTY_IMAGE);
00273 
00274   if (length != (cinfo->num_components * 3))
00275     ERREXIT(cinfo, JERR_BAD_LENGTH);
00276 
00277   if (cinfo->comp_info == NULL) /* do only once, even if suspend */
00278     cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
00279             ((j_common_ptr) cinfo, JPOOL_IMAGE,
00280              cinfo->num_components * SIZEOF(jpeg_component_info));
00281   
00282   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
00283        ci++, compptr++) {
00284     compptr->component_index = ci;
00285     INPUT_BYTE(cinfo, compptr->component_id, return FALSE);
00286     INPUT_BYTE(cinfo, c, return FALSE);
00287     compptr->h_samp_factor = (c >> 4) & 15;
00288     compptr->v_samp_factor = (c     ) & 15;
00289     INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE);
00290 
00291     TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
00292          compptr->component_id, compptr->h_samp_factor,
00293          compptr->v_samp_factor, compptr->quant_tbl_no);
00294   }
00295 
00296   cinfo->marker->saw_SOF = TRUE;
00297 
00298   INPUT_SYNC(cinfo);
00299   return TRUE;
00300 }
00301 
00302 
00303 LOCAL(boolean)
00304 get_sos (j_decompress_ptr cinfo)
00305 /* Process a SOS marker */
00306 {
00307   INT32 length;
00308   int i, ci, n, c, cc;
00309   jpeg_component_info * compptr;
00310   INPUT_VARS(cinfo);
00311 
00312   if (! cinfo->marker->saw_SOF)
00313     ERREXIT(cinfo, JERR_SOS_NO_SOF);
00314 
00315   INPUT_2BYTES(cinfo, length, return FALSE);
00316 
00317   INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */
00318 
00319   TRACEMS1(cinfo, 1, JTRC_SOS, n);
00320 
00321   if (length != (n * 2 + 6) || n > MAX_COMPS_IN_SCAN ||
00322       (n == 0 && !cinfo->progressive_mode))
00323       /* pseudo SOS marker only allowed in progressive mode */
00324     ERREXIT(cinfo, JERR_BAD_LENGTH);
00325 
00326   cinfo->comps_in_scan = n;
00327 
00328   /* Collect the component-spec parameters */
00329 
00330   for (i = 0; i < n; i++) {
00331     INPUT_BYTE(cinfo, cc, return FALSE);
00332     INPUT_BYTE(cinfo, c, return FALSE);
00333     
00334     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
00335      ci++, compptr++) {
00336       if (cc == compptr->component_id)
00337     goto id_found;
00338     }
00339 
00340     ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
00341 
00342   id_found:
00343 
00344     cinfo->cur_comp_info[i] = compptr;
00345     compptr->dc_tbl_no = (c >> 4) & 15;
00346     compptr->ac_tbl_no = (c     ) & 15;
00347     
00348     TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
00349          compptr->dc_tbl_no, compptr->ac_tbl_no);
00350   }
00351 
00352   /* Collect the additional scan parameters Ss, Se, Ah/Al. */
00353   INPUT_BYTE(cinfo, c, return FALSE);
00354   cinfo->Ss = c;
00355   INPUT_BYTE(cinfo, c, return FALSE);
00356   cinfo->Se = c;
00357   INPUT_BYTE(cinfo, c, return FALSE);
00358   cinfo->Ah = (c >> 4) & 15;
00359   cinfo->Al = (c     ) & 15;
00360 
00361   TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se,
00362        cinfo->Ah, cinfo->Al);
00363 
00364   /* Prepare to scan data & restart markers */
00365   cinfo->marker->next_restart_num = 0;
00366 
00367   /* Count another (non-pseudo) SOS marker */
00368   if (n) cinfo->input_scan_number++;
00369 
00370   INPUT_SYNC(cinfo);
00371   return TRUE;
00372 }
00373 
00374 
00375 #ifdef D_ARITH_CODING_SUPPORTED
00376 
00377 LOCAL(boolean)
00378 get_dac (j_decompress_ptr cinfo)
00379 /* Process a DAC marker */
00380 {
00381   INT32 length;
00382   int index, val;
00383   INPUT_VARS(cinfo);
00384 
00385   INPUT_2BYTES(cinfo, length, return FALSE);
00386   length -= 2;
00387   
00388   while (length > 0) {
00389     INPUT_BYTE(cinfo, index, return FALSE);
00390     INPUT_BYTE(cinfo, val, return FALSE);
00391 
00392     length -= 2;
00393 
00394     TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
00395 
00396     if (index < 0 || index >= (2*NUM_ARITH_TBLS))
00397       ERREXIT1(cinfo, JERR_DAC_INDEX, index);
00398 
00399     if (index >= NUM_ARITH_TBLS) { /* define AC table */
00400       cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
00401     } else {            /* define DC table */
00402       cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
00403       cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
00404       if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
00405     ERREXIT1(cinfo, JERR_DAC_VALUE, val);
00406     }
00407   }
00408 
00409   if (length != 0)
00410     ERREXIT(cinfo, JERR_BAD_LENGTH);
00411 
00412   INPUT_SYNC(cinfo);
00413   return TRUE;
00414 }
00415 
00416 #else /* ! D_ARITH_CODING_SUPPORTED */
00417 
00418 #define get_dac(cinfo)  skip_variable(cinfo)
00419 
00420 #endif /* D_ARITH_CODING_SUPPORTED */
00421 
00422 
00423 LOCAL(boolean)
00424 get_dht (j_decompress_ptr cinfo)
00425 /* Process a DHT marker */
00426 {
00427   INT32 length;
00428   UINT8 bits[17];
00429   UINT8 huffval[256];
00430   int i, index, count;
00431   JHUFF_TBL **htblptr;
00432   INPUT_VARS(cinfo);
00433 
00434   INPUT_2BYTES(cinfo, length, return FALSE);
00435   length -= 2;
00436   
00437   while (length > 16) {
00438     INPUT_BYTE(cinfo, index, return FALSE);
00439 
00440     TRACEMS1(cinfo, 1, JTRC_DHT, index);
00441       
00442     bits[0] = 0;
00443     count = 0;
00444     for (i = 1; i <= 16; i++) {
00445       INPUT_BYTE(cinfo, bits[i], return FALSE);
00446       count += bits[i];
00447     }
00448 
00449     length -= 1 + 16;
00450 
00451     TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
00452          bits[1], bits[2], bits[3], bits[4],
00453          bits[5], bits[6], bits[7], bits[8]);
00454     TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
00455          bits[9], bits[10], bits[11], bits[12],
00456          bits[13], bits[14], bits[15], bits[16]);
00457 
00458     /* Here we just do minimal validation of the counts to avoid walking
00459      * off the end of our table space.  jdhuff.c will check more carefully.
00460      */
00461     if (count > 256 || ((INT32) count) > length)
00462       ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
00463 
00464     for (i = 0; i < count; i++)
00465       INPUT_BYTE(cinfo, huffval[i], return FALSE);
00466 
00467     length -= count;
00468 
00469     if (index & 0x10) {     /* AC table definition */
00470       index -= 0x10;
00471       htblptr = &cinfo->ac_huff_tbl_ptrs[index];
00472     } else {            /* DC table definition */
00473       htblptr = &cinfo->dc_huff_tbl_ptrs[index];
00474     }
00475 
00476     if (index < 0 || index >= NUM_HUFF_TBLS)
00477       ERREXIT1(cinfo, JERR_DHT_INDEX, index);
00478 
00479     if (*htblptr == NULL)
00480       *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
00481   
00482     MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
00483     MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
00484   }
00485 
00486   if (length != 0)
00487     ERREXIT(cinfo, JERR_BAD_LENGTH);
00488 
00489   INPUT_SYNC(cinfo);
00490   return TRUE;
00491 }
00492 
00493 
00494 LOCAL(boolean)
00495 get_dqt (j_decompress_ptr cinfo)
00496 /* Process a DQT marker */
00497 {
00498   INT32 length, count, i;
00499   int n, prec;
00500   unsigned int tmp;
00501   JQUANT_TBL *quant_ptr;
00502   const int *natural_order;
00503   INPUT_VARS(cinfo);
00504 
00505   INPUT_2BYTES(cinfo, length, return FALSE);
00506   length -= 2;
00507 
00508   while (length > 0) {
00509     length--;
00510     INPUT_BYTE(cinfo, n, return FALSE);
00511     prec = n >> 4;
00512     n &= 0x0F;
00513 
00514     TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
00515 
00516     if (n >= NUM_QUANT_TBLS)
00517       ERREXIT1(cinfo, JERR_DQT_INDEX, n);
00518       
00519     if (cinfo->quant_tbl_ptrs[n] == NULL)
00520       cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
00521     quant_ptr = cinfo->quant_tbl_ptrs[n];
00522 
00523     if (prec) {
00524       if (length < DCTSIZE2 * 2) {
00525     /* Initialize full table for safety. */
00526     for (i = 0; i < DCTSIZE2; i++) {
00527       quant_ptr->quantval[i] = 1;
00528     }
00529     count = length >> 1;
00530       } else
00531     count = DCTSIZE2;
00532     } else {
00533       if (length < DCTSIZE2) {
00534     /* Initialize full table for safety. */
00535     for (i = 0; i < DCTSIZE2; i++) {
00536       quant_ptr->quantval[i] = 1;
00537     }
00538     count = length;
00539       } else
00540     count = DCTSIZE2;
00541     }
00542 
00543     switch (count) {
00544     case (2*2): natural_order = jpeg_natural_order2; break;
00545     case (3*3): natural_order = jpeg_natural_order3; break;
00546     case (4*4): natural_order = jpeg_natural_order4; break;
00547     case (5*5): natural_order = jpeg_natural_order5; break;
00548     case (6*6): natural_order = jpeg_natural_order6; break;
00549     case (7*7): natural_order = jpeg_natural_order7; break;
00550     default:    natural_order = jpeg_natural_order;  break;
00551     }
00552 
00553     for (i = 0; i < count; i++) {
00554       if (prec)
00555     INPUT_2BYTES(cinfo, tmp, return FALSE);
00556       else
00557     INPUT_BYTE(cinfo, tmp, return FALSE);
00558       /* We convert the zigzag-order table to natural array order. */
00559       quant_ptr->quantval[natural_order[i]] = (UINT16) tmp;
00560     }
00561 
00562     if (cinfo->err->trace_level >= 2) {
00563       for (i = 0; i < DCTSIZE2; i += 8) {
00564     TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
00565          quant_ptr->quantval[i],   quant_ptr->quantval[i+1],
00566          quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
00567          quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
00568          quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
00569       }
00570     }
00571 
00572     length -= count;
00573     if (prec) length -= count;
00574   }
00575 
00576   if (length != 0)
00577     ERREXIT(cinfo, JERR_BAD_LENGTH);
00578 
00579   INPUT_SYNC(cinfo);
00580   return TRUE;
00581 }
00582 
00583 
00584 LOCAL(boolean)
00585 get_dri (j_decompress_ptr cinfo)
00586 /* Process a DRI marker */
00587 {
00588   INT32 length;
00589   unsigned int tmp;
00590   INPUT_VARS(cinfo);
00591 
00592   INPUT_2BYTES(cinfo, length, return FALSE);
00593   
00594   if (length != 4)
00595     ERREXIT(cinfo, JERR_BAD_LENGTH);
00596 
00597   INPUT_2BYTES(cinfo, tmp, return FALSE);
00598 
00599   TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
00600 
00601   cinfo->restart_interval = tmp;
00602 
00603   INPUT_SYNC(cinfo);
00604   return TRUE;
00605 }
00606 
00607 
00608 /*
00609  * Routines for processing APPn and COM markers.
00610  * These are either saved in memory or discarded, per application request.
00611  * APP0 and APP14 are specially checked to see if they are
00612  * JFIF and Adobe markers, respectively.
00613  */
00614 
00615 #define APP0_DATA_LEN   14  /* Length of interesting data in APP0 */
00616 #define APP14_DATA_LEN  12  /* Length of interesting data in APP14 */
00617 #define APPN_DATA_LEN   14  /* Must be the largest of the above!! */
00618 
00619 
00620 LOCAL(void)
00621 examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data,
00622           unsigned int datalen, INT32 remaining)
00623 /* Examine first few bytes from an APP0.
00624  * Take appropriate action if it is a JFIF marker.
00625  * datalen is # of bytes at data[], remaining is length of rest of marker data.
00626  */
00627 {
00628   INT32 totallen = (INT32) datalen + remaining;
00629 
00630   if (datalen >= APP0_DATA_LEN &&
00631       GETJOCTET(data[0]) == 0x4A &&
00632       GETJOCTET(data[1]) == 0x46 &&
00633       GETJOCTET(data[2]) == 0x49 &&
00634       GETJOCTET(data[3]) == 0x46 &&
00635       GETJOCTET(data[4]) == 0) {
00636     /* Found JFIF APP0 marker: save info */
00637     cinfo->saw_JFIF_marker = TRUE;
00638     cinfo->JFIF_major_version = GETJOCTET(data[5]);
00639     cinfo->JFIF_minor_version = GETJOCTET(data[6]);
00640     cinfo->density_unit = GETJOCTET(data[7]);
00641     cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]);
00642     cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]);
00643     /* Check version.
00644      * Major version must be 1, anything else signals an incompatible change.
00645      * (We used to treat this as an error, but now it's a nonfatal warning,
00646      * because some bozo at Hijaak couldn't read the spec.)
00647      * Minor version should be 0..2, but process anyway if newer.
00648      */
00649     if (cinfo->JFIF_major_version != 1)
00650       WARNMS2(cinfo, JWRN_JFIF_MAJOR,
00651           cinfo->JFIF_major_version, cinfo->JFIF_minor_version);
00652     /* Generate trace messages */
00653     TRACEMS5(cinfo, 1, JTRC_JFIF,
00654          cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
00655          cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
00656     /* Validate thumbnail dimensions and issue appropriate messages */
00657     if (GETJOCTET(data[12]) | GETJOCTET(data[13]))
00658       TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
00659            GETJOCTET(data[12]), GETJOCTET(data[13]));
00660     totallen -= APP0_DATA_LEN;
00661     if (totallen !=
00662     ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3))
00663       TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
00664   } else if (datalen >= 6 &&
00665       GETJOCTET(data[0]) == 0x4A &&
00666       GETJOCTET(data[1]) == 0x46 &&
00667       GETJOCTET(data[2]) == 0x58 &&
00668       GETJOCTET(data[3]) == 0x58 &&
00669       GETJOCTET(data[4]) == 0) {
00670     /* Found JFIF "JFXX" extension APP0 marker */
00671     /* The library doesn't actually do anything with these,
00672      * but we try to produce a helpful trace message.
00673      */
00674     switch (GETJOCTET(data[5])) {
00675     case 0x10:
00676       TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
00677       break;
00678     case 0x11:
00679       TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
00680       break;
00681     case 0x13:
00682       TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
00683       break;
00684     default:
00685       TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
00686            GETJOCTET(data[5]), (int) totallen);
00687       break;
00688     }
00689   } else {
00690     /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
00691     TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
00692   }
00693 }
00694 
00695 
00696 LOCAL(void)
00697 examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data,
00698            unsigned int datalen, INT32 remaining)
00699 /* Examine first few bytes from an APP14.
00700  * Take appropriate action if it is an Adobe marker.
00701  * datalen is # of bytes at data[], remaining is length of rest of marker data.
00702  */
00703 {
00704   unsigned int version, flags0, flags1, transform;
00705 
00706   if (datalen >= APP14_DATA_LEN &&
00707       GETJOCTET(data[0]) == 0x41 &&
00708       GETJOCTET(data[1]) == 0x64 &&
00709       GETJOCTET(data[2]) == 0x6F &&
00710       GETJOCTET(data[3]) == 0x62 &&
00711       GETJOCTET(data[4]) == 0x65) {
00712     /* Found Adobe APP14 marker */
00713     version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
00714     flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
00715     flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
00716     transform = GETJOCTET(data[11]);
00717     TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
00718     cinfo->saw_Adobe_marker = TRUE;
00719     cinfo->Adobe_transform = (UINT8) transform;
00720   } else {
00721     /* Start of APP14 does not match "Adobe", or too short */
00722     TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
00723   }
00724 }
00725 
00726 
00727 METHODDEF(boolean)
00728 get_interesting_appn (j_decompress_ptr cinfo)
00729 /* Process an APP0 or APP14 marker without saving it */
00730 {
00731   INT32 length;
00732   JOCTET b[APPN_DATA_LEN];
00733   unsigned int i, numtoread;
00734   INPUT_VARS(cinfo);
00735 
00736   INPUT_2BYTES(cinfo, length, return FALSE);
00737   length -= 2;
00738 
00739   /* get the interesting part of the marker data */
00740   if (length >= APPN_DATA_LEN)
00741     numtoread = APPN_DATA_LEN;
00742   else if (length > 0)
00743     numtoread = (unsigned int) length;
00744   else
00745     numtoread = 0;
00746   for (i = 0; i < numtoread; i++)
00747     INPUT_BYTE(cinfo, b[i], return FALSE);
00748   length -= numtoread;
00749 
00750   /* process it */
00751   switch (cinfo->unread_marker) {
00752   case M_APP0:
00753     examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length);
00754     break;
00755   case M_APP14:
00756     examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length);
00757     break;
00758   default:
00759     /* can't get here unless jpeg_save_markers chooses wrong processor */
00760     ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
00761     break;
00762   }
00763 
00764   /* skip any remaining data -- could be lots */
00765   INPUT_SYNC(cinfo);
00766   if (length > 0)
00767     (*cinfo->src->skip_input_data) (cinfo, (long) length);
00768 
00769   return TRUE;
00770 }
00771 
00772 
00773 #ifdef SAVE_MARKERS_SUPPORTED
00774 
00775 METHODDEF(boolean)
00776 save_marker (j_decompress_ptr cinfo)
00777 /* Save an APPn or COM marker into the marker list */
00778 {
00779   my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
00780   jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
00781   unsigned int bytes_read, data_length;
00782   JOCTET FAR * data;
00783   INT32 length = 0;
00784   INPUT_VARS(cinfo);
00785 
00786   if (cur_marker == NULL) {
00787     /* begin reading a marker */
00788     INPUT_2BYTES(cinfo, length, return FALSE);
00789     length -= 2;
00790     if (length >= 0) {      /* watch out for bogus length word */
00791       /* figure out how much we want to save */
00792       unsigned int limit;
00793       if (cinfo->unread_marker == (int) M_COM)
00794     limit = marker->length_limit_COM;
00795       else
00796     limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0];
00797       if ((unsigned int) length < limit)
00798     limit = (unsigned int) length;
00799       /* allocate and initialize the marker item */
00800       cur_marker = (jpeg_saved_marker_ptr)
00801     (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00802                     SIZEOF(struct jpeg_marker_struct) + limit);
00803       cur_marker->next = NULL;
00804       cur_marker->marker = (UINT8) cinfo->unread_marker;
00805       cur_marker->original_length = (unsigned int) length;
00806       cur_marker->data_length = limit;
00807       /* data area is just beyond the jpeg_marker_struct */
00808       data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1);
00809       marker->cur_marker = cur_marker;
00810       marker->bytes_read = 0;
00811       bytes_read = 0;
00812       data_length = limit;
00813     } else {
00814       /* deal with bogus length word */
00815       bytes_read = data_length = 0;
00816       data = NULL;
00817     }
00818   } else {
00819     /* resume reading a marker */
00820     bytes_read = marker->bytes_read;
00821     data_length = cur_marker->data_length;
00822     data = cur_marker->data + bytes_read;
00823   }
00824 
00825   while (bytes_read < data_length) {
00826     INPUT_SYNC(cinfo);      /* move the restart point to here */
00827     marker->bytes_read = bytes_read;
00828     /* If there's not at least one byte in buffer, suspend */
00829     MAKE_BYTE_AVAIL(cinfo, return FALSE);
00830     /* Copy bytes with reasonable rapidity */
00831     while (bytes_read < data_length && bytes_in_buffer > 0) {
00832       *data++ = *next_input_byte++;
00833       bytes_in_buffer--;
00834       bytes_read++;
00835     }
00836   }
00837 
00838   /* Done reading what we want to read */
00839   if (cur_marker != NULL) { /* will be NULL if bogus length word */
00840     /* Add new marker to end of list */
00841     if (cinfo->marker_list == NULL) {
00842       cinfo->marker_list = cur_marker;
00843     } else {
00844       jpeg_saved_marker_ptr prev = cinfo->marker_list;
00845       while (prev->next != NULL)
00846     prev = prev->next;
00847       prev->next = cur_marker;
00848     }
00849     /* Reset pointer & calc remaining data length */
00850     data = cur_marker->data;
00851     length = cur_marker->original_length - data_length;
00852   }
00853   /* Reset to initial state for next marker */
00854   marker->cur_marker = NULL;
00855 
00856   /* Process the marker if interesting; else just make a generic trace msg */
00857   switch (cinfo->unread_marker) {
00858   case M_APP0:
00859     examine_app0(cinfo, data, data_length, length);
00860     break;
00861   case M_APP14:
00862     examine_app14(cinfo, data, data_length, length);
00863     break;
00864   default:
00865     TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
00866          (int) (data_length + length));
00867     break;
00868   }
00869 
00870   /* skip any remaining data -- could be lots */
00871   INPUT_SYNC(cinfo);        /* do before skip_input_data */
00872   if (length > 0)
00873     (*cinfo->src->skip_input_data) (cinfo, (long) length);
00874 
00875   return TRUE;
00876 }
00877 
00878 #endif /* SAVE_MARKERS_SUPPORTED */
00879 
00880 
00881 METHODDEF(boolean)
00882 skip_variable (j_decompress_ptr cinfo)
00883 /* Skip over an unknown or uninteresting variable-length marker */
00884 {
00885   INT32 length;
00886   INPUT_VARS(cinfo);
00887 
00888   INPUT_2BYTES(cinfo, length, return FALSE);
00889   length -= 2;
00890   
00891   TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);
00892 
00893   INPUT_SYNC(cinfo);        /* do before skip_input_data */
00894   if (length > 0)
00895     (*cinfo->src->skip_input_data) (cinfo, (long) length);
00896 
00897   return TRUE;
00898 }
00899 
00900 
00901 /*
00902  * Find the next JPEG marker, save it in cinfo->unread_marker.
00903  * Returns FALSE if had to suspend before reaching a marker;
00904  * in that case cinfo->unread_marker is unchanged.
00905  *
00906  * Note that the result might not be a valid marker code,
00907  * but it will never be 0 or FF.
00908  */
00909 
00910 LOCAL(boolean)
00911 next_marker (j_decompress_ptr cinfo)
00912 {
00913   int c;
00914   INPUT_VARS(cinfo);
00915 
00916   for (;;) {
00917     INPUT_BYTE(cinfo, c, return FALSE);
00918     /* Skip any non-FF bytes.
00919      * This may look a bit inefficient, but it will not occur in a valid file.
00920      * We sync after each discarded byte so that a suspending data source
00921      * can discard the byte from its buffer.
00922      */
00923     while (c != 0xFF) {
00924       cinfo->marker->discarded_bytes++;
00925       INPUT_SYNC(cinfo);
00926       INPUT_BYTE(cinfo, c, return FALSE);
00927     }
00928     /* This loop swallows any duplicate FF bytes.  Extra FFs are legal as
00929      * pad bytes, so don't count them in discarded_bytes.  We assume there
00930      * will not be so many consecutive FF bytes as to overflow a suspending
00931      * data source's input buffer.
00932      */
00933     do {
00934       INPUT_BYTE(cinfo, c, return FALSE);
00935     } while (c == 0xFF);
00936     if (c != 0)
00937       break;            /* found a valid marker, exit loop */
00938     /* Reach here if we found a stuffed-zero data sequence (FF/00).
00939      * Discard it and loop back to try again.
00940      */
00941     cinfo->marker->discarded_bytes += 2;
00942     INPUT_SYNC(cinfo);
00943   }
00944 
00945   if (cinfo->marker->discarded_bytes != 0) {
00946     WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c);
00947     cinfo->marker->discarded_bytes = 0;
00948   }
00949 
00950   cinfo->unread_marker = c;
00951 
00952   INPUT_SYNC(cinfo);
00953   return TRUE;
00954 }
00955 
00956 
00957 LOCAL(boolean)
00958 first_marker (j_decompress_ptr cinfo)
00959 /* Like next_marker, but used to obtain the initial SOI marker. */
00960 /* For this marker, we do not allow preceding garbage or fill; otherwise,
00961  * we might well scan an entire input file before realizing it ain't JPEG.
00962  * If an application wants to process non-JFIF files, it must seek to the
00963  * SOI before calling the JPEG library.
00964  */
00965 {
00966   int c, c2;
00967   INPUT_VARS(cinfo);
00968 
00969   INPUT_BYTE(cinfo, c, return FALSE);
00970   INPUT_BYTE(cinfo, c2, return FALSE);
00971   if (c != 0xFF || c2 != (int) M_SOI)
00972     ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
00973 
00974   cinfo->unread_marker = c2;
00975 
00976   INPUT_SYNC(cinfo);
00977   return TRUE;
00978 }
00979 
00980 
00981 /*
00982  * Read markers until SOS or EOI.
00983  *
00984  * Returns same codes as are defined for jpeg_consume_input:
00985  * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
00986  *
00987  * Note: This function may return a pseudo SOS marker (with zero
00988  * component number) for treat by input controller's consume_input.
00989  * consume_input itself should filter out (skip) the pseudo marker
00990  * after processing for the caller.
00991  */
00992 
00993 METHODDEF(int)
00994 read_markers (j_decompress_ptr cinfo)
00995 {
00996   /* Outer loop repeats once for each marker. */
00997   for (;;) {
00998     /* Collect the marker proper, unless we already did. */
00999     /* NB: first_marker() enforces the requirement that SOI appear first. */
01000     if (cinfo->unread_marker == 0) {
01001       if (! cinfo->marker->saw_SOI) {
01002     if (! first_marker(cinfo))
01003       return JPEG_SUSPENDED;
01004       } else {
01005     if (! next_marker(cinfo))
01006       return JPEG_SUSPENDED;
01007       }
01008     }
01009     /* At this point cinfo->unread_marker contains the marker code and the
01010      * input point is just past the marker proper, but before any parameters.
01011      * A suspension will cause us to return with this state still true.
01012      */
01013     switch (cinfo->unread_marker) {
01014     case M_SOI:
01015       if (! get_soi(cinfo))
01016     return JPEG_SUSPENDED;
01017       break;
01018 
01019     case M_SOF0:        /* Baseline */
01020       if (! get_sof(cinfo, TRUE, FALSE, FALSE))
01021     return JPEG_SUSPENDED;
01022       break;
01023 
01024     case M_SOF1:        /* Extended sequential, Huffman */
01025       if (! get_sof(cinfo, FALSE, FALSE, FALSE))
01026     return JPEG_SUSPENDED;
01027       break;
01028 
01029     case M_SOF2:        /* Progressive, Huffman */
01030       if (! get_sof(cinfo, FALSE, TRUE, FALSE))
01031     return JPEG_SUSPENDED;
01032       break;
01033 
01034     case M_SOF9:        /* Extended sequential, arithmetic */
01035       if (! get_sof(cinfo, FALSE, FALSE, TRUE))
01036     return JPEG_SUSPENDED;
01037       break;
01038 
01039     case M_SOF10:       /* Progressive, arithmetic */
01040       if (! get_sof(cinfo, FALSE, TRUE, TRUE))
01041     return JPEG_SUSPENDED;
01042       break;
01043 
01044     /* Currently unsupported SOFn types */
01045     case M_SOF3:        /* Lossless, Huffman */
01046     case M_SOF5:        /* Differential sequential, Huffman */
01047     case M_SOF6:        /* Differential progressive, Huffman */
01048     case M_SOF7:        /* Differential lossless, Huffman */
01049     case M_JPG:         /* Reserved for JPEG extensions */
01050     case M_SOF11:       /* Lossless, arithmetic */
01051     case M_SOF13:       /* Differential sequential, arithmetic */
01052     case M_SOF14:       /* Differential progressive, arithmetic */
01053     case M_SOF15:       /* Differential lossless, arithmetic */
01054       ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker);
01055       break;
01056 
01057     case M_SOS:
01058       if (! get_sos(cinfo))
01059     return JPEG_SUSPENDED;
01060       cinfo->unread_marker = 0; /* processed the marker */
01061       return JPEG_REACHED_SOS;
01062     
01063     case M_EOI:
01064       TRACEMS(cinfo, 1, JTRC_EOI);
01065       cinfo->unread_marker = 0; /* processed the marker */
01066       return JPEG_REACHED_EOI;
01067       
01068     case M_DAC:
01069       if (! get_dac(cinfo))
01070     return JPEG_SUSPENDED;
01071       break;
01072       
01073     case M_DHT:
01074       if (! get_dht(cinfo))
01075     return JPEG_SUSPENDED;
01076       break;
01077       
01078     case M_DQT:
01079       if (! get_dqt(cinfo))
01080     return JPEG_SUSPENDED;
01081       break;
01082       
01083     case M_DRI:
01084       if (! get_dri(cinfo))
01085     return JPEG_SUSPENDED;
01086       break;
01087       
01088     case M_APP0:
01089     case M_APP1:
01090     case M_APP2:
01091     case M_APP3:
01092     case M_APP4:
01093     case M_APP5:
01094     case M_APP6:
01095     case M_APP7:
01096     case M_APP8:
01097     case M_APP9:
01098     case M_APP10:
01099     case M_APP11:
01100     case M_APP12:
01101     case M_APP13:
01102     case M_APP14:
01103     case M_APP15:
01104       if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[
01105         cinfo->unread_marker - (int) M_APP0]) (cinfo))
01106     return JPEG_SUSPENDED;
01107       break;
01108       
01109     case M_COM:
01110       if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo))
01111     return JPEG_SUSPENDED;
01112       break;
01113 
01114     case M_RST0:        /* these are all parameterless */
01115     case M_RST1:
01116     case M_RST2:
01117     case M_RST3:
01118     case M_RST4:
01119     case M_RST5:
01120     case M_RST6:
01121     case M_RST7:
01122     case M_TEM:
01123       TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker);
01124       break;
01125 
01126     case M_DNL:         /* Ignore DNL ... perhaps the wrong thing */
01127       if (! skip_variable(cinfo))
01128     return JPEG_SUSPENDED;
01129       break;
01130 
01131     default:            /* must be DHP, EXP, JPGn, or RESn */
01132       /* For now, we treat the reserved markers as fatal errors since they are
01133        * likely to be used to signal incompatible JPEG Part 3 extensions.
01134        * Once the JPEG 3 version-number marker is well defined, this code
01135        * ought to change!
01136        */
01137       ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
01138       break;
01139     }
01140     /* Successfully processed marker, so reset state variable */
01141     cinfo->unread_marker = 0;
01142   } /* end loop */
01143 }
01144 
01145 
01146 /*
01147  * Read a restart marker, which is expected to appear next in the datastream;
01148  * if the marker is not there, take appropriate recovery action.
01149  * Returns FALSE if suspension is required.
01150  *
01151  * This is called by the entropy decoder after it has read an appropriate
01152  * number of MCUs.  cinfo->unread_marker may be nonzero if the entropy decoder
01153  * has already read a marker from the data source.  Under normal conditions
01154  * cinfo->unread_marker will be reset to 0 before returning; if not reset,
01155  * it holds a marker which the decoder will be unable to read past.
01156  */
01157 
01158 METHODDEF(boolean)
01159 read_restart_marker (j_decompress_ptr cinfo)
01160 {
01161   /* Obtain a marker unless we already did. */
01162   /* Note that next_marker will complain if it skips any data. */
01163   if (cinfo->unread_marker == 0) {
01164     if (! next_marker(cinfo))
01165       return FALSE;
01166   }
01167 
01168   if (cinfo->unread_marker ==
01169       ((int) M_RST0 + cinfo->marker->next_restart_num)) {
01170     /* Normal case --- swallow the marker and let entropy decoder continue */
01171     TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
01172     cinfo->unread_marker = 0;
01173   } else {
01174     /* Uh-oh, the restart markers have been messed up. */
01175     /* Let the data source manager determine how to resync. */
01176     if (! (*cinfo->src->resync_to_restart) (cinfo,
01177                         cinfo->marker->next_restart_num))
01178       return FALSE;
01179   }
01180 
01181   /* Update next-restart state */
01182   cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7;
01183 
01184   return TRUE;
01185 }
01186 
01187 
01188 /*
01189  * This is the default resync_to_restart method for data source managers
01190  * to use if they don't have any better approach.  Some data source managers
01191  * may be able to back up, or may have additional knowledge about the data
01192  * which permits a more intelligent recovery strategy; such managers would
01193  * presumably supply their own resync method.
01194  *
01195  * read_restart_marker calls resync_to_restart if it finds a marker other than
01196  * the restart marker it was expecting.  (This code is *not* used unless
01197  * a nonzero restart interval has been declared.)  cinfo->unread_marker is
01198  * the marker code actually found (might be anything, except 0 or FF).
01199  * The desired restart marker number (0..7) is passed as a parameter.
01200  * This routine is supposed to apply whatever error recovery strategy seems
01201  * appropriate in order to position the input stream to the next data segment.
01202  * Note that cinfo->unread_marker is treated as a marker appearing before
01203  * the current data-source input point; usually it should be reset to zero
01204  * before returning.
01205  * Returns FALSE if suspension is required.
01206  *
01207  * This implementation is substantially constrained by wanting to treat the
01208  * input as a data stream; this means we can't back up.  Therefore, we have
01209  * only the following actions to work with:
01210  *   1. Simply discard the marker and let the entropy decoder resume at next
01211  *      byte of file.
01212  *   2. Read forward until we find another marker, discarding intervening
01213  *      data.  (In theory we could look ahead within the current bufferload,
01214  *      without having to discard data if we don't find the desired marker.
01215  *      This idea is not implemented here, in part because it makes behavior
01216  *      dependent on buffer size and chance buffer-boundary positions.)
01217  *   3. Leave the marker unread (by failing to zero cinfo->unread_marker).
01218  *      This will cause the entropy decoder to process an empty data segment,
01219  *      inserting dummy zeroes, and then we will reprocess the marker.
01220  *
01221  * #2 is appropriate if we think the desired marker lies ahead, while #3 is
01222  * appropriate if the found marker is a future restart marker (indicating
01223  * that we have missed the desired restart marker, probably because it got
01224  * corrupted).
01225  * We apply #2 or #3 if the found marker is a restart marker no more than
01226  * two counts behind or ahead of the expected one.  We also apply #2 if the
01227  * found marker is not a legal JPEG marker code (it's certainly bogus data).
01228  * If the found marker is a restart marker more than 2 counts away, we do #1
01229  * (too much risk that the marker is erroneous; with luck we will be able to
01230  * resync at some future point).
01231  * For any valid non-restart JPEG marker, we apply #3.  This keeps us from
01232  * overrunning the end of a scan.  An implementation limited to single-scan
01233  * files might find it better to apply #2 for markers other than EOI, since
01234  * any other marker would have to be bogus data in that case.
01235  */
01236 
01237 GLOBAL(boolean)
01238 jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
01239 {
01240   int marker = cinfo->unread_marker;
01241   int action = 1;
01242   
01243   /* Always put up a warning. */
01244   WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
01245   
01246   /* Outer loop handles repeated decision after scanning forward. */
01247   for (;;) {
01248     if (marker < (int) M_SOF0)
01249       action = 2;       /* invalid marker */
01250     else if (marker < (int) M_RST0 || marker > (int) M_RST7)
01251       action = 3;       /* valid non-restart marker */
01252     else {
01253       if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
01254       marker == ((int) M_RST0 + ((desired+2) & 7)))
01255     action = 3;     /* one of the next two expected restarts */
01256       else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
01257            marker == ((int) M_RST0 + ((desired-2) & 7)))
01258     action = 2;     /* a prior restart, so advance */
01259       else
01260     action = 1;     /* desired restart or too far away */
01261     }
01262     TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
01263     switch (action) {
01264     case 1:
01265       /* Discard marker and let entropy decoder resume processing. */
01266       cinfo->unread_marker = 0;
01267       return TRUE;
01268     case 2:
01269       /* Scan to the next marker, and repeat the decision loop. */
01270       if (! next_marker(cinfo))
01271     return FALSE;
01272       marker = cinfo->unread_marker;
01273       break;
01274     case 3:
01275       /* Return without advancing past this marker. */
01276       /* Entropy decoder will be forced to process an empty segment. */
01277       return TRUE;
01278     }
01279   } /* end loop */
01280 }
01281 
01282 
01283 /*
01284  * Reset marker processing state to begin a fresh datastream.
01285  */
01286 
01287 METHODDEF(void)
01288 reset_marker_reader (j_decompress_ptr cinfo)
01289 {
01290   my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
01291 
01292   cinfo->comp_info = NULL;      /* until allocated by get_sof */
01293   cinfo->input_scan_number = 0;     /* no SOS seen yet */
01294   cinfo->unread_marker = 0;     /* no pending marker */
01295   marker->pub.saw_SOI = FALSE;      /* set internal state too */
01296   marker->pub.saw_SOF = FALSE;
01297   marker->pub.discarded_bytes = 0;
01298   marker->cur_marker = NULL;
01299 }
01300 
01301 
01302 /*
01303  * Initialize the marker reader module.
01304  * This is called only once, when the decompression object is created.
01305  */
01306 
01307 GLOBAL(void)
01308 jinit_marker_reader (j_decompress_ptr cinfo)
01309 {
01310   my_marker_ptr marker;
01311   int i;
01312 
01313   /* Create subobject in permanent pool */
01314   marker = (my_marker_ptr)
01315     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
01316                 SIZEOF(my_marker_reader));
01317   cinfo->marker = (struct jpeg_marker_reader *) marker;
01318   /* Initialize public method pointers */
01319   marker->pub.reset_marker_reader = reset_marker_reader;
01320   marker->pub.read_markers = read_markers;
01321   marker->pub.read_restart_marker = read_restart_marker;
01322   /* Initialize COM/APPn processing.
01323    * By default, we examine and then discard APP0 and APP14,
01324    * but simply discard COM and all other APPn.
01325    */
01326   marker->process_COM = skip_variable;
01327   marker->length_limit_COM = 0;
01328   for (i = 0; i < 16; i++) {
01329     marker->process_APPn[i] = skip_variable;
01330     marker->length_limit_APPn[i] = 0;
01331   }
01332   marker->process_APPn[0] = get_interesting_appn;
01333   marker->process_APPn[14] = get_interesting_appn;
01334   /* Reset marker processing state */
01335   reset_marker_reader(cinfo);
01336 }
01337 
01338 
01339 /*
01340  * Control saving of COM and APPn markers into marker_list.
01341  */
01342 
01343 #ifdef SAVE_MARKERS_SUPPORTED
01344 
01345 GLOBAL(void)
01346 jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
01347            unsigned int length_limit)
01348 {
01349   my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
01350   long maxlength;
01351   jpeg_marker_parser_method processor;
01352 
01353   /* Length limit mustn't be larger than what we can allocate
01354    * (should only be a concern in a 16-bit environment).
01355    */
01356   maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct);
01357   if (((long) length_limit) > maxlength)
01358     length_limit = (unsigned int) maxlength;
01359 
01360   /* Choose processor routine to use.
01361    * APP0/APP14 have special requirements.
01362    */
01363   if (length_limit) {
01364     processor = save_marker;
01365     /* If saving APP0/APP14, save at least enough for our internal use. */
01366     if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN)
01367       length_limit = APP0_DATA_LEN;
01368     else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN)
01369       length_limit = APP14_DATA_LEN;
01370   } else {
01371     processor = skip_variable;
01372     /* If discarding APP0/APP14, use our regular on-the-fly processor. */
01373     if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14)
01374       processor = get_interesting_appn;
01375   }
01376 
01377   if (marker_code == (int) M_COM) {
01378     marker->process_COM = processor;
01379     marker->length_limit_COM = length_limit;
01380   } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) {
01381     marker->process_APPn[marker_code - (int) M_APP0] = processor;
01382     marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit;
01383   } else
01384     ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
01385 }
01386 
01387 #endif /* SAVE_MARKERS_SUPPORTED */
01388 
01389 
01390 /*
01391  * Install a special processing method for COM or APPn markers.
01392  */
01393 
01394 GLOBAL(void)
01395 jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
01396                jpeg_marker_parser_method routine)
01397 {
01398   my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
01399 
01400   if (marker_code == (int) M_COM)
01401     marker->process_COM = routine;
01402   else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15)
01403     marker->process_APPn[marker_code - (int) M_APP0] = routine;
01404   else
01405     ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
01406 }

Generated on Sun May 27 2012 04:19:25 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.