4  * Copyright (C) 1991-1998, Thomas G. Lane. 
   5  * This file is part of the Independent JPEG Group's software. 
   6  * For conditions of distribution and use, see the accompanying README file. 
   8  * This file contains routines to decode JPEG datastream markers. 
   9  * Most of the complexity arises from our desire to support input 
  10  * suspension: if not all of the data for a marker is available, 
  11  * we must exit back to the application.  On resumption, we reprocess 
  15 #define JPEG_INTERNALS 
  20 typedef enum {                  /* JPEG marker codes */ 
  91   struct jpeg_marker_reader pub
; /* public fields */ 
  93   /* Application-overridable marker processing methods */ 
  94   jpeg_marker_parser_method process_COM
; 
  95   jpeg_marker_parser_method process_APPn
[16]; 
  97   /* Limit on marker data length to save for each marker type */ 
  98   unsigned int length_limit_COM
; 
  99   unsigned int length_limit_APPn
[16]; 
 101   /* Status of COM/APPn marker saving */ 
 102   jpeg_saved_marker_ptr cur_marker
;     /* NULL if not processing a marker */ 
 103   unsigned int bytes_read
;              /* data bytes read so far in marker */ 
 104   /* Note: cur_marker is not linked into marker_list until it's all read. */ 
 107 typedef my_marker_reader 
* my_marker_ptr
; 
 111  * Macros for fetching data from the data source module. 
 113  * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect 
 114  * the current restart point; we update them only when we have reached a 
 115  * suitable place to restart if a suspension occurs. 
 118 /* Declare and initialize local copies of input pointer/count */ 
 119 #define INPUT_VARS(cinfo)  \ 
 120         struct jpeg_source_mgr * datasrc = (cinfo)->src;  \ 
 121         const JOCTET * next_input_byte = datasrc->next_input_byte;  \ 
 122         size_t bytes_in_buffer = datasrc->bytes_in_buffer 
 124 /* Unload the local copies --- do this only at a restart boundary */ 
 125 #define INPUT_SYNC(cinfo)  \ 
 126         ( datasrc->next_input_byte = next_input_byte,  \ 
 127           datasrc->bytes_in_buffer = bytes_in_buffer ) 
 129 /* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ 
 130 #define INPUT_RELOAD(cinfo)  \ 
 131         ( next_input_byte = datasrc->next_input_byte,  \ 
 132           bytes_in_buffer = datasrc->bytes_in_buffer ) 
 134 /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. 
 135  * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, 
 136  * but we must reload the local copies after a successful fill. 
 138 #define MAKE_BYTE_AVAIL(cinfo,action)  \ 
 139         if (bytes_in_buffer == 0) {  \ 
 140           if (! (*datasrc->fill_input_buffer) (cinfo))  \ 
 142           INPUT_RELOAD(cinfo);  \ 
 145 /* Read a byte into variable V. 
 146  * If must suspend, take the specified action (typically "return FALSE"). 
 148 #define INPUT_BYTE(cinfo,V,action)  \ 
 149         MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ 
 151                   V = GETJOCTET(*next_input_byte++); ) 
 153 /* As above, but read two bytes interpreted as an unsigned 16-bit integer. 
 154  * V should be declared unsigned int or perhaps INT32. 
 156 #define INPUT_2BYTES(cinfo,V,action)  \ 
 157         MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ 
 159                   V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ 
 160                   MAKE_BYTE_AVAIL(cinfo,action); \ 
 162                   V += GETJOCTET(*next_input_byte++); ) 
 166  * Routines to process JPEG markers. 
 168  * Entry condition: JPEG marker itself has been read and its code saved 
 169  *   in cinfo->unread_marker; input restart point is just after the marker. 
 171  * Exit: if return TRUE, have read and processed any parameters, and have 
 172  *   updated the restart point to point after the parameters. 
 173  *   If return FALSE, was forced to suspend before reaching end of 
 174  *   marker parameters; restart point has not been moved.  Same routine 
 175  *   will be called again after application supplies more input data. 
 177  * This approach to suspension assumes that all of a marker's parameters 
 178  * can fit into a single input bufferload.  This should hold for "normal" 
 179  * markers.  Some COM/APPn markers might have large parameter segments 
 180  * that might not fit.  If we are simply dropping such a marker, we use 
 181  * skip_input_data to get past it, and thereby put the problem on the 
 182  * source manager's shoulders.  If we are saving the marker's contents 
 183  * into memory, we use a slightly different convention: when forced to 
 184  * suspend, the marker processor updates the restart point to the end of 
 185  * what it's consumed (ie, the end of the buffer) before returning FALSE. 
 186  * On resumption, cinfo->unread_marker still contains the marker code, 
 187  * but the data source will point to the next chunk of marker data. 
 188  * The marker processor must retain internal state to deal with this. 
 190  * Note that we don't bother to avoid duplicate trace messages if a 
 191  * suspension occurs within marker parameters.  Other side effects 
 197 get_soi (j_decompress_ptr cinfo
) 
 198 /* Process an SOI marker */ 
 202   TRACEMS(cinfo
, 1, JTRC_SOI
); 
 204   if (cinfo
->marker
->saw_SOI
) 
 205     ERREXIT(cinfo
, JERR_SOI_DUPLICATE
); 
 207   /* Reset all parameters that are defined to be reset by SOI */ 
 209   for (i 
= 0; i 
< NUM_ARITH_TBLS
; i
++) { 
 210     cinfo
->arith_dc_L
[i
] = 0; 
 211     cinfo
->arith_dc_U
[i
] = 1; 
 212     cinfo
->arith_ac_K
[i
] = 5; 
 214   cinfo
->restart_interval 
= 0; 
 216   /* Set initial assumptions for colorspace etc */ 
 218   cinfo
->jpeg_color_space 
= JCS_UNKNOWN
; 
 219   cinfo
->CCIR601_sampling 
= FALSE
; /* Assume non-CCIR sampling??? */ 
 221   cinfo
->saw_JFIF_marker 
= FALSE
; 
 222   cinfo
->JFIF_major_version 
= 1; /* set default JFIF APP0 values */ 
 223   cinfo
->JFIF_minor_version 
= 1; 
 224   cinfo
->density_unit 
= 0; 
 225   cinfo
->X_density 
= 1; 
 226   cinfo
->Y_density 
= 1; 
 227   cinfo
->saw_Adobe_marker 
= FALSE
; 
 228   cinfo
->Adobe_transform 
= 0; 
 230   cinfo
->marker
->saw_SOI 
= TRUE
; 
 237 get_sof (j_decompress_ptr cinfo
, boolean is_prog
, boolean is_arith
) 
 238 /* Process a SOFn marker */ 
 242   jpeg_component_info 
* compptr
; 
 245   cinfo
->progressive_mode 
= is_prog
; 
 246   cinfo
->arith_code 
= is_arith
; 
 248   INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 250   INPUT_BYTE(cinfo
, cinfo
->data_precision
, return FALSE
); 
 251   INPUT_2BYTES(cinfo
, cinfo
->image_height
, return FALSE
); 
 252   INPUT_2BYTES(cinfo
, cinfo
->image_width
, return FALSE
); 
 253   INPUT_BYTE(cinfo
, cinfo
->num_components
, return FALSE
); 
 257   TRACEMS4(cinfo
, 1, JTRC_SOF
, cinfo
->unread_marker
, 
 258            (int) cinfo
->image_width
, (int) cinfo
->image_height
, 
 259            cinfo
->num_components
); 
 261   if (cinfo
->marker
->saw_SOF
) 
 262     ERREXIT(cinfo
, JERR_SOF_DUPLICATE
); 
 264   /* We don't support files in which the image height is initially specified */ 
 265   /* as 0 and is later redefined by DNL.  As long as we have to check that,  */ 
 266   /* might as well have a general sanity check. */ 
 267   if (cinfo
->image_height 
<= 0 || cinfo
->image_width 
<= 0 
 268       || cinfo
->num_components 
<= 0) 
 269     ERREXIT(cinfo
, JERR_EMPTY_IMAGE
); 
 271   if (length 
!= (cinfo
->num_components 
* 3)) 
 272     ERREXIT(cinfo
, JERR_BAD_LENGTH
); 
 274   if (cinfo
->comp_info 
== NULL
) /* do only once, even if suspend */ 
 275     cinfo
->comp_info 
= (jpeg_component_info 
*) (*cinfo
->mem
->alloc_small
) 
 276                         ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 277                          cinfo
->num_components 
* SIZEOF(jpeg_component_info
)); 
 279   for (ci 
= 0, compptr 
= cinfo
->comp_info
; ci 
< cinfo
->num_components
; 
 281     compptr
->component_index 
= ci
; 
 282     INPUT_BYTE(cinfo
, compptr
->component_id
, return FALSE
); 
 283     INPUT_BYTE(cinfo
, c
, return FALSE
); 
 284     compptr
->h_samp_factor 
= (c 
>> 4) & 15; 
 285     compptr
->v_samp_factor 
= (c     
) & 15; 
 286     INPUT_BYTE(cinfo
, compptr
->quant_tbl_no
, return FALSE
); 
 288     TRACEMS4(cinfo
, 1, JTRC_SOF_COMPONENT
, 
 289              compptr
->component_id
, compptr
->h_samp_factor
, 
 290              compptr
->v_samp_factor
, compptr
->quant_tbl_no
); 
 293   cinfo
->marker
->saw_SOF 
= TRUE
; 
 301 get_sos (j_decompress_ptr cinfo
) 
 302 /* Process a SOS marker */ 
 306   jpeg_component_info 
* compptr
; 
 309   if (! cinfo
->marker
->saw_SOF
) 
 310     ERREXIT(cinfo
, JERR_SOS_NO_SOF
); 
 312   INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 314   INPUT_BYTE(cinfo
, n
, return FALSE
); /* Number of components */ 
 316   TRACEMS1(cinfo
, 1, JTRC_SOS
, n
); 
 318   if (length 
!= (n 
* 2 + 6) || n 
< 1 || n 
> MAX_COMPS_IN_SCAN
) 
 319     ERREXIT(cinfo
, JERR_BAD_LENGTH
); 
 321   cinfo
->comps_in_scan 
= n
; 
 323   /* Collect the component-spec parameters */ 
 325   for (i 
= 0; i 
< n
; i
++) { 
 326     INPUT_BYTE(cinfo
, cc
, return FALSE
); 
 327     INPUT_BYTE(cinfo
, c
, return FALSE
); 
 329     for (ci 
= 0, compptr 
= cinfo
->comp_info
; ci 
< cinfo
->num_components
; 
 331       if (cc 
== compptr
->component_id
) 
 335     ERREXIT1(cinfo
, JERR_BAD_COMPONENT_ID
, cc
); 
 339     cinfo
->cur_comp_info
[i
] = compptr
; 
 340     compptr
->dc_tbl_no 
= (c 
>> 4) & 15; 
 341     compptr
->ac_tbl_no 
= (c     
) & 15; 
 343     TRACEMS3(cinfo
, 1, JTRC_SOS_COMPONENT
, cc
, 
 344              compptr
->dc_tbl_no
, compptr
->ac_tbl_no
); 
 347   /* Collect the additional scan parameters Ss, Se, Ah/Al. */ 
 348   INPUT_BYTE(cinfo
, c
, return FALSE
); 
 350   INPUT_BYTE(cinfo
, c
, return FALSE
); 
 352   INPUT_BYTE(cinfo
, c
, return FALSE
); 
 353   cinfo
->Ah 
= (c 
>> 4) & 15; 
 354   cinfo
->Al 
= (c     
) & 15; 
 356   TRACEMS4(cinfo
, 1, JTRC_SOS_PARAMS
, cinfo
->Ss
, cinfo
->Se
, 
 357            cinfo
->Ah
, cinfo
->Al
); 
 359   /* Prepare to scan data & restart markers */ 
 360   cinfo
->marker
->next_restart_num 
= 0; 
 362   /* Count another SOS marker */ 
 363   cinfo
->input_scan_number
++; 
 370 #ifdef D_ARITH_CODING_SUPPORTED 
 373 get_dac (j_decompress_ptr cinfo
) 
 374 /* Process a DAC marker */ 
 380   INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 384     INPUT_BYTE(cinfo
, index
, return FALSE
); 
 385     INPUT_BYTE(cinfo
, val
, return FALSE
); 
 389     TRACEMS2(cinfo
, 1, JTRC_DAC
, index
, val
); 
 391     if (index 
< 0 || index 
>= (2*NUM_ARITH_TBLS
)) 
 392       ERREXIT1(cinfo
, JERR_DAC_INDEX
, index
); 
 394     if (index 
>= NUM_ARITH_TBLS
) { /* define AC table */ 
 395       cinfo
->arith_ac_K
[index
-NUM_ARITH_TBLS
] = (UINT8
) val
; 
 396     } else {                    /* define DC table */ 
 397       cinfo
->arith_dc_L
[index
] = (UINT8
) (val 
& 0x0F); 
 398       cinfo
->arith_dc_U
[index
] = (UINT8
) (val 
>> 4); 
 399       if (cinfo
->arith_dc_L
[index
] > cinfo
->arith_dc_U
[index
]) 
 400         ERREXIT1(cinfo
, JERR_DAC_VALUE
, val
); 
 405     ERREXIT(cinfo
, JERR_BAD_LENGTH
); 
 411 #else /* ! D_ARITH_CODING_SUPPORTED */ 
 413 #define get_dac(cinfo)  skip_variable(cinfo) 
 415 #endif /* D_ARITH_CODING_SUPPORTED */ 
 419 get_dht (j_decompress_ptr cinfo
) 
 420 /* Process a DHT marker */ 
 429   INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 432   while (length 
> 16) { 
 433     INPUT_BYTE(cinfo
, index
, return FALSE
); 
 435     TRACEMS1(cinfo
, 1, JTRC_DHT
, index
); 
 439     for (i 
= 1; i 
<= 16; i
++) { 
 440       INPUT_BYTE(cinfo
, bits
[i
], return FALSE
); 
 446     TRACEMS8(cinfo
, 2, JTRC_HUFFBITS
, 
 447              bits
[1], bits
[2], bits
[3], bits
[4], 
 448              bits
[5], bits
[6], bits
[7], bits
[8]); 
 449     TRACEMS8(cinfo
, 2, JTRC_HUFFBITS
, 
 450              bits
[9], bits
[10], bits
[11], bits
[12], 
 451              bits
[13], bits
[14], bits
[15], bits
[16]); 
 453     /* Here we just do minimal validation of the counts to avoid walking 
 454      * off the end of our table space.  jdhuff.c will check more carefully. 
 456     if (count 
> 256 || ((JPEG_INT32
) count
) > length
) 
 457       ERREXIT(cinfo
, JERR_BAD_HUFF_TABLE
); 
 459     for (i 
= 0; i 
< count
; i
++) 
 460       INPUT_BYTE(cinfo
, huffval
[i
], return FALSE
); 
 464     if (index 
& 0x10) {         /* AC table definition */ 
 466       htblptr 
= &cinfo
->ac_huff_tbl_ptrs
[index
]; 
 467     } else {                    /* DC table definition */ 
 468       htblptr 
= &cinfo
->dc_huff_tbl_ptrs
[index
]; 
 471     if (index 
< 0 || index 
>= NUM_HUFF_TBLS
) 
 472       ERREXIT1(cinfo
, JERR_DHT_INDEX
, index
); 
 474     if (*htblptr 
== NULL
) 
 475       *htblptr 
= jpeg_alloc_huff_table((j_common_ptr
) cinfo
); 
 477     MEMCOPY((*htblptr
)->bits
, bits
, SIZEOF((*htblptr
)->bits
)); 
 478     MEMCOPY((*htblptr
)->huffval
, huffval
, SIZEOF((*htblptr
)->huffval
)); 
 482     ERREXIT(cinfo
, JERR_BAD_LENGTH
); 
 490 get_dqt (j_decompress_ptr cinfo
) 
 491 /* Process a DQT marker */ 
 496   JQUANT_TBL 
*quant_ptr
; 
 499   INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 503     INPUT_BYTE(cinfo
, n
, return FALSE
); 
 507     TRACEMS2(cinfo
, 1, JTRC_DQT
, n
, prec
); 
 509     if (n 
>= NUM_QUANT_TBLS
) 
 510       ERREXIT1(cinfo
, JERR_DQT_INDEX
, n
); 
 512     if (cinfo
->quant_tbl_ptrs
[n
] == NULL
) 
 513       cinfo
->quant_tbl_ptrs
[n
] = jpeg_alloc_quant_table((j_common_ptr
) cinfo
); 
 514     quant_ptr 
= cinfo
->quant_tbl_ptrs
[n
]; 
 516     for (i 
= 0; i 
< DCTSIZE2
; i
++) { 
 518         INPUT_2BYTES(cinfo
, tmp
, return FALSE
); 
 520         INPUT_BYTE(cinfo
, tmp
, return FALSE
); 
 521       /* We convert the zigzag-order table to natural array order. */ 
 522       quant_ptr
->quantval
[jpeg_natural_order
[i
]] = (UINT16
) tmp
; 
 525     if (cinfo
->err
->trace_level 
>= 2) { 
 526       for (i 
= 0; i 
< DCTSIZE2
; i 
+= 8) { 
 527         TRACEMS8(cinfo
, 2, JTRC_QUANTVALS
, 
 528                  quant_ptr
->quantval
[i
],   quant_ptr
->quantval
[i
+1], 
 529                  quant_ptr
->quantval
[i
+2], quant_ptr
->quantval
[i
+3], 
 530                  quant_ptr
->quantval
[i
+4], quant_ptr
->quantval
[i
+5], 
 531                  quant_ptr
->quantval
[i
+6], quant_ptr
->quantval
[i
+7]); 
 535     length 
-= DCTSIZE2
+1; 
 536     if (prec
) length 
-= DCTSIZE2
; 
 540     ERREXIT(cinfo
, JERR_BAD_LENGTH
); 
 548 get_dri (j_decompress_ptr cinfo
) 
 549 /* Process a DRI marker */ 
 555   INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 558     ERREXIT(cinfo
, JERR_BAD_LENGTH
); 
 560   INPUT_2BYTES(cinfo
, tmp
, return FALSE
); 
 562   TRACEMS1(cinfo
, 1, JTRC_DRI
, tmp
); 
 564   cinfo
->restart_interval 
= tmp
; 
 572  * Routines for processing APPn and COM markers. 
 573  * These are either saved in memory or discarded, per application request. 
 574  * APP0 and APP14 are specially checked to see if they are 
 575  * JFIF and Adobe markers, respectively. 
 578 #define APP0_DATA_LEN   14      /* Length of interesting data in APP0 */ 
 579 #define APP14_DATA_LEN  12      /* Length of interesting data in APP14 */ 
 580 #define APPN_DATA_LEN   14      /* Must be the largest of the above!! */ 
 584 examine_app0 (j_decompress_ptr cinfo
, JOCTET FAR 
* data
, 
 585               unsigned int datalen
, JPEG_INT32 remaining
) 
 586 /* Examine first few bytes from an APP0. 
 587  * Take appropriate action if it is a JFIF marker. 
 588  * datalen is # of bytes at data[], remaining is length of rest of marker data. 
 591   JPEG_INT32 totallen 
= (JPEG_INT32
) datalen 
+ remaining
; 
 593   if (datalen 
>= APP0_DATA_LEN 
&& 
 594       GETJOCTET(data
[0]) == 0x4A && 
 595       GETJOCTET(data
[1]) == 0x46 && 
 596       GETJOCTET(data
[2]) == 0x49 && 
 597       GETJOCTET(data
[3]) == 0x46 && 
 598       GETJOCTET(data
[4]) == 0) { 
 599     /* Found JFIF APP0 marker: save info */ 
 600     cinfo
->saw_JFIF_marker 
= TRUE
; 
 601     cinfo
->JFIF_major_version 
= GETJOCTET(data
[5]); 
 602     cinfo
->JFIF_minor_version 
= GETJOCTET(data
[6]); 
 603     cinfo
->density_unit 
= GETJOCTET(data
[7]); 
 604     cinfo
->X_density 
= (GETJOCTET(data
[8]) << 8) + GETJOCTET(data
[9]); 
 605     cinfo
->Y_density 
= (GETJOCTET(data
[10]) << 8) + GETJOCTET(data
[11]); 
 607      * Major version must be 1, anything else signals an incompatible change. 
 608      * (We used to treat this as an error, but now it's a nonfatal warning, 
 609      * because some bozo at Hijaak couldn't read the spec.) 
 610      * Minor version should be 0..2, but process anyway if newer. 
 612     if (cinfo
->JFIF_major_version 
!= 1) 
 613       WARNMS2(cinfo
, JWRN_JFIF_MAJOR
, 
 614               cinfo
->JFIF_major_version
, cinfo
->JFIF_minor_version
); 
 615     /* Generate trace messages */ 
 616     TRACEMS5(cinfo
, 1, JTRC_JFIF
, 
 617              cinfo
->JFIF_major_version
, cinfo
->JFIF_minor_version
, 
 618              cinfo
->X_density
, cinfo
->Y_density
, cinfo
->density_unit
); 
 619     /* Validate thumbnail dimensions and issue appropriate messages */ 
 620     if (GETJOCTET(data
[12]) | GETJOCTET(data
[13])) 
 621       TRACEMS2(cinfo
, 1, JTRC_JFIF_THUMBNAIL
, 
 622                GETJOCTET(data
[12]), GETJOCTET(data
[13])); 
 623     totallen 
-= APP0_DATA_LEN
; 
 625         ((JPEG_INT32
)GETJOCTET(data
[12]) * (JPEG_INT32
)GETJOCTET(data
[13]) * (JPEG_INT32
) 3)) 
 626       TRACEMS1(cinfo
, 1, JTRC_JFIF_BADTHUMBNAILSIZE
, (int) totallen
); 
 627   } else if (datalen 
>= 6 && 
 628       GETJOCTET(data
[0]) == 0x4A && 
 629       GETJOCTET(data
[1]) == 0x46 && 
 630       GETJOCTET(data
[2]) == 0x58 && 
 631       GETJOCTET(data
[3]) == 0x58 && 
 632       GETJOCTET(data
[4]) == 0) { 
 633     /* Found JFIF "JFXX" extension APP0 marker */ 
 634     /* The library doesn't actually do anything with these, 
 635      * but we try to produce a helpful trace message. 
 637     switch (GETJOCTET(data
[5])) { 
 639       TRACEMS1(cinfo
, 1, JTRC_THUMB_JPEG
, (int) totallen
); 
 642       TRACEMS1(cinfo
, 1, JTRC_THUMB_PALETTE
, (int) totallen
); 
 645       TRACEMS1(cinfo
, 1, JTRC_THUMB_RGB
, (int) totallen
); 
 648       TRACEMS2(cinfo
, 1, JTRC_JFIF_EXTENSION
, 
 649                GETJOCTET(data
[5]), (int) totallen
); 
 653     /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ 
 654     TRACEMS1(cinfo
, 1, JTRC_APP0
, (int) totallen
); 
 660 examine_app14 (j_decompress_ptr cinfo
, JOCTET FAR 
* data
, 
 661                unsigned int datalen
, JPEG_INT32 remaining
) 
 662 /* Examine first few bytes from an APP14. 
 663  * Take appropriate action if it is an Adobe marker. 
 664  * datalen is # of bytes at data[], remaining is length of rest of marker data. 
 667   unsigned int version
, flags0
, flags1
, transform
; 
 669   if (datalen 
>= APP14_DATA_LEN 
&& 
 670       GETJOCTET(data
[0]) == 0x41 && 
 671       GETJOCTET(data
[1]) == 0x64 && 
 672       GETJOCTET(data
[2]) == 0x6F && 
 673       GETJOCTET(data
[3]) == 0x62 && 
 674       GETJOCTET(data
[4]) == 0x65) { 
 675     /* Found Adobe APP14 marker */ 
 676     version 
= (GETJOCTET(data
[5]) << 8) + GETJOCTET(data
[6]); 
 677     flags0 
= (GETJOCTET(data
[7]) << 8) + GETJOCTET(data
[8]); 
 678     flags1 
= (GETJOCTET(data
[9]) << 8) + GETJOCTET(data
[10]); 
 679     transform 
= GETJOCTET(data
[11]); 
 680     TRACEMS4(cinfo
, 1, JTRC_ADOBE
, version
, flags0
, flags1
, transform
); 
 681     cinfo
->saw_Adobe_marker 
= TRUE
; 
 682     cinfo
->Adobe_transform 
= (UINT8
) transform
; 
 684     /* Start of APP14 does not match "Adobe", or too short */ 
 685     TRACEMS1(cinfo
, 1, JTRC_APP14
, (int) (datalen 
+ remaining
)); 
 691 get_interesting_appn (j_decompress_ptr cinfo
) 
 692 /* Process an APP0 or APP14 marker without saving it */ 
 695   JOCTET b
[APPN_DATA_LEN
]; 
 696   unsigned int i
, numtoread
; 
 699   INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 702   /* get the interesting part of the marker data */ 
 703   if (length 
>= APPN_DATA_LEN
) 
 704     numtoread 
= APPN_DATA_LEN
; 
 706     numtoread 
= (unsigned int) length
; 
 709   for (i 
= 0; i 
< numtoread
; i
++) 
 710     INPUT_BYTE(cinfo
, b
[i
], return FALSE
); 
 714   switch (cinfo
->unread_marker
) { 
 716     examine_app0(cinfo
, (JOCTET FAR 
*) b
, numtoread
, length
); 
 719     examine_app14(cinfo
, (JOCTET FAR 
*) b
, numtoread
, length
); 
 722     /* can't get here unless jpeg_save_markers chooses wrong processor */ 
 723     ERREXIT1(cinfo
, JERR_UNKNOWN_MARKER
, cinfo
->unread_marker
); 
 727   /* skip any remaining data -- could be lots */ 
 730     (*cinfo
->src
->skip_input_data
) (cinfo
, (long) length
); 
 736 #ifdef SAVE_MARKERS_SUPPORTED 
 739 save_marker (j_decompress_ptr cinfo
) 
 740 /* Save an APPn or COM marker into the marker list */ 
 742   my_marker_ptr marker 
= (my_marker_ptr
) cinfo
->marker
; 
 743   jpeg_saved_marker_ptr cur_marker 
= marker
->cur_marker
; 
 744   unsigned int bytes_read
, data_length
; 
 746   JPEG_INT32 length 
= 0; 
 749   if (cur_marker 
== NULL
) { 
 750     /* begin reading a marker */ 
 751     INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 753     if (length 
>= 0) {          /* watch out for bogus length word */ 
 754       /* figure out how much we want to save */ 
 756       if (cinfo
->unread_marker 
== (int) M_COM
) 
 757         limit 
= marker
->length_limit_COM
; 
 759         limit 
= marker
->length_limit_APPn
[cinfo
->unread_marker 
- (int) M_APP0
]; 
 760       if ((unsigned int) length 
< limit
) 
 761         limit 
= (unsigned int) length
; 
 762       /* allocate and initialize the marker item */ 
 763       cur_marker 
= (jpeg_saved_marker_ptr
) 
 764         (*cinfo
->mem
->alloc_large
) ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 765                                     SIZEOF(struct jpeg_marker_struct
) + limit
); 
 766       cur_marker
->next 
= NULL
; 
 767       cur_marker
->marker 
= (UINT8
) cinfo
->unread_marker
; 
 768       cur_marker
->original_length 
= (unsigned int) length
; 
 769       cur_marker
->data_length 
= limit
; 
 770       /* data area is just beyond the jpeg_marker_struct */ 
 771       data 
= cur_marker
->data 
= (JOCTET FAR 
*) (cur_marker 
+ 1); 
 772       marker
->cur_marker 
= cur_marker
; 
 773       marker
->bytes_read 
= 0; 
 777       /* deal with bogus length word */ 
 778       bytes_read 
= data_length 
= 0; 
 782     /* resume reading a marker */ 
 783     bytes_read 
= marker
->bytes_read
; 
 784     data_length 
= cur_marker
->data_length
; 
 785     data 
= cur_marker
->data 
+ bytes_read
; 
 788   while (bytes_read 
< data_length
) { 
 789     INPUT_SYNC(cinfo
);          /* move the restart point to here */ 
 790     marker
->bytes_read 
= bytes_read
; 
 791     /* If there's not at least one byte in buffer, suspend */ 
 792     MAKE_BYTE_AVAIL(cinfo
, return FALSE
); 
 793     /* Copy bytes with reasonable rapidity */ 
 794     while (bytes_read 
< data_length 
&& bytes_in_buffer 
> 0) { 
 795       *data
++ = *next_input_byte
++; 
 801   /* Done reading what we want to read */ 
 802   if (cur_marker 
!= NULL
) {     /* will be NULL if bogus length word */ 
 803     /* Add new marker to end of list */ 
 804     if (cinfo
->marker_list 
== NULL
) { 
 805       cinfo
->marker_list 
= cur_marker
; 
 807       jpeg_saved_marker_ptr prev 
= cinfo
->marker_list
; 
 808       while (prev
->next 
!= NULL
) 
 810       prev
->next 
= cur_marker
; 
 812     /* Reset pointer & calc remaining data length */ 
 813     data 
= cur_marker
->data
; 
 814     length 
= cur_marker
->original_length 
- data_length
; 
 816   /* Reset to initial state for next marker */ 
 817   marker
->cur_marker 
= NULL
; 
 819   /* Process the marker if interesting; else just make a generic trace msg */ 
 820   switch (cinfo
->unread_marker
) { 
 822     examine_app0(cinfo
, data
, data_length
, length
); 
 825     examine_app14(cinfo
, data
, data_length
, length
); 
 828     TRACEMS2(cinfo
, 1, JTRC_MISC_MARKER
, cinfo
->unread_marker
, 
 829              (int) (data_length 
+ length
)); 
 833   /* skip any remaining data -- could be lots */ 
 834   INPUT_SYNC(cinfo
);            /* do before skip_input_data */ 
 836     (*cinfo
->src
->skip_input_data
) (cinfo
, (long) length
); 
 841 #endif /* SAVE_MARKERS_SUPPORTED */ 
 845 skip_variable (j_decompress_ptr cinfo
) 
 846 /* Skip over an unknown or uninteresting variable-length marker */ 
 851   INPUT_2BYTES(cinfo
, length
, return FALSE
); 
 854   TRACEMS2(cinfo
, 1, JTRC_MISC_MARKER
, cinfo
->unread_marker
, (int) length
); 
 856   INPUT_SYNC(cinfo
);            /* do before skip_input_data */ 
 858     (*cinfo
->src
->skip_input_data
) (cinfo
, (long) length
); 
 865  * Find the next JPEG marker, save it in cinfo->unread_marker. 
 866  * Returns FALSE if had to suspend before reaching a marker; 
 867  * in that case cinfo->unread_marker is unchanged. 
 869  * Note that the result might not be a valid marker code, 
 870  * but it will never be 0 or FF. 
 874 next_marker (j_decompress_ptr cinfo
) 
 880     INPUT_BYTE(cinfo
, c
, return FALSE
); 
 881     /* Skip any non-FF bytes. 
 882      * This may look a bit inefficient, but it will not occur in a valid file. 
 883      * We sync after each discarded byte so that a suspending data source 
 884      * can discard the byte from its buffer. 
 887       cinfo
->marker
->discarded_bytes
++; 
 889       INPUT_BYTE(cinfo
, c
, return FALSE
); 
 891     /* This loop swallows any duplicate FF bytes.  Extra FFs are legal as 
 892      * pad bytes, so don't count them in discarded_bytes.  We assume there 
 893      * will not be so many consecutive FF bytes as to overflow a suspending 
 894      * data source's input buffer. 
 897       INPUT_BYTE(cinfo
, c
, return FALSE
); 
 900       break;                    /* found a valid marker, exit loop */ 
 901     /* Reach here if we found a stuffed-zero data sequence (FF/00). 
 902      * Discard it and loop back to try again. 
 904     cinfo
->marker
->discarded_bytes 
+= 2; 
 908   if (cinfo
->marker
->discarded_bytes 
!= 0) { 
 909     WARNMS2(cinfo
, JWRN_EXTRANEOUS_DATA
, cinfo
->marker
->discarded_bytes
, c
); 
 910     cinfo
->marker
->discarded_bytes 
= 0; 
 913   cinfo
->unread_marker 
= c
; 
 921 first_marker (j_decompress_ptr cinfo
) 
 922 /* Like next_marker, but used to obtain the initial SOI marker. */ 
 923 /* For this marker, we do not allow preceding garbage or fill; otherwise, 
 924  * we might well scan an entire input file before realizing it ain't JPEG. 
 925  * If an application wants to process non-JFIF files, it must seek to the 
 926  * SOI before calling the JPEG library. 
 932   INPUT_BYTE(cinfo
, c
, return FALSE
); 
 933   INPUT_BYTE(cinfo
, c2
, return FALSE
); 
 934   if (c 
!= 0xFF || c2 
!= (int) M_SOI
) 
 935     ERREXIT2(cinfo
, JERR_NO_SOI
, c
, c2
); 
 937   cinfo
->unread_marker 
= c2
; 
 945  * Read markers until SOS or EOI. 
 947  * Returns same codes as are defined for jpeg_consume_input: 
 948  * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. 
 952 read_markers (j_decompress_ptr cinfo
) 
 954   /* Outer loop repeats once for each marker. */ 
 956     /* Collect the marker proper, unless we already did. */ 
 957     /* NB: first_marker() enforces the requirement that SOI appear first. */ 
 958     if (cinfo
->unread_marker 
== 0) { 
 959       if (! cinfo
->marker
->saw_SOI
) { 
 960         if (! first_marker(cinfo
)) 
 961           return JPEG_SUSPENDED
; 
 963         if (! next_marker(cinfo
)) 
 964           return JPEG_SUSPENDED
; 
 967     /* At this point cinfo->unread_marker contains the marker code and the 
 968      * input point is just past the marker proper, but before any parameters. 
 969      * A suspension will cause us to return with this state still true. 
 971     switch (cinfo
->unread_marker
) { 
 973       if (! get_soi(cinfo
)) 
 974         return JPEG_SUSPENDED
; 
 977     case M_SOF0
:                /* Baseline */ 
 978     case M_SOF1
:                /* Extended sequential, Huffman */ 
 979       if (! get_sof(cinfo
, FALSE
, FALSE
)) 
 980         return JPEG_SUSPENDED
; 
 983     case M_SOF2
:                /* Progressive, Huffman */ 
 984       if (! get_sof(cinfo
, TRUE
, FALSE
)) 
 985         return JPEG_SUSPENDED
; 
 988     case M_SOF9
:                /* Extended sequential, arithmetic */ 
 989       if (! get_sof(cinfo
, FALSE
, TRUE
)) 
 990         return JPEG_SUSPENDED
; 
 993     case M_SOF10
:               /* Progressive, arithmetic */ 
 994       if (! get_sof(cinfo
, TRUE
, TRUE
)) 
 995         return JPEG_SUSPENDED
; 
 998     /* Currently unsupported SOFn types */ 
 999     case M_SOF3
:                /* Lossless, Huffman */ 
1000     case M_SOF5
:                /* Differential sequential, Huffman */ 
1001     case M_SOF6
:                /* Differential progressive, Huffman */ 
1002     case M_SOF7
:                /* Differential lossless, Huffman */ 
1003     case M_JPG
:                 /* Reserved for JPEG extensions */ 
1004     case M_SOF11
:               /* Lossless, arithmetic */ 
1005     case M_SOF13
:               /* Differential sequential, arithmetic */ 
1006     case M_SOF14
:               /* Differential progressive, arithmetic */ 
1007     case M_SOF15
:               /* Differential lossless, arithmetic */ 
1008       ERREXIT1(cinfo
, JERR_SOF_UNSUPPORTED
, cinfo
->unread_marker
); 
1012       if (! get_sos(cinfo
)) 
1013         return JPEG_SUSPENDED
; 
1014       cinfo
->unread_marker 
= 0; /* processed the marker */ 
1015       return JPEG_REACHED_SOS
; 
1018       TRACEMS(cinfo
, 1, JTRC_EOI
); 
1019       cinfo
->unread_marker 
= 0; /* processed the marker */ 
1020       return JPEG_REACHED_EOI
; 
1023       if (! get_dac(cinfo
)) 
1024         return JPEG_SUSPENDED
; 
1028       if (! get_dht(cinfo
)) 
1029         return JPEG_SUSPENDED
; 
1033       if (! get_dqt(cinfo
)) 
1034         return JPEG_SUSPENDED
; 
1038       if (! get_dri(cinfo
)) 
1039         return JPEG_SUSPENDED
; 
1058       if (! (*((my_marker_ptr
) cinfo
->marker
)->process_APPn
[ 
1059                 cinfo
->unread_marker 
- (int) M_APP0
]) (cinfo
)) 
1060         return JPEG_SUSPENDED
; 
1064       if (! (*((my_marker_ptr
) cinfo
->marker
)->process_COM
) (cinfo
)) 
1065         return JPEG_SUSPENDED
; 
1068     case M_RST0
:                /* these are all parameterless */ 
1077       TRACEMS1(cinfo
, 1, JTRC_PARMLESS_MARKER
, cinfo
->unread_marker
); 
1080     case M_DNL
:                 /* Ignore DNL ... perhaps the wrong thing */ 
1081       if (! skip_variable(cinfo
)) 
1082         return JPEG_SUSPENDED
; 
1085     default:                    /* must be DHP, EXP, JPGn, or RESn */ 
1086       /* For now, we treat the reserved markers as fatal errors since they are 
1087        * likely to be used to signal incompatible JPEG Part 3 extensions. 
1088        * Once the JPEG 3 version-number marker is well defined, this code 
1091       ERREXIT1(cinfo
, JERR_UNKNOWN_MARKER
, cinfo
->unread_marker
); 
1094     /* Successfully processed marker, so reset state variable */ 
1095     cinfo
->unread_marker 
= 0; 
1101  * Read a restart marker, which is expected to appear next in the datastream; 
1102  * if the marker is not there, take appropriate recovery action. 
1103  * Returns FALSE if suspension is required. 
1105  * This is called by the entropy decoder after it has read an appropriate 
1106  * number of MCUs.  cinfo->unread_marker may be nonzero if the entropy decoder 
1107  * has already read a marker from the data source.  Under normal conditions 
1108  * cinfo->unread_marker will be reset to 0 before returning; if not reset, 
1109  * it holds a marker which the decoder will be unable to read past. 
1113 read_restart_marker (j_decompress_ptr cinfo
) 
1115   /* Obtain a marker unless we already did. */ 
1116   /* Note that next_marker will complain if it skips any data. */ 
1117   if (cinfo
->unread_marker 
== 0) { 
1118     if (! next_marker(cinfo
)) 
1122   if (cinfo
->unread_marker 
== 
1123       ((int) M_RST0 
+ cinfo
->marker
->next_restart_num
)) { 
1124     /* Normal case --- swallow the marker and let entropy decoder continue */ 
1125     TRACEMS1(cinfo
, 3, JTRC_RST
, cinfo
->marker
->next_restart_num
); 
1126     cinfo
->unread_marker 
= 0; 
1128     /* Uh-oh, the restart markers have been messed up. */ 
1129     /* Let the data source manager determine how to resync. */ 
1130     if (! (*cinfo
->src
->resync_to_restart
) (cinfo
, 
1131                                             cinfo
->marker
->next_restart_num
)) 
1135   /* Update next-restart state */ 
1136   cinfo
->marker
->next_restart_num 
= (cinfo
->marker
->next_restart_num 
+ 1) & 7; 
1143  * This is the default resync_to_restart method for data source managers 
1144  * to use if they don't have any better approach.  Some data source managers 
1145  * may be able to back up, or may have additional knowledge about the data 
1146  * which permits a more intelligent recovery strategy; such managers would 
1147  * presumably supply their own resync method. 
1149  * read_restart_marker calls resync_to_restart if it finds a marker other than 
1150  * the restart marker it was expecting.  (This code is *not* used unless 
1151  * a nonzero restart interval has been declared.)  cinfo->unread_marker is 
1152  * the marker code actually found (might be anything, except 0 or FF). 
1153  * The desired restart marker number (0..7) is passed as a parameter. 
1154  * This routine is supposed to apply whatever error recovery strategy seems 
1155  * appropriate in order to position the input stream to the next data segment. 
1156  * Note that cinfo->unread_marker is treated as a marker appearing before 
1157  * the current data-source input point; usually it should be reset to zero 
1159  * Returns FALSE if suspension is required. 
1161  * This implementation is substantially constrained by wanting to treat the 
1162  * input as a data stream; this means we can't back up.  Therefore, we have 
1163  * only the following actions to work with: 
1164  *   1. Simply discard the marker and let the entropy decoder resume at next 
1166  *   2. Read forward until we find another marker, discarding intervening 
1167  *      data.  (In theory we could look ahead within the current bufferload, 
1168  *      without having to discard data if we don't find the desired marker. 
1169  *      This idea is not implemented here, in part because it makes behavior 
1170  *      dependent on buffer size and chance buffer-boundary positions.) 
1171  *   3. Leave the marker unread (by failing to zero cinfo->unread_marker). 
1172  *      This will cause the entropy decoder to process an empty data segment, 
1173  *      inserting dummy zeroes, and then we will reprocess the marker. 
1175  * #2 is appropriate if we think the desired marker lies ahead, while #3 is 
1176  * appropriate if the found marker is a future restart marker (indicating 
1177  * that we have missed the desired restart marker, probably because it got 
1179  * We apply #2 or #3 if the found marker is a restart marker no more than 
1180  * two counts behind or ahead of the expected one.  We also apply #2 if the 
1181  * found marker is not a legal JPEG marker code (it's certainly bogus data). 
1182  * If the found marker is a restart marker more than 2 counts away, we do #1 
1183  * (too much risk that the marker is erroneous; with luck we will be able to 
1184  * resync at some future point). 
1185  * For any valid non-restart JPEG marker, we apply #3.  This keeps us from 
1186  * overrunning the end of a scan.  An implementation limited to single-scan 
1187  * files might find it better to apply #2 for markers other than EOI, since 
1188  * any other marker would have to be bogus data in that case. 
1192 jpeg_resync_to_restart (j_decompress_ptr cinfo
, int desired
) 
1194   int marker 
= cinfo
->unread_marker
; 
1197   /* Always put up a warning. */ 
1198   WARNMS2(cinfo
, JWRN_MUST_RESYNC
, marker
, desired
); 
1200   /* Outer loop handles repeated decision after scanning forward. */ 
1202     if (marker 
< (int) M_SOF0
) 
1203       action 
= 2;               /* invalid marker */ 
1204     else if (marker 
< (int) M_RST0 
|| marker 
> (int) M_RST7
) 
1205       action 
= 3;               /* valid non-restart marker */ 
1207       if (marker 
== ((int) M_RST0 
+ ((desired
+1) & 7)) || 
1208           marker 
== ((int) M_RST0 
+ ((desired
+2) & 7))) 
1209         action 
= 3;             /* one of the next two expected restarts */ 
1210       else if (marker 
== ((int) M_RST0 
+ ((desired
-1) & 7)) || 
1211                marker 
== ((int) M_RST0 
+ ((desired
-2) & 7))) 
1212         action 
= 2;             /* a prior restart, so advance */ 
1214         action 
= 1;             /* desired restart or too far away */ 
1216     TRACEMS2(cinfo
, 4, JTRC_RECOVERY_ACTION
, marker
, action
); 
1219       /* Discard marker and let entropy decoder resume processing. */ 
1220       cinfo
->unread_marker 
= 0; 
1223       /* Scan to the next marker, and repeat the decision loop. */ 
1224       if (! next_marker(cinfo
)) 
1226       marker 
= cinfo
->unread_marker
; 
1229       /* Return without advancing past this marker. */ 
1230       /* Entropy decoder will be forced to process an empty segment. */ 
1238  * Reset marker processing state to begin a fresh datastream. 
1242 reset_marker_reader (j_decompress_ptr cinfo
) 
1244   my_marker_ptr marker 
= (my_marker_ptr
) cinfo
->marker
; 
1246   cinfo
->comp_info 
= NULL
;              /* until allocated by get_sof */ 
1247   cinfo
->input_scan_number 
= 0;         /* no SOS seen yet */ 
1248   cinfo
->unread_marker 
= 0;             /* no pending marker */ 
1249   marker
->pub
.saw_SOI 
= FALSE
;          /* set internal state too */ 
1250   marker
->pub
.saw_SOF 
= FALSE
; 
1251   marker
->pub
.discarded_bytes 
= 0; 
1252   marker
->cur_marker 
= NULL
; 
1257  * Initialize the marker reader module. 
1258  * This is called only once, when the decompression object is created. 
1262 jinit_marker_reader (j_decompress_ptr cinfo
) 
1264   my_marker_ptr marker
; 
1267   /* Create subobject in permanent pool */ 
1268   marker 
= (my_marker_ptr
) 
1269     (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_PERMANENT
, 
1270                                 SIZEOF(my_marker_reader
)); 
1271   cinfo
->marker 
= (struct jpeg_marker_reader 
*) marker
; 
1272   /* Initialize public method pointers */ 
1273   marker
->pub
.reset_marker_reader 
= reset_marker_reader
; 
1274   marker
->pub
.read_markers 
= read_markers
; 
1275   marker
->pub
.read_restart_marker 
= read_restart_marker
; 
1276   /* Initialize COM/APPn processing. 
1277    * By default, we examine and then discard APP0 and APP14, 
1278    * but simply discard COM and all other APPn. 
1280   marker
->process_COM 
= skip_variable
; 
1281   marker
->length_limit_COM 
= 0; 
1282   for (i 
= 0; i 
< 16; i
++) { 
1283     marker
->process_APPn
[i
] = skip_variable
; 
1284     marker
->length_limit_APPn
[i
] = 0; 
1286   marker
->process_APPn
[0] = get_interesting_appn
; 
1287   marker
->process_APPn
[14] = get_interesting_appn
; 
1288   /* Reset marker processing state */ 
1289   reset_marker_reader(cinfo
); 
1294  * Control saving of COM and APPn markers into marker_list. 
1297 #ifdef SAVE_MARKERS_SUPPORTED 
1300 jpeg_save_markers (j_decompress_ptr cinfo
, int marker_code
, 
1301                    unsigned int length_limit
) 
1303   my_marker_ptr marker 
= (my_marker_ptr
) cinfo
->marker
; 
1305   jpeg_marker_parser_method processor
; 
1307   /* Length limit mustn't be larger than what we can allocate 
1308    * (should only be a concern in a 16-bit environment). 
1310   maxlength 
= cinfo
->mem
->max_alloc_chunk 
- SIZEOF(struct jpeg_marker_struct
); 
1311   if (((long) length_limit
) > maxlength
) 
1312     length_limit 
= (unsigned int) maxlength
; 
1314   /* Choose processor routine to use. 
1315    * APP0/APP14 have special requirements. 
1318     processor 
= save_marker
; 
1319     /* If saving APP0/APP14, save at least enough for our internal use. */ 
1320     if (marker_code 
== (int) M_APP0 
&& length_limit 
< APP0_DATA_LEN
) 
1321       length_limit 
= APP0_DATA_LEN
; 
1322     else if (marker_code 
== (int) M_APP14 
&& length_limit 
< APP14_DATA_LEN
) 
1323       length_limit 
= APP14_DATA_LEN
; 
1325     processor 
= skip_variable
; 
1326     /* If discarding APP0/APP14, use our regular on-the-fly processor. */ 
1327     if (marker_code 
== (int) M_APP0 
|| marker_code 
== (int) M_APP14
) 
1328       processor 
= get_interesting_appn
; 
1331   if (marker_code 
== (int) M_COM
) { 
1332     marker
->process_COM 
= processor
; 
1333     marker
->length_limit_COM 
= length_limit
; 
1334   } else if (marker_code 
>= (int) M_APP0 
&& marker_code 
<= (int) M_APP15
) { 
1335     marker
->process_APPn
[marker_code 
- (int) M_APP0
] = processor
; 
1336     marker
->length_limit_APPn
[marker_code 
- (int) M_APP0
] = length_limit
; 
1338     ERREXIT1(cinfo
, JERR_UNKNOWN_MARKER
, marker_code
); 
1341 #endif /* SAVE_MARKERS_SUPPORTED */ 
1345  * Install a special processing method for COM or APPn markers. 
1349 jpeg_set_marker_processor (j_decompress_ptr cinfo
, int marker_code
, 
1350                            jpeg_marker_parser_method routine
) 
1352   my_marker_ptr marker 
= (my_marker_ptr
) cinfo
->marker
; 
1354   if (marker_code 
== (int) M_COM
) 
1355     marker
->process_COM 
= routine
; 
1356   else if (marker_code 
>= (int) M_APP0 
&& marker_code 
<= (int) M_APP15
) 
1357     marker
->process_APPn
[marker_code 
- (int) M_APP0
] = routine
; 
1359     ERREXIT1(cinfo
, JERR_UNKNOWN_MARKER
, marker_code
);