| /* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0 | 
 |    specification is now totally obsolete and deprecated for new applications and | 
 |    images. This file was was created solely in order to read unconverted images | 
 |    still present on some users' computer systems. It will never be extended | 
 |    to write such files. Writing new-style JPEG compressed TIFFs is implemented | 
 |    in tif_jpeg.c. | 
 |  | 
 |    The code is carefully crafted to robustly read all gathered JPEG-in-TIFF | 
 |    testfiles, and anticipate as much as possible all other... But still, it may | 
 |    fail on some. If you encounter problems, please report them on the TIFF | 
 |    mailing list and/or to Joris Van Damme <info@awaresystems.be>. | 
 |  | 
 |    Please read the file called "TIFF Technical Note #2" if you need to be | 
 |    convinced this compression scheme is bad and breaks TIFF. That document | 
 |    is linked to from the LibTiff site <http://www.remotesensing.org/libtiff/> | 
 |    and from AWare Systems' TIFF section | 
 |    <http://www.awaresystems.be/imaging/tiff.html>. It is also absorbed | 
 |    in Adobe's specification supplements, marked "draft" up to this day, but | 
 |    supported by the TIFF community. | 
 |  | 
 |    This file interfaces with Release 6B of the JPEG Library written by the | 
 |    Independent JPEG Group. Previous versions of this file required a hack inside | 
 |    the LibJpeg library. This version no longer requires that. Remember to | 
 |    remove the hack if you update from the old version. | 
 |  | 
 |    Copyright (c) Joris Van Damme <info@awaresystems.be> | 
 |    Copyright (c) AWare Systems <http://www.awaresystems.be/> | 
 |  | 
 |    The licence agreement for this file is the same as the rest of the LibTiff | 
 |    library. | 
 |  | 
 |    IN NO EVENT SHALL JORIS VAN DAMME OR AWARE SYSTEMS BE LIABLE FOR | 
 |    ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, | 
 |    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | 
 |    WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF | 
 |    LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | 
 |    OF THIS SOFTWARE. | 
 |  | 
 |    Joris Van Damme and/or AWare Systems may be available for custom | 
 |    development. If you like what you see, and need anything similar or related, | 
 |    contact <info@awaresystems.be>. | 
 | */ | 
 |  | 
 | /* What is what, and what is not? | 
 |  | 
 |    This decoder starts with an input stream, that is essentially the JpegInterchangeFormat | 
 |    stream, if any, followed by the strile data, if any. This stream is read in | 
 |    OJPEGReadByte and related functions. | 
 |  | 
 |    It analyzes the start of this stream, until it encounters non-marker data, i.e. | 
 |    compressed image data. Some of the header markers it sees have no actual content, | 
 |    like the SOI marker, and APP/COM markers that really shouldn't even be there. Some | 
 |    other markers do have content, and the valuable bits and pieces of information | 
 |    in these markers are saved, checking all to verify that the stream is more or | 
 |    less within expected bounds. This happens inside the OJPEGReadHeaderInfoSecStreamXxx | 
 |    functions. | 
 |  | 
 |    Some OJPEG imagery contains no valid JPEG header markers. This situation is picked | 
 |    up on if we've seen no SOF marker when we're at the start of the compressed image | 
 |    data. In this case, the tables are read from JpegXxxTables tags, and the other | 
 |    bits and pieces of information is initialized to its most basic value. This is | 
 |    implemented in the OJPEGReadHeaderInfoSecTablesXxx functions. | 
 |  | 
 |    When this is complete, a good and valid JPEG header can be assembled, and this is | 
 |    passed through to LibJpeg. When that's done, the remainder of the input stream, i.e. | 
 |    the compressed image data, can be passed through unchanged. This is done in | 
 |    OJPEGWriteStream functions. | 
 |  | 
 |    LibTiff rightly expects to know the subsampling values before decompression. Just like | 
 |    in new-style JPEG-in-TIFF, though, or even more so, actually, the YCbCrsubsampling | 
 |    tag is notoriously unreliable. To correct these tag values with the ones inside | 
 |    the JPEG stream, the first part of the input stream is pre-scanned in | 
 |    OJPEGSubsamplingCorrect, making no note of any other data, reporting no warnings | 
 |    or errors, up to the point where either these values are read, or it's clear they | 
 |    aren't there. This means that some of the data is read twice, but we feel speed | 
 |    in correcting these values is important enough to warrant this sacrifice. Although | 
 |    there is currently no define or other configuration mechanism to disable this behaviour, | 
 |    the actual header scanning is build to robustly respond with error report if it | 
 |    should encounter an uncorrected mismatch of subsampling values. See | 
 |    OJPEGReadHeaderInfoSecStreamSof. | 
 |  | 
 |    The restart interval and restart markers are the most tricky part... The restart | 
 |    interval can be specified in a tag. It can also be set inside the input JPEG stream. | 
 |    It can be used inside the input JPEG stream. If reading from strile data, we've | 
 |    consistently discovered the need to insert restart markers in between the different | 
 |    striles, as is also probably the most likely interpretation of the original TIFF 6.0 | 
 |    specification. With all this setting of interval, and actual use of markers that is not | 
 |    predictable at the time of valid JPEG header assembly, the restart thing may turn | 
 |    out the Achilles heel of this implementation. Fortunately, most OJPEG writer vendors | 
 |    succeed in reading back what they write, which may be the reason why we've been able | 
 |    to discover ways that seem to work. | 
 |  | 
 |    Some special provision is made for planarconfig separate OJPEG files. These seem | 
 |    to consistently contain header info, a SOS marker, a plane, SOS marker, plane, SOS, | 
 |    and plane. This may or may not be a valid JPEG configuration, we don't know and don't | 
 |    care. We want LibTiff to be able to access the planes individually, without huge | 
 |    buffering inside LibJpeg, anyway. So we compose headers to feed to LibJpeg, in this | 
 |    case, that allow us to pass a single plane such that LibJpeg sees a valid | 
 |    single-channel JPEG stream. Locating subsequent SOS markers, and thus subsequent | 
 |    planes, is done inside OJPEGReadSecondarySos. | 
 |  | 
 |    The benefit of the scheme is... that it works, basically. We know of no other that | 
 |    does. It works without checking software tag, or otherwise going about things in an | 
 |    OJPEG flavor specific manner. Instead, it is a single scheme, that covers the cases | 
 |    with and without JpegInterchangeFormat, with and without striles, with part of | 
 |    the header in JpegInterchangeFormat and remainder in first strile, etc. It is forgiving | 
 |    and robust, may likely work with OJPEG flavors we've not seen yet, and makes most out | 
 |    of the data. | 
 |  | 
 |    Another nice side-effect is that a complete JPEG single valid stream is build if | 
 |    planarconfig is not separate (vast majority). We may one day use that to build | 
 |    converters to JPEG, and/or to new-style JPEG compression inside TIFF. | 
 |  | 
 |    A disadvantage is the lack of random access to the individual striles. This is the | 
 |    reason for much of the complicated restart-and-position stuff inside OJPEGPreDecode. | 
 |    Applications would do well accessing all striles in order, as this will result in | 
 |    a single sequential scan of the input stream, and no restarting of LibJpeg decoding | 
 |    session. | 
 | */ | 
 |  | 
 | #define WIN32_LEAN_AND_MEAN | 
 | #define VC_EXTRALEAN | 
 |  | 
 | #include "tiffiop.h" | 
 | #ifdef OJPEG_SUPPORT | 
 |  | 
 | /* Configuration defines here are: | 
 |  * JPEG_ENCAP_EXTERNAL: The normal way to call libjpeg, uses longjump. In some environments, | 
 |  * 	like eg LibTiffDelphi, this is not possible. For this reason, the actual calls to | 
 |  * 	libjpeg, with longjump stuff, are encapsulated in dedicated functions. When | 
 |  * 	JPEG_ENCAP_EXTERNAL is defined, these encapsulating functions are declared external | 
 |  * 	to this unit, and can be defined elsewhere to use stuff other then longjump. | 
 |  * 	The default mode, without JPEG_ENCAP_EXTERNAL, implements the call encapsulators | 
 |  * 	here, internally, with normal longjump. | 
 |  * SETJMP, LONGJMP, JMP_BUF: On some machines/environments a longjump equivalent is | 
 |  * 	conveniently available, but still it may be worthwhile to use _setjmp or sigsetjmp | 
 |  * 	in place of plain setjmp. These macros will make it easier. It is useless | 
 |  * 	to fiddle with these if you define JPEG_ENCAP_EXTERNAL. | 
 |  * OJPEG_BUFFER: Define the size of the desired buffer here. Should be small enough so as to guarantee | 
 |  * 	instant processing, optimal streaming and optimal use of processor cache, but also big | 
 |  * 	enough so as to not result in significant call overhead. It should be at least a few | 
 |  * 	bytes to accommodate some structures (this is verified in asserts), but it would not be | 
 |  * 	sensible to make it this small anyway, and it should be at most 64K since it is indexed | 
 |  * 	with uint16. We recommend 2K. | 
 |  * EGYPTIANWALK: You could also define EGYPTIANWALK here, but it is not used anywhere and has | 
 |  * 	absolutely no effect. That is why most people insist the EGYPTIANWALK is a bit silly. | 
 |  */ | 
 |  | 
 | /* define LIBJPEG_ENCAP_EXTERNAL */ | 
 | #define SETJMP(jbuf) setjmp(jbuf) | 
 | #define LONGJMP(jbuf,code) longjmp(jbuf,code) | 
 | #define JMP_BUF jmp_buf | 
 | #define OJPEG_BUFFER 2048 | 
 | /* define EGYPTIANWALK */ | 
 |  | 
 | #define JPEG_MARKER_SOF0 0xC0 | 
 | #define JPEG_MARKER_SOF1 0xC1 | 
 | #define JPEG_MARKER_SOF3 0xC3 | 
 | #define JPEG_MARKER_DHT 0xC4 | 
 | #define JPEG_MARKER_RST0 0XD0 | 
 | #define JPEG_MARKER_SOI 0xD8 | 
 | #define JPEG_MARKER_EOI 0xD9 | 
 | #define JPEG_MARKER_SOS 0xDA | 
 | #define JPEG_MARKER_DQT 0xDB | 
 | #define JPEG_MARKER_DRI 0xDD | 
 | #define JPEG_MARKER_APP0 0xE0 | 
 | #define JPEG_MARKER_COM 0xFE | 
 |  | 
 | #define FIELD_OJPEG_JPEGINTERCHANGEFORMAT (FIELD_CODEC+0) | 
 | #define FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH (FIELD_CODEC+1) | 
 | #define FIELD_OJPEG_JPEGQTABLES (FIELD_CODEC+2) | 
 | #define FIELD_OJPEG_JPEGDCTABLES (FIELD_CODEC+3) | 
 | #define FIELD_OJPEG_JPEGACTABLES (FIELD_CODEC+4) | 
 | #define FIELD_OJPEG_JPEGPROC (FIELD_CODEC+5) | 
 | #define FIELD_OJPEG_JPEGRESTARTINTERVAL (FIELD_CODEC+6) | 
 |  | 
 | static const TIFFField ojpegFields[] = { | 
 | 	{TIFFTAG_JPEGIFOFFSET,1,1,TIFF_LONG8,0,TIFF_SETGET_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGINTERCHANGEFORMAT,TRUE,FALSE,"JpegInterchangeFormat",NULL}, | 
 | 	{TIFFTAG_JPEGIFBYTECOUNT,1,1,TIFF_LONG8,0,TIFF_SETGET_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH,TRUE,FALSE,"JpegInterchangeFormatLength",NULL}, | 
 | 	{TIFFTAG_JPEGQTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGQTABLES,FALSE,TRUE,"JpegQTables",NULL}, | 
 | 	{TIFFTAG_JPEGDCTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGDCTABLES,FALSE,TRUE,"JpegDcTables",NULL}, | 
 | 	{TIFFTAG_JPEGACTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGACTABLES,FALSE,TRUE,"JpegAcTables",NULL}, | 
 | 	{TIFFTAG_JPEGPROC,1,1,TIFF_SHORT,0,TIFF_SETGET_UINT16,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGPROC,FALSE,FALSE,"JpegProc",NULL}, | 
 | 	{TIFFTAG_JPEGRESTARTINTERVAL,1,1,TIFF_SHORT,0,TIFF_SETGET_UINT16,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGRESTARTINTERVAL,FALSE,FALSE,"JpegRestartInterval",NULL}, | 
 | }; | 
 |  | 
 | #ifndef LIBJPEG_ENCAP_EXTERNAL | 
 | #include <setjmp.h> | 
 | #endif | 
 |  | 
 | /* We undefine FAR to avoid conflict with JPEG definition */ | 
 |  | 
 | #ifdef FAR | 
 | #undef FAR | 
 | #endif | 
 |  | 
 | /* | 
 |   Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is | 
 |   not defined.  Unfortunately, the MinGW and Borland compilers include | 
 |   a typedef for INT32, which causes a conflict.  MSVC does not include | 
 |   a conflicting typedef given the headers which are included. | 
 | */ | 
 | #if defined(__BORLANDC__) || defined(__MINGW32__) | 
 | # define XMD_H 1 | 
 | #endif | 
 |  | 
 | /* Define "boolean" as unsigned char, not int, per Windows custom. */ | 
 | #if defined(__WIN32__) && !defined(__MINGW32__) | 
 | # ifndef __RPCNDR_H__            /* don't conflict if rpcndr.h already read */ | 
 |    typedef unsigned char boolean; | 
 | # endif | 
 | # define HAVE_BOOLEAN            /* prevent jmorecfg.h from redefining it */ | 
 | #endif | 
 |  | 
 | #if defined(USE_SYSTEM_LIBJPEG) | 
 | #include <jerror.h> | 
 | #include <jpeglib.h> | 
 | #elif defined(USE_LIBJPEG_TURBO) | 
 | #include "third_party/libjpeg_turbo/jerror.h" | 
 | #include "third_party/libjpeg_turbo/jpeglib.h" | 
 | #else | 
 | #include "third_party/libjpeg/jerror.h" | 
 | #include "third_party/libjpeg/jpeglib.h" | 
 | #endif | 
 |  | 
 |  | 
 | typedef struct jpeg_error_mgr jpeg_error_mgr; | 
 | typedef struct jpeg_common_struct jpeg_common_struct; | 
 | typedef struct jpeg_decompress_struct jpeg_decompress_struct; | 
 | typedef struct jpeg_source_mgr jpeg_source_mgr; | 
 |  | 
 | typedef enum { | 
 | 	osibsNotSetYet, | 
 | 	osibsJpegInterchangeFormat, | 
 | 	osibsStrile, | 
 | 	osibsEof | 
 | } OJPEGStateInBufferSource; | 
 |  | 
 | typedef enum { | 
 | 	ososSoi, | 
 | 	ososQTable0,ososQTable1,ososQTable2,ososQTable3, | 
 | 	ososDcTable0,ososDcTable1,ososDcTable2,ososDcTable3, | 
 | 	ososAcTable0,ososAcTable1,ososAcTable2,ososAcTable3, | 
 | 	ososDri, | 
 | 	ososSof, | 
 | 	ososSos, | 
 | 	ososCompressed, | 
 | 	ososRst, | 
 | 	ososEoi | 
 | } OJPEGStateOutState; | 
 |  | 
 | typedef struct { | 
 | 	TIFF* tif; | 
 |         int decoder_ok; | 
 |         int error_in_raw_data_decoding; | 
 | 	#ifndef LIBJPEG_ENCAP_EXTERNAL | 
 | 	JMP_BUF exit_jmpbuf; | 
 | 	#endif | 
 | 	TIFFVGetMethod vgetparent; | 
 | 	TIFFVSetMethod vsetparent; | 
 | 	TIFFPrintMethod printdir; | 
 | 	uint64 file_size; | 
 | 	uint32 image_width; | 
 | 	uint32 image_length; | 
 | 	uint32 strile_width; | 
 | 	uint32 strile_length; | 
 | 	uint32 strile_length_total; | 
 | 	uint8 samples_per_pixel; | 
 | 	uint8 plane_sample_offset; | 
 | 	uint8 samples_per_pixel_per_plane; | 
 | 	uint64 jpeg_interchange_format; | 
 | 	uint64 jpeg_interchange_format_length; | 
 | 	uint8 jpeg_proc; | 
 | 	uint8 subsamplingcorrect; | 
 | 	uint8 subsamplingcorrect_done; | 
 | 	uint8 subsampling_tag; | 
 | 	uint8 subsampling_hor; | 
 | 	uint8 subsampling_ver; | 
 | 	uint8 subsampling_force_desubsampling_inside_decompression; | 
 | 	uint8 qtable_offset_count; | 
 | 	uint8 dctable_offset_count; | 
 | 	uint8 actable_offset_count; | 
 | 	uint64 qtable_offset[3]; | 
 | 	uint64 dctable_offset[3]; | 
 | 	uint64 actable_offset[3]; | 
 | 	uint8* qtable[4]; | 
 | 	uint8* dctable[4]; | 
 | 	uint8* actable[4]; | 
 | 	uint16 restart_interval; | 
 | 	uint8 restart_index; | 
 | 	uint8 sof_log; | 
 | 	uint8 sof_marker_id; | 
 | 	uint32 sof_x; | 
 | 	uint32 sof_y; | 
 | 	uint8 sof_c[3]; | 
 | 	uint8 sof_hv[3]; | 
 | 	uint8 sof_tq[3]; | 
 | 	uint8 sos_cs[3]; | 
 | 	uint8 sos_tda[3]; | 
 | 	struct { | 
 | 		uint8 log; | 
 | 		OJPEGStateInBufferSource in_buffer_source; | 
 | 		uint32 in_buffer_next_strile; | 
 | 		uint64 in_buffer_file_pos; | 
 | 		uint64 in_buffer_file_togo; | 
 | 	} sos_end[3]; | 
 | 	uint8 readheader_done; | 
 | 	uint8 writeheader_done; | 
 | 	uint16 write_cursample; | 
 | 	uint32 write_curstrile; | 
 | 	uint8 libjpeg_session_active; | 
 | 	uint8 libjpeg_jpeg_query_style; | 
 | 	jpeg_error_mgr libjpeg_jpeg_error_mgr; | 
 | 	jpeg_decompress_struct libjpeg_jpeg_decompress_struct; | 
 | 	jpeg_source_mgr libjpeg_jpeg_source_mgr; | 
 | 	uint8 subsampling_convert_log; | 
 | 	uint32 subsampling_convert_ylinelen; | 
 | 	uint32 subsampling_convert_ylines; | 
 | 	uint32 subsampling_convert_clinelen; | 
 | 	uint32 subsampling_convert_clines; | 
 | 	uint32 subsampling_convert_ybuflen; | 
 | 	uint32 subsampling_convert_cbuflen; | 
 | 	uint32 subsampling_convert_ycbcrbuflen; | 
 | 	uint8* subsampling_convert_ycbcrbuf; | 
 | 	uint8* subsampling_convert_ybuf; | 
 | 	uint8* subsampling_convert_cbbuf; | 
 | 	uint8* subsampling_convert_crbuf; | 
 | 	uint32 subsampling_convert_ycbcrimagelen; | 
 | 	uint8** subsampling_convert_ycbcrimage; | 
 | 	uint32 subsampling_convert_clinelenout; | 
 | 	uint32 subsampling_convert_state; | 
 | 	uint32 bytes_per_line;   /* if the codec outputs subsampled data, a 'line' in bytes_per_line */ | 
 | 	uint32 lines_per_strile; /* and lines_per_strile means subsampling_ver desubsampled rows     */ | 
 | 	OJPEGStateInBufferSource in_buffer_source; | 
 | 	uint32 in_buffer_next_strile; | 
 | 	uint32 in_buffer_strile_count; | 
 | 	uint64 in_buffer_file_pos; | 
 | 	uint8 in_buffer_file_pos_log; | 
 | 	uint64 in_buffer_file_togo; | 
 | 	uint16 in_buffer_togo; | 
 | 	uint8* in_buffer_cur; | 
 | 	uint8 in_buffer[OJPEG_BUFFER]; | 
 | 	OJPEGStateOutState out_state; | 
 | 	uint8 out_buffer[OJPEG_BUFFER]; | 
 | 	uint8* skip_buffer; | 
 | } OJPEGState; | 
 |  | 
 | static int OJPEGVGetField(TIFF* tif, uint32 tag, va_list ap); | 
 | static int OJPEGVSetField(TIFF* tif, uint32 tag, va_list ap); | 
 | static void OJPEGPrintDir(TIFF* tif, FILE* fd, long flags); | 
 |  | 
 | static int OJPEGFixupTags(TIFF* tif); | 
 | static int OJPEGSetupDecode(TIFF* tif); | 
 | static int OJPEGPreDecode(TIFF* tif, uint16 s); | 
 | static int OJPEGPreDecodeSkipRaw(TIFF* tif); | 
 | static int OJPEGPreDecodeSkipScanlines(TIFF* tif); | 
 | static int OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s); | 
 | static int OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc); | 
 | static int OJPEGDecodeScanlines(TIFF* tif, uint8* buf, tmsize_t cc); | 
 | static void OJPEGPostDecode(TIFF* tif, uint8* buf, tmsize_t cc); | 
 | static int OJPEGSetupEncode(TIFF* tif); | 
 | static int OJPEGPreEncode(TIFF* tif, uint16 s); | 
 | static int OJPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s); | 
 | static int OJPEGPostEncode(TIFF* tif); | 
 | static void OJPEGCleanup(TIFF* tif); | 
 |  | 
 | static void OJPEGSubsamplingCorrect(TIFF* tif); | 
 | static int OJPEGReadHeaderInfo(TIFF* tif); | 
 | static int OJPEGReadSecondarySos(TIFF* tif, uint16 s); | 
 | static int OJPEGWriteHeaderInfo(TIFF* tif); | 
 | static void OJPEGLibjpegSessionAbort(TIFF* tif); | 
 |  | 
 | static int OJPEGReadHeaderInfoSec(TIFF* tif); | 
 | static int OJPEGReadHeaderInfoSecStreamDri(TIFF* tif); | 
 | static int OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif); | 
 | static int OJPEGReadHeaderInfoSecStreamDht(TIFF* tif); | 
 | static int OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id); | 
 | static int OJPEGReadHeaderInfoSecStreamSos(TIFF* tif); | 
 | static int OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif); | 
 | static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif); | 
 | static int OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif); | 
 |  | 
 | static int OJPEGReadBufferFill(OJPEGState* sp); | 
 | static int OJPEGReadByte(OJPEGState* sp, uint8* byte); | 
 | static int OJPEGReadBytePeek(OJPEGState* sp, uint8* byte); | 
 | static void OJPEGReadByteAdvance(OJPEGState* sp); | 
 | static int OJPEGReadWord(OJPEGState* sp, uint16* word); | 
 | static int OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem); | 
 | static void OJPEGReadSkip(OJPEGState* sp, uint16 len); | 
 |  | 
 | static int OJPEGWriteStream(TIFF* tif, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len); | 
 | static int OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len); | 
 | static void OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len); | 
 |  | 
 | #ifdef LIBJPEG_ENCAP_EXTERNAL | 
 | extern int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo); | 
 | extern int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image); | 
 | extern int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo); | 
 | extern int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines); | 
 | extern int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines); | 
 | extern void jpeg_encap_unwind(TIFF* tif); | 
 | #else | 
 | static int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* j); | 
 | static int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image); | 
 | static int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo); | 
 | static int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines); | 
 | static int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines); | 
 | static void jpeg_encap_unwind(TIFF* tif); | 
 | #endif | 
 |  | 
 | static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo); | 
 | static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo); | 
 | static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo); | 
 | static boolean OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo); | 
 | static void OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes); | 
 | static boolean OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired); | 
 | static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo); | 
 |  | 
 | int | 
 | TIFFInitOJPEG(TIFF* tif, int scheme) | 
 | { | 
 | 	static const char module[]="TIFFInitOJPEG"; | 
 | 	OJPEGState* sp; | 
 |  | 
 | 	assert(scheme==COMPRESSION_OJPEG); | 
 |  | 
 |         /* | 
 | 	 * Merge codec-specific tag information. | 
 | 	 */ | 
 | 	if (!_TIFFMergeFields(tif, ojpegFields, TIFFArrayCount(ojpegFields))) { | 
 | 		TIFFErrorExt(tif->tif_clientdata, module, | 
 | 		    "Merging Old JPEG codec-specific tags failed"); | 
 | 		return 0; | 
 | 	} | 
 |  | 
 | 	/* state block */ | 
 | 	sp=_TIFFmalloc(sizeof(OJPEGState)); | 
 | 	if (sp==NULL) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"No space for OJPEG state block"); | 
 | 		return(0); | 
 | 	} | 
 | 	_TIFFmemset(sp,0,sizeof(OJPEGState)); | 
 | 	sp->tif=tif; | 
 | 	sp->jpeg_proc=1; | 
 | 	sp->subsampling_hor=2; | 
 | 	sp->subsampling_ver=2; | 
 | 	TIFFSetField(tif,TIFFTAG_YCBCRSUBSAMPLING,2,2); | 
 | 	/* tif codec methods */ | 
 | 	tif->tif_fixuptags=OJPEGFixupTags;   | 
 | 	tif->tif_setupdecode=OJPEGSetupDecode; | 
 | 	tif->tif_predecode=OJPEGPreDecode; | 
 | 	tif->tif_postdecode=OJPEGPostDecode;   | 
 | 	tif->tif_decoderow=OJPEGDecode;   | 
 | 	tif->tif_decodestrip=OJPEGDecode;   | 
 | 	tif->tif_decodetile=OJPEGDecode;   | 
 | 	tif->tif_setupencode=OJPEGSetupEncode; | 
 | 	tif->tif_preencode=OJPEGPreEncode; | 
 | 	tif->tif_postencode=OJPEGPostEncode; | 
 | 	tif->tif_encoderow=OJPEGEncode;   | 
 | 	tif->tif_encodestrip=OJPEGEncode;   | 
 | 	tif->tif_encodetile=OJPEGEncode;   | 
 | 	tif->tif_cleanup=OJPEGCleanup; | 
 | 	tif->tif_data=(uint8*)sp; | 
 | 	/* tif tag methods */ | 
 | 	sp->vgetparent=tif->tif_tagmethods.vgetfield; | 
 | 	tif->tif_tagmethods.vgetfield=OJPEGVGetField; | 
 | 	sp->vsetparent=tif->tif_tagmethods.vsetfield; | 
 | 	tif->tif_tagmethods.vsetfield=OJPEGVSetField; | 
 | 	sp->printdir=tif->tif_tagmethods.printdir; | 
 | 	tif->tif_tagmethods.printdir=OJPEGPrintDir; | 
 | 	/* Some OJPEG files don't have strip or tile offsets or bytecounts tags. | 
 | 	   Some others do, but have totally meaningless or corrupt values | 
 | 	   in these tags. In these cases, the JpegInterchangeFormat stream is | 
 | 	   reliable. In any case, this decoder reads the compressed data itself, | 
 | 	   from the most reliable locations, and we need to notify encapsulating | 
 | 	   LibTiff not to read raw strips or tiles for us. */ | 
 | 	tif->tif_flags|=TIFF_NOREADRAW; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGVGetField(TIFF* tif, uint32 tag, va_list ap) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	switch(tag) | 
 | 	{ | 
 | 		case TIFFTAG_JPEGIFOFFSET: | 
 | 			*va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format; | 
 | 			break; | 
 | 		case TIFFTAG_JPEGIFBYTECOUNT: | 
 | 			*va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format_length; | 
 | 			break; | 
 | 		case TIFFTAG_YCBCRSUBSAMPLING: | 
 | 			if (sp->subsamplingcorrect_done==0) | 
 | 				OJPEGSubsamplingCorrect(tif); | 
 | 			*va_arg(ap,uint16*)=(uint16)sp->subsampling_hor; | 
 | 			*va_arg(ap,uint16*)=(uint16)sp->subsampling_ver; | 
 | 			break; | 
 | 		case TIFFTAG_JPEGQTABLES: | 
 | 			*va_arg(ap,uint32*)=(uint32)sp->qtable_offset_count; | 
 | 			*va_arg(ap,void**)=(void*)sp->qtable_offset;  | 
 | 			break; | 
 | 		case TIFFTAG_JPEGDCTABLES: | 
 | 			*va_arg(ap,uint32*)=(uint32)sp->dctable_offset_count; | 
 | 			*va_arg(ap,void**)=(void*)sp->dctable_offset;   | 
 | 			break; | 
 | 		case TIFFTAG_JPEGACTABLES: | 
 | 			*va_arg(ap,uint32*)=(uint32)sp->actable_offset_count; | 
 | 			*va_arg(ap,void**)=(void*)sp->actable_offset; | 
 | 			break; | 
 | 		case TIFFTAG_JPEGPROC: | 
 | 			*va_arg(ap,uint16*)=(uint16)sp->jpeg_proc; | 
 | 			break; | 
 | 		case TIFFTAG_JPEGRESTARTINTERVAL: | 
 | 			*va_arg(ap,uint16*)=sp->restart_interval; | 
 | 			break; | 
 | 		default: | 
 | 			return (*sp->vgetparent)(tif,tag,ap); | 
 | 	} | 
 | 	return (1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGVSetField(TIFF* tif, uint32 tag, va_list ap) | 
 | { | 
 | 	static const char module[]="OJPEGVSetField"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint32 ma; | 
 | 	uint64* mb; | 
 | 	uint32 n; | 
 | 	const TIFFField* fip; | 
 |  | 
 | 	switch(tag) | 
 | 	{ | 
 | 		case TIFFTAG_JPEGIFOFFSET: | 
 | 			sp->jpeg_interchange_format=(uint64)va_arg(ap,uint64); | 
 | 			break; | 
 | 		case TIFFTAG_JPEGIFBYTECOUNT: | 
 | 			sp->jpeg_interchange_format_length=(uint64)va_arg(ap,uint64); | 
 | 			break; | 
 | 		case TIFFTAG_YCBCRSUBSAMPLING: | 
 | 			sp->subsampling_tag=1; | 
 | 			sp->subsampling_hor=(uint8)va_arg(ap,uint16_vap); | 
 | 			sp->subsampling_ver=(uint8)va_arg(ap,uint16_vap); | 
 | 			tif->tif_dir.td_ycbcrsubsampling[0]=sp->subsampling_hor; | 
 | 			tif->tif_dir.td_ycbcrsubsampling[1]=sp->subsampling_ver; | 
 | 			break; | 
 | 		case TIFFTAG_JPEGQTABLES: | 
 | 			ma=(uint32)va_arg(ap,uint32); | 
 | 			if (ma!=0) | 
 | 			{ | 
 | 				if (ma>3) | 
 | 				{ | 
 | 					TIFFErrorExt(tif->tif_clientdata,module,"JpegQTables tag has incorrect count"); | 
 | 					return(0); | 
 | 				} | 
 | 				sp->qtable_offset_count=(uint8)ma; | 
 | 				mb=(uint64*)va_arg(ap,uint64*); | 
 | 				for (n=0; n<ma; n++) | 
 | 					sp->qtable_offset[n]=mb[n]; | 
 | 			} | 
 | 			break; | 
 | 		case TIFFTAG_JPEGDCTABLES: | 
 | 			ma=(uint32)va_arg(ap,uint32); | 
 | 			if (ma!=0) | 
 | 			{ | 
 | 				if (ma>3) | 
 | 				{ | 
 | 					TIFFErrorExt(tif->tif_clientdata,module,"JpegDcTables tag has incorrect count"); | 
 | 					return(0); | 
 | 				} | 
 | 				sp->dctable_offset_count=(uint8)ma; | 
 | 				mb=(uint64*)va_arg(ap,uint64*); | 
 | 				for (n=0; n<ma; n++) | 
 | 					sp->dctable_offset[n]=mb[n]; | 
 | 			} | 
 | 			break; | 
 | 		case TIFFTAG_JPEGACTABLES: | 
 | 			ma=(uint32)va_arg(ap,uint32); | 
 | 			if (ma!=0) | 
 | 			{ | 
 | 				if (ma>3) | 
 | 				{ | 
 | 					TIFFErrorExt(tif->tif_clientdata,module,"JpegAcTables tag has incorrect count"); | 
 | 					return(0); | 
 | 				} | 
 | 				sp->actable_offset_count=(uint8)ma; | 
 | 				mb=(uint64*)va_arg(ap,uint64*); | 
 | 				for (n=0; n<ma; n++) | 
 | 					sp->actable_offset[n]=mb[n]; | 
 | 			} | 
 | 			break; | 
 | 		case TIFFTAG_JPEGPROC: | 
 | 			sp->jpeg_proc=(uint8)va_arg(ap,uint16_vap); | 
 | 			break; | 
 | 		case TIFFTAG_JPEGRESTARTINTERVAL: | 
 | 			sp->restart_interval=(uint16)va_arg(ap,uint16_vap); | 
 | 			break; | 
 | 		default: | 
 | 			return (*sp->vsetparent)(tif,tag,ap); | 
 | 	} | 
 | 	fip = TIFFFieldWithTag(tif,tag); | 
 | 	if( fip == NULL ) /* shouldn't happen */ | 
 | 	    return(0); | 
 | 	TIFFSetFieldBit(tif,fip->field_bit); | 
 | 	tif->tif_flags|=TIFF_DIRTYDIRECT; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGPrintDir(TIFF* tif, FILE* fd, long flags) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 m; | 
 | 	(void)flags; | 
 | 	assert(sp!=NULL); | 
 | 	if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMAT)) | 
 | 		fprintf(fd,"  JpegInterchangeFormat: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format);   | 
 | 	if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH)) | 
 | 		fprintf(fd,"  JpegInterchangeFormatLength: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format_length);   | 
 | 	if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGQTABLES)) | 
 | 	{ | 
 | 		fprintf(fd,"  JpegQTables:"); | 
 | 		for (m=0; m<sp->qtable_offset_count; m++) | 
 | 			fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->qtable_offset[m]); | 
 | 		fprintf(fd,"\n"); | 
 | 	} | 
 | 	if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGDCTABLES)) | 
 | 	{ | 
 | 		fprintf(fd,"  JpegDcTables:"); | 
 | 		for (m=0; m<sp->dctable_offset_count; m++) | 
 | 			fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->dctable_offset[m]); | 
 | 		fprintf(fd,"\n"); | 
 | 	} | 
 | 	if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGACTABLES)) | 
 | 	{ | 
 | 		fprintf(fd,"  JpegAcTables:"); | 
 | 		for (m=0; m<sp->actable_offset_count; m++) | 
 | 			fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->actable_offset[m]); | 
 | 		fprintf(fd,"\n"); | 
 | 	} | 
 | 	if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGPROC)) | 
 | 		fprintf(fd,"  JpegProc: %u\n",(unsigned int)sp->jpeg_proc); | 
 | 	if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGRESTARTINTERVAL)) | 
 | 		fprintf(fd,"  JpegRestartInterval: %u\n",(unsigned int)sp->restart_interval); | 
 | 	if (sp->printdir) | 
 | 		(*sp->printdir)(tif, fd, flags); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGFixupTags(TIFF* tif) | 
 | { | 
 | 	(void) tif; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGSetupDecode(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGSetupDecode"; | 
 | 	TIFFWarningExt(tif->tif_clientdata,module,"Depreciated and troublesome old-style JPEG compression mode, please convert to new-style JPEG compression and notify vendor of writing software"); | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGPreDecode(TIFF* tif, uint16 s) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint32 m; | 
 | 	if (sp->subsamplingcorrect_done==0) | 
 | 		OJPEGSubsamplingCorrect(tif); | 
 | 	if (sp->readheader_done==0) | 
 | 	{ | 
 | 		if (OJPEGReadHeaderInfo(tif)==0) | 
 | 			return(0); | 
 | 	} | 
 | 	if (sp->sos_end[s].log==0) | 
 | 	{ | 
 | 		if (OJPEGReadSecondarySos(tif,s)==0) | 
 | 			return(0); | 
 | 	} | 
 | 	if (isTiled(tif)) | 
 | 		m=tif->tif_curtile; | 
 | 	else | 
 | 		m=tif->tif_curstrip; | 
 | 	if ((sp->writeheader_done!=0) && ((sp->write_cursample!=s) || (sp->write_curstrile>m))) | 
 | 	{ | 
 | 		if (sp->libjpeg_session_active!=0) | 
 | 			OJPEGLibjpegSessionAbort(tif); | 
 | 		sp->writeheader_done=0; | 
 | 	} | 
 | 	if (sp->writeheader_done==0) | 
 | 	{ | 
 | 		sp->plane_sample_offset=(uint8)s; | 
 | 		sp->write_cursample=s; | 
 | 		sp->write_curstrile=s*tif->tif_dir.td_stripsperimage; | 
 | 		if ((sp->in_buffer_file_pos_log==0) || | 
 | 		    (sp->in_buffer_file_pos-sp->in_buffer_togo!=sp->sos_end[s].in_buffer_file_pos)) | 
 | 		{ | 
 | 			sp->in_buffer_source=sp->sos_end[s].in_buffer_source; | 
 | 			sp->in_buffer_next_strile=sp->sos_end[s].in_buffer_next_strile; | 
 | 			sp->in_buffer_file_pos=sp->sos_end[s].in_buffer_file_pos; | 
 | 			sp->in_buffer_file_pos_log=0; | 
 | 			sp->in_buffer_file_togo=sp->sos_end[s].in_buffer_file_togo; | 
 | 			sp->in_buffer_togo=0; | 
 | 			sp->in_buffer_cur=0; | 
 | 		} | 
 | 		if (OJPEGWriteHeaderInfo(tif)==0) | 
 | 			return(0); | 
 | 	} | 
 | 	while (sp->write_curstrile<m)           | 
 | 	{ | 
 | 		if (sp->libjpeg_jpeg_query_style==0) | 
 | 		{ | 
 | 			if (OJPEGPreDecodeSkipRaw(tif)==0) | 
 | 				return(0); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			if (OJPEGPreDecodeSkipScanlines(tif)==0) | 
 | 				return(0); | 
 | 		} | 
 | 		sp->write_curstrile++; | 
 | 	} | 
 | 	sp->decoder_ok = 1; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGPreDecodeSkipRaw(TIFF* tif) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint32 m; | 
 | 	m=sp->lines_per_strile; | 
 | 	if (sp->subsampling_convert_state!=0) | 
 | 	{ | 
 | 		if (sp->subsampling_convert_clines-sp->subsampling_convert_state>=m) | 
 | 		{ | 
 | 			sp->subsampling_convert_state+=m; | 
 | 			if (sp->subsampling_convert_state==sp->subsampling_convert_clines) | 
 | 				sp->subsampling_convert_state=0; | 
 | 			return(1); | 
 | 		} | 
 | 		m-=sp->subsampling_convert_clines-sp->subsampling_convert_state; | 
 | 		sp->subsampling_convert_state=0; | 
 |                 sp->error_in_raw_data_decoding=0; | 
 | 	} | 
 | 	while (m>=sp->subsampling_convert_clines) | 
 | 	{ | 
 | 		if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) | 
 | 			return(0); | 
 | 		m-=sp->subsampling_convert_clines; | 
 | 	} | 
 | 	if (m>0) | 
 | 	{ | 
 | 		if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) | 
 | 			return(0); | 
 | 		sp->subsampling_convert_state=m; | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGPreDecodeSkipScanlines(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGPreDecodeSkipScanlines"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint32 m; | 
 | 	if (sp->skip_buffer==NULL) | 
 | 	{ | 
 | 		sp->skip_buffer=_TIFFmalloc(sp->bytes_per_line); | 
 | 		if (sp->skip_buffer==NULL) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); | 
 | 			return(0); | 
 | 		} | 
 | 	} | 
 | 	for (m=0; m<sp->lines_per_strile; m++) | 
 | 	{ | 
 | 		if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&sp->skip_buffer,1)==0) | 
 | 			return(0); | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) | 
 | { | 
 |         static const char module[]="OJPEGDecode"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	(void)s; | 
 |         if( !sp->decoder_ok ) | 
 |         { | 
 |             TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized"); | 
 |             return 0; | 
 |         } | 
 |         if( sp->error_in_raw_data_decoding ) | 
 |         { | 
 |             return 0; | 
 |         } | 
 | 	if (sp->libjpeg_jpeg_query_style==0) | 
 | 	{ | 
 | 		if (OJPEGDecodeRaw(tif,buf,cc)==0) | 
 | 			return(0); | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		if (OJPEGDecodeScanlines(tif,buf,cc)==0) | 
 | 			return(0); | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc) | 
 | { | 
 | 	static const char module[]="OJPEGDecodeRaw"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8* m; | 
 | 	tmsize_t n; | 
 | 	uint8* oy; | 
 | 	uint8* ocb; | 
 | 	uint8* ocr; | 
 | 	uint8* p; | 
 | 	uint32 q; | 
 | 	uint8* r; | 
 | 	uint8 sx,sy; | 
 | 	if (cc%sp->bytes_per_line!=0) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read"); | 
 | 		return(0); | 
 | 	} | 
 | 	assert(cc>0); | 
 | 	m=buf; | 
 | 	n=cc; | 
 | 	do | 
 | 	{ | 
 | 		if (sp->subsampling_convert_state==0) | 
 | 		{ | 
 | 			const jpeg_decompress_struct* cinfo = &sp->libjpeg_jpeg_decompress_struct; | 
 | 			int width = 0; | 
 | 			int last_col_width = 0; | 
 | 			int jpeg_bytes; | 
 | 			int expected_bytes; | 
 | 			int i; | 
 | 			if (cinfo->MCUs_per_row == 0) | 
 | 			{ | 
 | 				sp->error_in_raw_data_decoding = 1; | 
 | 				return 0; | 
 | 			} | 
 | 			for (i = 0; i < cinfo->comps_in_scan; ++i) | 
 | 			{ | 
 | 				const jpeg_component_info* info = cinfo->cur_comp_info[i]; | 
 | #if JPEG_LIB_VERSION >= 70 | 
 | 				width += info->MCU_width * info->DCT_h_scaled_size; | 
 | 				last_col_width += info->last_col_width * info->DCT_h_scaled_size; | 
 | #else | 
 | 				width += info->MCU_width * info->DCT_scaled_size; | 
 | 				last_col_width += info->last_col_width * info->DCT_scaled_size; | 
 | #endif | 
 | 			} | 
 | 			jpeg_bytes = (cinfo->MCUs_per_row - 1) * width + last_col_width; | 
 | 			expected_bytes = sp->subsampling_convert_clinelenout * sp->subsampling_ver * sp->subsampling_hor; | 
 | 			if (jpeg_bytes != expected_bytes) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Inconsistent number of MCU in codestream"); | 
 | 				sp->error_in_raw_data_decoding = 1; | 
 | 				return(0); | 
 | 			} | 
 | 			if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) | 
 | 			{ | 
 | 				sp->error_in_raw_data_decoding = 1; | 
 | 				return(0); | 
 | 			} | 
 | 		} | 
 | 		oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen; | 
 | 		ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; | 
 | 		ocr=sp->subsampling_convert_crbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; | 
 | 		p=m; | 
 | 		for (q=0; q<sp->subsampling_convert_clinelenout; q++) | 
 | 		{ | 
 | 			r=oy; | 
 | 			for (sy=0; sy<sp->subsampling_ver; sy++) | 
 | 			{ | 
 | 				for (sx=0; sx<sp->subsampling_hor; sx++) | 
 | 					*p++=*r++; | 
 | 				r+=sp->subsampling_convert_ylinelen-sp->subsampling_hor; | 
 | 			} | 
 | 			oy+=sp->subsampling_hor; | 
 | 			*p++=*ocb++; | 
 | 			*p++=*ocr++; | 
 | 		} | 
 | 		sp->subsampling_convert_state++; | 
 | 		if (sp->subsampling_convert_state==sp->subsampling_convert_clines) | 
 | 			sp->subsampling_convert_state=0; | 
 | 		m+=sp->bytes_per_line; | 
 | 		n-=sp->bytes_per_line; | 
 | 	} while(n>0); | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGDecodeScanlines(TIFF* tif, uint8* buf, tmsize_t cc) | 
 | { | 
 | 	static const char module[]="OJPEGDecodeScanlines"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8* m; | 
 | 	tmsize_t n; | 
 | 	if (cc%sp->bytes_per_line!=0) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read"); | 
 | 		return(0); | 
 | 	} | 
 | 	assert(cc>0); | 
 | 	m=buf; | 
 | 	n=cc; | 
 | 	do | 
 | 	{ | 
 | 		if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&m,1)==0) | 
 | 			return(0); | 
 | 		m+=sp->bytes_per_line; | 
 | 		n-=sp->bytes_per_line; | 
 | 	} while(n>0); | 
 | 	return(1); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGPostDecode(TIFF* tif, uint8* buf, tmsize_t cc) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	(void)buf; | 
 | 	(void)cc; | 
 | 	sp->write_curstrile++; | 
 | 	if (sp->write_curstrile%tif->tif_dir.td_stripsperimage==0)   | 
 | 	{ | 
 | 		assert(sp->libjpeg_session_active!=0); | 
 | 		OJPEGLibjpegSessionAbort(tif); | 
 | 		sp->writeheader_done=0; | 
 | 	} | 
 | } | 
 |  | 
 | static int | 
 | OJPEGSetupEncode(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGSetupEncode"; | 
 | 	TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); | 
 | 	return(0); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGPreEncode(TIFF* tif, uint16 s) | 
 | { | 
 | 	static const char module[]="OJPEGPreEncode"; | 
 | 	(void)s; | 
 | 	TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); | 
 | 	return(0); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) | 
 | { | 
 | 	static const char module[]="OJPEGEncode"; | 
 | 	(void)buf; | 
 | 	(void)cc; | 
 | 	(void)s; | 
 | 	TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); | 
 | 	return(0); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGPostEncode(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGPostEncode"; | 
 | 	TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); | 
 | 	return(0); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGCleanup(TIFF* tif) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	if (sp!=0) | 
 | 	{ | 
 | 		tif->tif_tagmethods.vgetfield=sp->vgetparent; | 
 | 		tif->tif_tagmethods.vsetfield=sp->vsetparent; | 
 | 		tif->tif_tagmethods.printdir=sp->printdir; | 
 | 		if (sp->qtable[0]!=0) | 
 | 			_TIFFfree(sp->qtable[0]); | 
 | 		if (sp->qtable[1]!=0) | 
 | 			_TIFFfree(sp->qtable[1]); | 
 | 		if (sp->qtable[2]!=0) | 
 | 			_TIFFfree(sp->qtable[2]); | 
 | 		if (sp->qtable[3]!=0) | 
 | 			_TIFFfree(sp->qtable[3]); | 
 | 		if (sp->dctable[0]!=0) | 
 | 			_TIFFfree(sp->dctable[0]); | 
 | 		if (sp->dctable[1]!=0) | 
 | 			_TIFFfree(sp->dctable[1]); | 
 | 		if (sp->dctable[2]!=0) | 
 | 			_TIFFfree(sp->dctable[2]); | 
 | 		if (sp->dctable[3]!=0) | 
 | 			_TIFFfree(sp->dctable[3]); | 
 | 		if (sp->actable[0]!=0) | 
 | 			_TIFFfree(sp->actable[0]); | 
 | 		if (sp->actable[1]!=0) | 
 | 			_TIFFfree(sp->actable[1]); | 
 | 		if (sp->actable[2]!=0) | 
 | 			_TIFFfree(sp->actable[2]); | 
 | 		if (sp->actable[3]!=0) | 
 | 			_TIFFfree(sp->actable[3]); | 
 | 		if (sp->libjpeg_session_active!=0) | 
 | 			OJPEGLibjpegSessionAbort(tif); | 
 | 		if (sp->subsampling_convert_ycbcrbuf!=0) | 
 | 			_TIFFfree(sp->subsampling_convert_ycbcrbuf); | 
 | 		if (sp->subsampling_convert_ycbcrimage!=0) | 
 | 			_TIFFfree(sp->subsampling_convert_ycbcrimage); | 
 | 		if (sp->skip_buffer!=0) | 
 | 			_TIFFfree(sp->skip_buffer); | 
 | 		_TIFFfree(sp); | 
 | 		tif->tif_data=NULL; | 
 | 		_TIFFSetDefaultCompressionState(tif); | 
 | 	} | 
 | } | 
 |  | 
 | static void | 
 | OJPEGSubsamplingCorrect(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGSubsamplingCorrect"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 mh; | 
 | 	uint8 mv; | 
 |          | 
 | 	assert(sp->subsamplingcorrect_done==0); | 
 | 	if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) && | 
 | 	    (tif->tif_dir.td_photometric!=PHOTOMETRIC_ITULAB))) | 
 | 	{ | 
 | 		if (sp->subsampling_tag!=0) | 
 | 			TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag not appropriate for this Photometric and/or SamplesPerPixel"); | 
 | 		sp->subsampling_hor=1; | 
 | 		sp->subsampling_ver=1; | 
 | 		sp->subsampling_force_desubsampling_inside_decompression=0; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		sp->subsamplingcorrect_done=1; | 
 | 		mh=sp->subsampling_hor; | 
 | 		mv=sp->subsampling_ver; | 
 | 		sp->subsamplingcorrect=1; | 
 | 		OJPEGReadHeaderInfoSec(tif); | 
 | 		if (sp->subsampling_force_desubsampling_inside_decompression!=0) | 
 | 		{ | 
 | 			sp->subsampling_hor=1; | 
 | 			sp->subsampling_ver=1; | 
 | 		} | 
 | 		sp->subsamplingcorrect=0; | 
 | 		if (((sp->subsampling_hor!=mh) || (sp->subsampling_ver!=mv)) && (sp->subsampling_force_desubsampling_inside_decompression==0)) | 
 | 		{ | 
 | 			if (sp->subsampling_tag==0) | 
 | 				TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data [%d,%d] does not match default values [2,2]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver); | 
 | 			else | 
 | 				TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data [%d,%d] does not match subsampling tag values [%d,%d]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver,mh,mv); | 
 | 		} | 
 | 		if (sp->subsampling_force_desubsampling_inside_decompression!=0) | 
 | 		{ | 
 | 			if (sp->subsampling_tag==0) | 
 | 				TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data does not match default values [2,2] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression"); | 
 | 			else | 
 | 				TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data does not match subsampling tag values [%d,%d] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression",mh,mv); | 
 | 		} | 
 | 		if (sp->subsampling_force_desubsampling_inside_decompression==0) | 
 | 		{ | 
 | 			if (sp->subsampling_hor<sp->subsampling_ver) | 
 | 				TIFFWarningExt(tif->tif_clientdata,module,"Subsampling values [%d,%d] are not allowed in TIFF",sp->subsampling_hor,sp->subsampling_ver); | 
 | 		} | 
 | 	} | 
 | 	sp->subsamplingcorrect_done=1; | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfo(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGReadHeaderInfo"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	assert(sp->readheader_done==0); | 
 | 	sp->image_width=tif->tif_dir.td_imagewidth; | 
 | 	sp->image_length=tif->tif_dir.td_imagelength; | 
 | 	if (isTiled(tif)) | 
 | 	{ | 
 | 		sp->strile_width=tif->tif_dir.td_tilewidth; | 
 | 		sp->strile_length=tif->tif_dir.td_tilelength; | 
 | 		sp->strile_length_total=((sp->image_length+sp->strile_length-1)/sp->strile_length)*sp->strile_length; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		sp->strile_width=sp->image_width; | 
 | 		sp->strile_length=tif->tif_dir.td_rowsperstrip; | 
 | 		sp->strile_length_total=sp->image_length; | 
 | 	} | 
 | 	if (tif->tif_dir.td_samplesperpixel==1) | 
 | 	{ | 
 | 		sp->samples_per_pixel=1; | 
 | 		sp->plane_sample_offset=0; | 
 | 		sp->samples_per_pixel_per_plane=sp->samples_per_pixel; | 
 | 		sp->subsampling_hor=1; | 
 | 		sp->subsampling_ver=1; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		if (tif->tif_dir.td_samplesperpixel!=3) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"SamplesPerPixel %d not supported for this compression scheme",sp->samples_per_pixel); | 
 | 			return(0); | 
 | 		} | 
 | 		sp->samples_per_pixel=3; | 
 | 		sp->plane_sample_offset=0; | 
 | 		if (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG) | 
 | 			sp->samples_per_pixel_per_plane=3; | 
 | 		else | 
 | 			sp->samples_per_pixel_per_plane=1; | 
 | 	} | 
 | 	if (sp->strile_length<sp->image_length) | 
 | 	{ | 
 | 		if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) || | 
 | 		    ((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4))) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Invalid subsampling values"); | 
 | 			return(0); | 
 | 		} | 
 | 		if (sp->strile_length%(sp->subsampling_ver*8)!=0) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length"); | 
 | 			return(0); | 
 | 		} | 
 | 		sp->restart_interval=(uint16)(((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8))); | 
 | 	} | 
 | 	if (OJPEGReadHeaderInfoSec(tif)==0) | 
 | 		return(0); | 
 | 	sp->sos_end[0].log=1; | 
 | 	sp->sos_end[0].in_buffer_source=sp->in_buffer_source; | 
 | 	sp->sos_end[0].in_buffer_next_strile=sp->in_buffer_next_strile; | 
 | 	sp->sos_end[0].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo; | 
 | 	sp->sos_end[0].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo;  | 
 | 	sp->readheader_done=1; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadSecondarySos(TIFF* tif, uint16 s) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 m; | 
 | 	assert(s>0); | 
 | 	assert(s<3); | 
 | 	assert(sp->sos_end[0].log!=0); | 
 | 	assert(sp->sos_end[s].log==0); | 
 | 	sp->plane_sample_offset=(uint8)(s-1); | 
 | 	while(sp->sos_end[sp->plane_sample_offset].log==0) | 
 | 		sp->plane_sample_offset--; | 
 | 	sp->in_buffer_source=sp->sos_end[sp->plane_sample_offset].in_buffer_source; | 
 | 	sp->in_buffer_next_strile=sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile; | 
 | 	sp->in_buffer_file_pos=sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos; | 
 | 	sp->in_buffer_file_pos_log=0; | 
 | 	sp->in_buffer_file_togo=sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo; | 
 | 	sp->in_buffer_togo=0; | 
 | 	sp->in_buffer_cur=0; | 
 | 	while(sp->plane_sample_offset<s) | 
 | 	{ | 
 | 		do | 
 | 		{ | 
 | 			if (OJPEGReadByte(sp,&m)==0) | 
 | 				return(0); | 
 | 			if (m==255) | 
 | 			{ | 
 | 				do | 
 | 				{ | 
 | 					if (OJPEGReadByte(sp,&m)==0) | 
 | 						return(0); | 
 | 					if (m!=255) | 
 | 						break; | 
 | 				} while(1); | 
 | 				if (m==JPEG_MARKER_SOS) | 
 | 					break; | 
 | 			} | 
 | 		} while(1); | 
 | 		sp->plane_sample_offset++; | 
 | 		if (OJPEGReadHeaderInfoSecStreamSos(tif)==0) | 
 | 			return(0); | 
 | 		sp->sos_end[sp->plane_sample_offset].log=1; | 
 | 		sp->sos_end[sp->plane_sample_offset].in_buffer_source=sp->in_buffer_source; | 
 | 		sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile=sp->in_buffer_next_strile; | 
 | 		sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo; | 
 | 		sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo; | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGWriteHeaderInfo(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGWriteHeaderInfo"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8** m; | 
 | 	uint32 n; | 
 | 	/* if a previous attempt failed, don't try again */ | 
 | 	if (sp->libjpeg_session_active != 0)  | 
 | 		return 0; | 
 | 	sp->out_state=ososSoi; | 
 | 	sp->restart_index=0; | 
 | 	jpeg_std_error(&(sp->libjpeg_jpeg_error_mgr)); | 
 | 	sp->libjpeg_jpeg_error_mgr.output_message=OJPEGLibjpegJpegErrorMgrOutputMessage; | 
 | 	sp->libjpeg_jpeg_error_mgr.error_exit=OJPEGLibjpegJpegErrorMgrErrorExit; | 
 | 	sp->libjpeg_jpeg_decompress_struct.err=&(sp->libjpeg_jpeg_error_mgr); | 
 | 	sp->libjpeg_jpeg_decompress_struct.client_data=(void*)tif; | 
 | 	if (jpeg_create_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0) | 
 | 		return(0); | 
 | 	sp->libjpeg_session_active=1; | 
 | 	sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=0; | 
 | 	sp->libjpeg_jpeg_source_mgr.init_source=OJPEGLibjpegJpegSourceMgrInitSource; | 
 | 	sp->libjpeg_jpeg_source_mgr.fill_input_buffer=OJPEGLibjpegJpegSourceMgrFillInputBuffer; | 
 | 	sp->libjpeg_jpeg_source_mgr.skip_input_data=OJPEGLibjpegJpegSourceMgrSkipInputData; | 
 | 	sp->libjpeg_jpeg_source_mgr.resync_to_restart=OJPEGLibjpegJpegSourceMgrResyncToRestart; | 
 | 	sp->libjpeg_jpeg_source_mgr.term_source=OJPEGLibjpegJpegSourceMgrTermSource; | 
 | 	sp->libjpeg_jpeg_decompress_struct.src=&(sp->libjpeg_jpeg_source_mgr); | 
 | 	if (jpeg_read_header_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),1)==0) | 
 | 		return(0); | 
 | 	if ((sp->subsampling_force_desubsampling_inside_decompression==0) && (sp->samples_per_pixel_per_plane>1)) | 
 | 	{ | 
 | 		sp->libjpeg_jpeg_decompress_struct.raw_data_out=1; | 
 | #if JPEG_LIB_VERSION >= 70 | 
 | 		sp->libjpeg_jpeg_decompress_struct.do_fancy_upsampling=FALSE; | 
 | #endif | 
 | 		sp->libjpeg_jpeg_query_style=0; | 
 | 		if (sp->subsampling_convert_log==0) | 
 | 		{ | 
 | 			assert(sp->subsampling_convert_ycbcrbuf==0); | 
 | 			assert(sp->subsampling_convert_ycbcrimage==0); | 
 | 			sp->subsampling_convert_ylinelen=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8)*sp->subsampling_hor*8); | 
 | 			sp->subsampling_convert_ylines=sp->subsampling_ver*8; | 
 | 			sp->subsampling_convert_clinelen=sp->subsampling_convert_ylinelen/sp->subsampling_hor; | 
 | 			sp->subsampling_convert_clines=8; | 
 | 			sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines; | 
 | 			sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines; | 
 | 			sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen; | 
 |                         /* The calloc is not normally necessary, except in some edge/broken cases */ | 
 |                         /* for example for a tiled image of height 1 with a tile height of 1 and subsampling_hor=subsampling_ver=2 */ | 
 |                         /* In that case, libjpeg will only fill the 8 first lines of the 16 lines */ | 
 |                         /* See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16844 */ | 
 |                         /* Even if this case is allowed (?), its handling is broken because OJPEGPreDecode() should also likely */ | 
 |                         /* reset subsampling_convert_state to 0 when changing tile. */ | 
 | 			sp->subsampling_convert_ycbcrbuf=_TIFFcalloc(1, sp->subsampling_convert_ycbcrbuflen); | 
 | 			if (sp->subsampling_convert_ycbcrbuf==0) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); | 
 | 				return(0); | 
 | 			} | 
 | 			sp->subsampling_convert_ybuf=sp->subsampling_convert_ycbcrbuf; | 
 | 			sp->subsampling_convert_cbbuf=sp->subsampling_convert_ybuf+sp->subsampling_convert_ybuflen; | 
 | 			sp->subsampling_convert_crbuf=sp->subsampling_convert_cbbuf+sp->subsampling_convert_cbuflen; | 
 | 			sp->subsampling_convert_ycbcrimagelen=3+sp->subsampling_convert_ylines+2*sp->subsampling_convert_clines; | 
 | 			sp->subsampling_convert_ycbcrimage=_TIFFmalloc(sp->subsampling_convert_ycbcrimagelen*sizeof(uint8*)); | 
 | 			if (sp->subsampling_convert_ycbcrimage==0) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); | 
 | 				return(0); | 
 | 			} | 
 | 			m=sp->subsampling_convert_ycbcrimage; | 
 | 			*m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3); | 
 | 			*m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines); | 
 | 			*m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines+sp->subsampling_convert_clines); | 
 | 			for (n=0; n<sp->subsampling_convert_ylines; n++) | 
 | 				*m++=sp->subsampling_convert_ybuf+n*sp->subsampling_convert_ylinelen; | 
 | 			for (n=0; n<sp->subsampling_convert_clines; n++) | 
 | 				*m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen; | 
 | 			for (n=0; n<sp->subsampling_convert_clines; n++) | 
 | 				*m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen; | 
 | 			sp->subsampling_convert_clinelenout=sp->strile_width/sp->subsampling_hor + ((sp->strile_width % sp->subsampling_hor) != 0 ? 1 : 0); | 
 | 			sp->subsampling_convert_state=0; | 
 | 			sp->error_in_raw_data_decoding=0; | 
 | 			sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2); | 
 | 			sp->lines_per_strile=sp->strile_length/sp->subsampling_ver + ((sp->strile_length % sp->subsampling_ver) != 0 ? 1 : 0); | 
 | 			sp->subsampling_convert_log=1; | 
 | 		} | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		sp->libjpeg_jpeg_decompress_struct.jpeg_color_space=JCS_UNKNOWN; | 
 | 		sp->libjpeg_jpeg_decompress_struct.out_color_space=JCS_UNKNOWN; | 
 | 		sp->libjpeg_jpeg_query_style=1; | 
 | 		sp->bytes_per_line=sp->samples_per_pixel_per_plane*sp->strile_width; | 
 | 		sp->lines_per_strile=sp->strile_length; | 
 | 	} | 
 | 	if (jpeg_start_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0) | 
 | 		return(0); | 
 | 	sp->writeheader_done=1; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGLibjpegSessionAbort(TIFF* tif) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	assert(sp->libjpeg_session_active!=0); | 
 | 	jpeg_destroy((jpeg_common_struct*)(&(sp->libjpeg_jpeg_decompress_struct))); | 
 | 	sp->libjpeg_session_active=0; | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSec(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGReadHeaderInfoSec"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 m; | 
 | 	uint16 n; | 
 | 	uint8 o; | 
 | 	if (sp->file_size==0) | 
 | 		sp->file_size=TIFFGetFileSize(tif); | 
 | 	if (sp->jpeg_interchange_format!=0) | 
 | 	{ | 
 | 		if (sp->jpeg_interchange_format>=sp->file_size) | 
 | 		{ | 
 | 			sp->jpeg_interchange_format=0; | 
 | 			sp->jpeg_interchange_format_length=0; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			if ((sp->jpeg_interchange_format_length==0) || | 
 |                             (sp->jpeg_interchange_format > TIFF_UINT64_MAX - sp->jpeg_interchange_format_length) || | 
 |                             (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size)) | 
 | 				sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format; | 
 | 		} | 
 | 	} | 
 | 	sp->in_buffer_source=osibsNotSetYet; | 
 | 	sp->in_buffer_next_strile=0; | 
 | 	sp->in_buffer_strile_count=tif->tif_dir.td_nstrips; | 
 | 	sp->in_buffer_file_togo=0; | 
 | 	sp->in_buffer_togo=0; | 
 | 	do | 
 | 	{ | 
 | 		if (OJPEGReadBytePeek(sp,&m)==0) | 
 | 			return(0); | 
 | 		if (m!=255) | 
 | 			break; | 
 | 		OJPEGReadByteAdvance(sp); | 
 | 		do | 
 | 		{ | 
 | 			if (OJPEGReadByte(sp,&m)==0) | 
 | 				return(0); | 
 | 		} while(m==255); | 
 | 		switch(m) | 
 | 		{ | 
 | 			case JPEG_MARKER_SOI: | 
 | 				/* this type of marker has no data, and should be skipped */ | 
 | 				break; | 
 | 			case JPEG_MARKER_COM: | 
 | 			case JPEG_MARKER_APP0: | 
 | 			case JPEG_MARKER_APP0+1: | 
 | 			case JPEG_MARKER_APP0+2: | 
 | 			case JPEG_MARKER_APP0+3: | 
 | 			case JPEG_MARKER_APP0+4: | 
 | 			case JPEG_MARKER_APP0+5: | 
 | 			case JPEG_MARKER_APP0+6: | 
 | 			case JPEG_MARKER_APP0+7: | 
 | 			case JPEG_MARKER_APP0+8: | 
 | 			case JPEG_MARKER_APP0+9: | 
 | 			case JPEG_MARKER_APP0+10: | 
 | 			case JPEG_MARKER_APP0+11: | 
 | 			case JPEG_MARKER_APP0+12: | 
 | 			case JPEG_MARKER_APP0+13: | 
 | 			case JPEG_MARKER_APP0+14: | 
 | 			case JPEG_MARKER_APP0+15: | 
 | 				/* this type of marker has data, but it has no use to us (and no place here) and should be skipped */ | 
 | 				if (OJPEGReadWord(sp,&n)==0) | 
 | 					return(0); | 
 | 				if (n<2) | 
 | 				{ | 
 | 					if (sp->subsamplingcorrect==0) | 
 | 						TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data"); | 
 | 					return(0); | 
 | 				} | 
 | 				if (n>2) | 
 | 					OJPEGReadSkip(sp,n-2); | 
 | 				break; | 
 | 			case JPEG_MARKER_DRI: | 
 | 				if (OJPEGReadHeaderInfoSecStreamDri(tif)==0) | 
 | 					return(0); | 
 | 				break; | 
 | 			case JPEG_MARKER_DQT: | 
 | 				if (OJPEGReadHeaderInfoSecStreamDqt(tif)==0) | 
 | 					return(0); | 
 | 				break; | 
 | 			case JPEG_MARKER_DHT: | 
 | 				if (OJPEGReadHeaderInfoSecStreamDht(tif)==0) | 
 | 					return(0); | 
 | 				break; | 
 | 			case JPEG_MARKER_SOF0: | 
 | 			case JPEG_MARKER_SOF1: | 
 | 			case JPEG_MARKER_SOF3: | 
 | 				if (OJPEGReadHeaderInfoSecStreamSof(tif,m)==0) | 
 | 					return(0); | 
 | 				if (sp->subsamplingcorrect!=0) | 
 | 					return(1); | 
 | 				break; | 
 | 			case JPEG_MARKER_SOS: | 
 | 				if (sp->subsamplingcorrect!=0) | 
 | 					return(1); | 
 | 				assert(sp->plane_sample_offset==0); | 
 | 				if (OJPEGReadHeaderInfoSecStreamSos(tif)==0) | 
 | 					return(0); | 
 | 				break; | 
 | 			default: | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Unknown marker type %d in JPEG data",m); | 
 | 				return(0); | 
 | 		} | 
 | 	} while(m!=JPEG_MARKER_SOS); | 
 | 	if (sp->subsamplingcorrect) | 
 | 		return(1); | 
 | 	if (sp->sof_log==0) | 
 | 	{ | 
 | 		if (OJPEGReadHeaderInfoSecTablesQTable(tif)==0) | 
 | 			return(0); | 
 | 		sp->sof_marker_id=JPEG_MARKER_SOF0; | 
 | 		for (o=0; o<sp->samples_per_pixel; o++) | 
 | 			sp->sof_c[o]=o; | 
 | 		sp->sof_hv[0]=((sp->subsampling_hor<<4)|sp->subsampling_ver); | 
 | 		for (o=1; o<sp->samples_per_pixel; o++) | 
 | 			sp->sof_hv[o]=17; | 
 | 		sp->sof_x=sp->strile_width; | 
 | 		sp->sof_y=sp->strile_length_total; | 
 | 		sp->sof_log=1; | 
 | 		if (OJPEGReadHeaderInfoSecTablesDcTable(tif)==0) | 
 | 			return(0); | 
 | 		if (OJPEGReadHeaderInfoSecTablesAcTable(tif)==0) | 
 | 			return(0); | 
 | 		for (o=1; o<sp->samples_per_pixel; o++) | 
 | 			sp->sos_cs[o]=o; | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSecStreamDri(TIFF* tif) | 
 | { | 
 | 	/* This could easily cause trouble in some cases... but no such cases have | 
 |            occurred so far */ | 
 | 	static const char module[]="OJPEGReadHeaderInfoSecStreamDri"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint16 m; | 
 | 	if (OJPEGReadWord(sp,&m)==0) | 
 | 		return(0); | 
 | 	if (m!=4) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DRI marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	if (OJPEGReadWord(sp,&m)==0) | 
 | 		return(0); | 
 | 	sp->restart_interval=m; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif) | 
 | { | 
 | 	/* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */ | 
 | 	static const char module[]="OJPEGReadHeaderInfoSecStreamDqt"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint16 m; | 
 | 	uint32 na; | 
 | 	uint8* nb; | 
 | 	uint8 o; | 
 | 	if (OJPEGReadWord(sp,&m)==0) | 
 | 		return(0); | 
 | 	if (m<=2) | 
 | 	{ | 
 | 		if (sp->subsamplingcorrect==0) | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	if (sp->subsamplingcorrect!=0) | 
 | 		OJPEGReadSkip(sp,m-2); | 
 | 	else | 
 | 	{ | 
 | 		m-=2; | 
 | 		do | 
 | 		{ | 
 | 			if (m<65) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); | 
 | 				return(0); | 
 | 			} | 
 | 			na=sizeof(uint32)+69; | 
 | 			nb=_TIFFmalloc(na); | 
 | 			if (nb==0) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); | 
 | 				return(0); | 
 | 			} | 
 | 			*(uint32*)nb=na; | 
 | 			nb[sizeof(uint32)]=255; | 
 | 			nb[sizeof(uint32)+1]=JPEG_MARKER_DQT; | 
 | 			nb[sizeof(uint32)+2]=0; | 
 | 			nb[sizeof(uint32)+3]=67; | 
 | 			if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0) { | 
 | 				_TIFFfree(nb); | 
 | 				return(0); | 
 | 			} | 
 | 			o=nb[sizeof(uint32)+4]&15; | 
 | 			if (3<o) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); | 
 | 				_TIFFfree(nb); | 
 | 				return(0); | 
 | 			} | 
 | 			if (sp->qtable[o]!=0) | 
 | 				_TIFFfree(sp->qtable[o]); | 
 | 			sp->qtable[o]=nb; | 
 | 			m-=65; | 
 | 		} while(m>0); | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSecStreamDht(TIFF* tif) | 
 | { | 
 | 	/* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */ | 
 | 	/* TODO: the following assumes there is only one table in this marker... but i'm not quite sure that assumption is guaranteed correct */ | 
 | 	static const char module[]="OJPEGReadHeaderInfoSecStreamDht"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint16 m; | 
 | 	uint32 na; | 
 | 	uint8* nb; | 
 | 	uint8 o; | 
 | 	if (OJPEGReadWord(sp,&m)==0) | 
 | 		return(0); | 
 | 	if (m<=2) | 
 | 	{ | 
 | 		if (sp->subsamplingcorrect==0) | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	if (sp->subsamplingcorrect!=0) | 
 | 	{ | 
 | 		OJPEGReadSkip(sp,m-2); | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		na=sizeof(uint32)+2+m; | 
 | 		nb=_TIFFmalloc(na); | 
 | 		if (nb==0) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); | 
 | 			return(0); | 
 | 		} | 
 | 		*(uint32*)nb=na; | 
 | 		nb[sizeof(uint32)]=255; | 
 | 		nb[sizeof(uint32)+1]=JPEG_MARKER_DHT; | 
 | 		nb[sizeof(uint32)+2]=(m>>8); | 
 | 		nb[sizeof(uint32)+3]=(m&255); | 
 | 		if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0) { | 
 |                         _TIFFfree(nb); | 
 | 			return(0); | 
 |                 } | 
 | 		o=nb[sizeof(uint32)+4]; | 
 | 		if ((o&240)==0) | 
 | 		{ | 
 | 			if (3<o) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); | 
 |                                 _TIFFfree(nb); | 
 | 				return(0); | 
 | 			} | 
 | 			if (sp->dctable[o]!=0) | 
 | 				_TIFFfree(sp->dctable[o]); | 
 | 			sp->dctable[o]=nb; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			if ((o&240)!=16) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); | 
 |                                 _TIFFfree(nb); | 
 | 				return(0); | 
 | 			} | 
 | 			o&=15; | 
 | 			if (3<o) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); | 
 |                                 _TIFFfree(nb); | 
 | 				return(0); | 
 | 			} | 
 | 			if (sp->actable[o]!=0) | 
 | 				_TIFFfree(sp->actable[o]); | 
 | 			sp->actable[o]=nb; | 
 | 		} | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id) | 
 | { | 
 | 	/* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */ | 
 | 	static const char module[]="OJPEGReadHeaderInfoSecStreamSof"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint16 m; | 
 | 	uint16 n; | 
 | 	uint8 o; | 
 | 	uint16 p; | 
 | 	uint16 q; | 
 | 	if (sp->sof_log!=0) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	if (sp->subsamplingcorrect==0) | 
 | 		sp->sof_marker_id=marker_id; | 
 | 	/* Lf: data length */ | 
 | 	if (OJPEGReadWord(sp,&m)==0) | 
 | 		return(0); | 
 | 	if (m<11) | 
 | 	{ | 
 | 		if (sp->subsamplingcorrect==0) | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	m-=8; | 
 | 	if (m%3!=0) | 
 | 	{ | 
 | 		if (sp->subsamplingcorrect==0) | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	n=m/3; | 
 | 	if (sp->subsamplingcorrect==0) | 
 | 	{ | 
 | 		if (n!=sp->samples_per_pixel) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of samples"); | 
 | 			return(0); | 
 | 		} | 
 | 	} | 
 | 	/* P: Sample precision */ | 
 | 	if (OJPEGReadByte(sp,&o)==0) | 
 | 		return(0); | 
 | 	if (o!=8) | 
 | 	{ | 
 | 		if (sp->subsamplingcorrect==0) | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of bits per sample"); | 
 | 		return(0); | 
 | 	} | 
 | 	/* Y: Number of lines, X: Number of samples per line */ | 
 | 	if (sp->subsamplingcorrect) | 
 | 		OJPEGReadSkip(sp,4); | 
 | 	else | 
 | 	{ | 
 | 		/* Y: Number of lines */ | 
 | 		if (OJPEGReadWord(sp,&p)==0) | 
 | 			return(0); | 
 | 		if (((uint32)p<sp->image_length) && ((uint32)p<sp->strile_length_total)) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected height"); | 
 | 			return(0); | 
 | 		} | 
 | 		sp->sof_y=p; | 
 | 		/* X: Number of samples per line */ | 
 | 		if (OJPEGReadWord(sp,&p)==0) | 
 | 			return(0); | 
 | 		if (((uint32)p<sp->image_width) && ((uint32)p<sp->strile_width)) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width"); | 
 | 			return(0); | 
 | 		} | 
 | 		if ((uint32)p>sp->strile_width) | 
 | 		{ | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data image width exceeds expected image width"); | 
 | 			return(0); | 
 | 		} | 
 | 		sp->sof_x=p; | 
 | 	} | 
 | 	/* Nf: Number of image components in frame */ | 
 | 	if (OJPEGReadByte(sp,&o)==0) | 
 | 		return(0); | 
 | 	if (o!=n) | 
 | 	{ | 
 | 		if (sp->subsamplingcorrect==0) | 
 | 			TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	/* per component stuff */ | 
 | 	/* TODO: double-check that flow implies that n cannot be as big as to make us overflow sof_c, sof_hv and sof_tq arrays */ | 
 | 	for (q=0; q<n; q++) | 
 | 	{ | 
 | 		/* C: Component identifier */ | 
 | 		if (OJPEGReadByte(sp,&o)==0) | 
 | 			return(0); | 
 | 		if (sp->subsamplingcorrect==0) | 
 | 			sp->sof_c[q]=o; | 
 | 		/* H: Horizontal sampling factor, and V: Vertical sampling factor */ | 
 | 		if (OJPEGReadByte(sp,&o)==0) | 
 | 			return(0); | 
 | 		if (sp->subsamplingcorrect!=0) | 
 | 		{ | 
 | 			if (q==0) | 
 | 			{ | 
 | 				sp->subsampling_hor=(o>>4); | 
 | 				sp->subsampling_ver=(o&15); | 
 | 				if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) || | 
 | 					((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4))) | 
 | 					sp->subsampling_force_desubsampling_inside_decompression=1; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				if (o!=17) | 
 | 					sp->subsampling_force_desubsampling_inside_decompression=1; | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			sp->sof_hv[q]=o; | 
 | 			if (sp->subsampling_force_desubsampling_inside_decompression==0) | 
 | 			{ | 
 | 				if (q==0) | 
 | 				{ | 
 | 					if (o!=((sp->subsampling_hor<<4)|sp->subsampling_ver)) | 
 | 					{ | 
 | 						TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values"); | 
 | 						return(0); | 
 | 					} | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					if (o!=17) | 
 | 					{ | 
 | 						TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values"); | 
 | 						return(0); | 
 | 					} | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 		/* Tq: Quantization table destination selector */ | 
 | 		if (OJPEGReadByte(sp,&o)==0) | 
 | 			return(0); | 
 | 		if (sp->subsamplingcorrect==0) | 
 | 			sp->sof_tq[q]=o; | 
 | 	} | 
 | 	if (sp->subsamplingcorrect==0) | 
 | 		sp->sof_log=1; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSecStreamSos(TIFF* tif) | 
 | { | 
 | 	/* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */ | 
 | 	static const char module[]="OJPEGReadHeaderInfoSecStreamSos"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint16 m; | 
 | 	uint8 n; | 
 | 	uint8 o; | 
 | 	assert(sp->subsamplingcorrect==0); | 
 | 	if (sp->sof_log==0) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	/* Ls */ | 
 | 	if (OJPEGReadWord(sp,&m)==0) | 
 | 		return(0); | 
 | 	if (m!=6+sp->samples_per_pixel_per_plane*2) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	/* Ns */ | 
 | 	if (OJPEGReadByte(sp,&n)==0) | 
 | 		return(0); | 
 | 	if (n!=sp->samples_per_pixel_per_plane) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); | 
 | 		return(0); | 
 | 	} | 
 | 	/* Cs, Td, and Ta */ | 
 | 	for (o=0; o<sp->samples_per_pixel_per_plane; o++) | 
 | 	{ | 
 | 		/* Cs */ | 
 | 		if (OJPEGReadByte(sp,&n)==0) | 
 | 			return(0); | 
 | 		sp->sos_cs[sp->plane_sample_offset+o]=n; | 
 | 		/* Td and Ta */ | 
 | 		if (OJPEGReadByte(sp,&n)==0) | 
 | 			return(0); | 
 | 		sp->sos_tda[sp->plane_sample_offset+o]=n; | 
 | 	} | 
 | 	/* skip Ss, Se, Ah, en Al -> no check, as per Tom Lane recommendation, as per LibJpeg source */ | 
 | 	OJPEGReadSkip(sp,3); | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGReadHeaderInfoSecTablesQTable"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 m; | 
 | 	uint8 n; | 
 | 	uint32 oa; | 
 | 	uint8* ob; | 
 | 	uint32 p; | 
 | 	if (sp->qtable_offset[0]==0) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); | 
 | 		return(0); | 
 | 	} | 
 | 	sp->in_buffer_file_pos_log=0; | 
 | 	for (m=0; m<sp->samples_per_pixel; m++) | 
 | 	{ | 
 | 		if ((sp->qtable_offset[m]!=0) && ((m==0) || (sp->qtable_offset[m]!=sp->qtable_offset[m-1]))) | 
 | 		{ | 
 | 			for (n=0; n<m-1; n++) | 
 | 			{ | 
 | 				if (sp->qtable_offset[m]==sp->qtable_offset[n]) | 
 | 				{ | 
 | 					TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegQTables tag value"); | 
 | 					return(0); | 
 | 				} | 
 | 			} | 
 | 			oa=sizeof(uint32)+69; | 
 | 			ob=_TIFFmalloc(oa); | 
 | 			if (ob==0) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); | 
 | 				return(0); | 
 | 			} | 
 | 			*(uint32*)ob=oa; | 
 | 			ob[sizeof(uint32)]=255; | 
 | 			ob[sizeof(uint32)+1]=JPEG_MARKER_DQT; | 
 | 			ob[sizeof(uint32)+2]=0; | 
 | 			ob[sizeof(uint32)+3]=67; | 
 | 			ob[sizeof(uint32)+4]=m; | 
 | 			TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET);  | 
 | 			p=(uint32)TIFFReadFile(tif,&ob[sizeof(uint32)+5],64); | 
 | 			if (p!=64) | 
 |                         { | 
 |                                 _TIFFfree(ob); | 
 | 				return(0); | 
 |                         } | 
 | 			if (sp->qtable[m]!=0) | 
 | 				_TIFFfree(sp->qtable[m]); | 
 | 			sp->qtable[m]=ob; | 
 | 			sp->sof_tq[m]=m; | 
 | 		} | 
 | 		else | 
 | 			sp->sof_tq[m]=sp->sof_tq[m-1]; | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGReadHeaderInfoSecTablesDcTable"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 m; | 
 | 	uint8 n; | 
 | 	uint8 o[16]; | 
 | 	uint32 p; | 
 | 	uint32 q; | 
 | 	uint32 ra; | 
 | 	uint8* rb; | 
 | 	if (sp->dctable_offset[0]==0) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); | 
 | 		return(0); | 
 | 	} | 
 | 	sp->in_buffer_file_pos_log=0; | 
 | 	for (m=0; m<sp->samples_per_pixel; m++) | 
 | 	{ | 
 | 		if ((sp->dctable_offset[m]!=0) && ((m==0) || (sp->dctable_offset[m]!=sp->dctable_offset[m-1]))) | 
 | 		{ | 
 | 			for (n=0; n<m-1; n++) | 
 | 			{ | 
 | 				if (sp->dctable_offset[m]==sp->dctable_offset[n]) | 
 | 				{ | 
 | 					TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegDcTables tag value"); | 
 | 					return(0); | 
 | 				} | 
 | 			} | 
 | 			TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET); | 
 | 			p=(uint32)TIFFReadFile(tif,o,16); | 
 | 			if (p!=16) | 
 | 				return(0); | 
 | 			q=0; | 
 | 			for (n=0; n<16; n++) | 
 | 				q+=o[n]; | 
 | 			ra=sizeof(uint32)+21+q; | 
 | 			rb=_TIFFmalloc(ra); | 
 | 			if (rb==0) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); | 
 | 				return(0); | 
 | 			} | 
 | 			*(uint32*)rb=ra; | 
 | 			rb[sizeof(uint32)]=255; | 
 | 			rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; | 
 | 			rb[sizeof(uint32)+2]=(uint8)((19+q)>>8); | 
 | 			rb[sizeof(uint32)+3]=((19+q)&255); | 
 | 			rb[sizeof(uint32)+4]=m; | 
 | 			for (n=0; n<16; n++) | 
 | 				rb[sizeof(uint32)+5+n]=o[n]; | 
 | 			p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); | 
 | 			if (p!=q) | 
 |                         { | 
 |                                 _TIFFfree(rb); | 
 | 				return(0); | 
 |                         } | 
 | 			if (sp->dctable[m]!=0) | 
 | 				_TIFFfree(sp->dctable[m]); | 
 | 			sp->dctable[m]=rb; | 
 | 			sp->sos_tda[m]=(m<<4); | 
 | 		} | 
 | 		else | 
 | 			sp->sos_tda[m]=sp->sos_tda[m-1]; | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif) | 
 | { | 
 | 	static const char module[]="OJPEGReadHeaderInfoSecTablesAcTable"; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 m; | 
 | 	uint8 n; | 
 | 	uint8 o[16]; | 
 | 	uint32 p; | 
 | 	uint32 q; | 
 | 	uint32 ra; | 
 | 	uint8* rb; | 
 | 	if (sp->actable_offset[0]==0) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); | 
 | 		return(0); | 
 | 	} | 
 | 	sp->in_buffer_file_pos_log=0; | 
 | 	for (m=0; m<sp->samples_per_pixel; m++) | 
 | 	{ | 
 | 		if ((sp->actable_offset[m]!=0) && ((m==0) || (sp->actable_offset[m]!=sp->actable_offset[m-1]))) | 
 | 		{ | 
 | 			for (n=0; n<m-1; n++) | 
 | 			{ | 
 | 				if (sp->actable_offset[m]==sp->actable_offset[n]) | 
 | 				{ | 
 | 					TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegAcTables tag value"); | 
 | 					return(0); | 
 | 				} | 
 | 			} | 
 | 			TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET);   | 
 | 			p=(uint32)TIFFReadFile(tif,o,16); | 
 | 			if (p!=16) | 
 | 				return(0); | 
 | 			q=0; | 
 | 			for (n=0; n<16; n++) | 
 | 				q+=o[n]; | 
 | 			ra=sizeof(uint32)+21+q; | 
 | 			rb=_TIFFmalloc(ra); | 
 | 			if (rb==0) | 
 | 			{ | 
 | 				TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); | 
 | 				return(0); | 
 | 			} | 
 | 			*(uint32*)rb=ra; | 
 | 			rb[sizeof(uint32)]=255; | 
 | 			rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; | 
 | 			rb[sizeof(uint32)+2]=(uint8)((19+q)>>8); | 
 | 			rb[sizeof(uint32)+3]=((19+q)&255); | 
 | 			rb[sizeof(uint32)+4]=(16|m); | 
 | 			for (n=0; n<16; n++) | 
 | 				rb[sizeof(uint32)+5+n]=o[n]; | 
 | 			p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); | 
 | 			if (p!=q) | 
 |                         { | 
 |                                 _TIFFfree(rb); | 
 | 				return(0); | 
 |                         } | 
 | 			if (sp->actable[m]!=0) | 
 | 				_TIFFfree(sp->actable[m]); | 
 | 			sp->actable[m]=rb; | 
 | 			sp->sos_tda[m]=(sp->sos_tda[m]|m); | 
 | 		} | 
 | 		else | 
 | 			sp->sos_tda[m]=(sp->sos_tda[m]|(sp->sos_tda[m-1]&15)); | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadBufferFill(OJPEGState* sp) | 
 | { | 
 | 	uint16 m; | 
 | 	tmsize_t n; | 
 | 	/* TODO: double-check: when subsamplingcorrect is set, no call to TIFFErrorExt or TIFFWarningExt should be made | 
 | 	 * in any other case, seek or read errors should be passed through */ | 
 | 	do | 
 | 	{ | 
 | 		if (sp->in_buffer_file_togo!=0) | 
 | 		{ | 
 | 			if (sp->in_buffer_file_pos_log==0) | 
 | 			{ | 
 | 				TIFFSeekFile(sp->tif,sp->in_buffer_file_pos,SEEK_SET); | 
 | 				sp->in_buffer_file_pos_log=1; | 
 | 			} | 
 | 			m=OJPEG_BUFFER; | 
 | 			if ((uint64)m>sp->in_buffer_file_togo) | 
 | 				m=(uint16)sp->in_buffer_file_togo; | 
 | 			n=TIFFReadFile(sp->tif,sp->in_buffer,(tmsize_t)m); | 
 | 			if (n==0) | 
 | 				return(0); | 
 | 			assert(n>0); | 
 | 			assert(n<=OJPEG_BUFFER); | 
 | 			assert(n<65536); | 
 | 			assert((uint64)n<=sp->in_buffer_file_togo); | 
 | 			m=(uint16)n; | 
 | 			sp->in_buffer_togo=m; | 
 | 			sp->in_buffer_cur=sp->in_buffer; | 
 | 			sp->in_buffer_file_togo-=m; | 
 | 			sp->in_buffer_file_pos+=m; | 
 | 			break; | 
 | 		} | 
 | 		sp->in_buffer_file_pos_log=0; | 
 | 		switch(sp->in_buffer_source) | 
 | 		{ | 
 | 			case osibsNotSetYet: | 
 | 				if (sp->jpeg_interchange_format!=0) | 
 | 				{ | 
 | 					sp->in_buffer_file_pos=sp->jpeg_interchange_format; | 
 | 					sp->in_buffer_file_togo=sp->jpeg_interchange_format_length; | 
 | 				} | 
 | 				sp->in_buffer_source=osibsJpegInterchangeFormat; | 
 | 				break; | 
 | 			case osibsJpegInterchangeFormat: | 
 | 				sp->in_buffer_source=osibsStrile; | 
 |                                 break; | 
 | 			case osibsStrile: | 
 | 				if (sp->in_buffer_next_strile==sp->in_buffer_strile_count) | 
 | 					sp->in_buffer_source=osibsEof; | 
 | 				else | 
 | 				{ | 
 | 					int err = 0; | 
 | 					sp->in_buffer_file_pos=TIFFGetStrileOffsetWithErr(sp->tif, sp->in_buffer_next_strile, &err); | 
 | 					if( err ) | 
 | 						return 0; | 
 | 					if (sp->in_buffer_file_pos!=0) | 
 | 					{ | 
 | 						uint64 bytecount = TIFFGetStrileByteCountWithErr(sp->tif, sp->in_buffer_next_strile, &err); | 
 | 						if( err ) | 
 | 							return 0; | 
 | 						if (sp->in_buffer_file_pos>=sp->file_size) | 
 | 							sp->in_buffer_file_pos=0; | 
 | 						else if (bytecount==0) | 
 | 							sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; | 
 | 						else | 
 | 						{ | 
 | 							sp->in_buffer_file_togo=bytecount; | 
 | 							if (sp->in_buffer_file_togo==0) | 
 | 								sp->in_buffer_file_pos=0; | 
 | 							else if (sp->in_buffer_file_pos > TIFF_UINT64_MAX - sp->in_buffer_file_togo ||  | 
 |                                                                 sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size) | 
 | 								sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; | 
 | 						} | 
 | 					} | 
 | 					sp->in_buffer_next_strile++; | 
 | 				} | 
 | 				break; | 
 | 			default: | 
 | 				return(0); | 
 | 		} | 
 | 	} while (1); | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadByte(OJPEGState* sp, uint8* byte) | 
 | { | 
 | 	if (sp->in_buffer_togo==0) | 
 | 	{ | 
 | 		if (OJPEGReadBufferFill(sp)==0) | 
 | 			return(0); | 
 | 		assert(sp->in_buffer_togo>0); | 
 | 	} | 
 | 	*byte=*(sp->in_buffer_cur); | 
 | 	sp->in_buffer_cur++; | 
 | 	sp->in_buffer_togo--; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadBytePeek(OJPEGState* sp, uint8* byte) | 
 | { | 
 | 	if (sp->in_buffer_togo==0) | 
 | 	{ | 
 | 		if (OJPEGReadBufferFill(sp)==0) | 
 | 			return(0); | 
 | 		assert(sp->in_buffer_togo>0); | 
 | 	} | 
 | 	*byte=*(sp->in_buffer_cur); | 
 | 	return(1); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGReadByteAdvance(OJPEGState* sp) | 
 | { | 
 | 	assert(sp->in_buffer_togo>0); | 
 | 	sp->in_buffer_cur++; | 
 | 	sp->in_buffer_togo--; | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadWord(OJPEGState* sp, uint16* word) | 
 | { | 
 | 	uint8 m; | 
 | 	if (OJPEGReadByte(sp,&m)==0) | 
 | 		return(0); | 
 | 	*word=(m<<8); | 
 | 	if (OJPEGReadByte(sp,&m)==0) | 
 | 		return(0); | 
 | 	*word|=m; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static int | 
 | OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem) | 
 | { | 
 | 	uint16 mlen; | 
 | 	uint8* mmem; | 
 | 	uint16 n; | 
 | 	assert(len>0); | 
 | 	mlen=len; | 
 | 	mmem=mem; | 
 | 	do | 
 | 	{ | 
 | 		if (sp->in_buffer_togo==0) | 
 | 		{ | 
 | 			if (OJPEGReadBufferFill(sp)==0) | 
 | 				return(0); | 
 | 			assert(sp->in_buffer_togo>0); | 
 | 		} | 
 | 		n=mlen; | 
 | 		if (n>sp->in_buffer_togo) | 
 | 			n=sp->in_buffer_togo; | 
 | 		_TIFFmemcpy(mmem,sp->in_buffer_cur,n); | 
 | 		sp->in_buffer_cur+=n; | 
 | 		sp->in_buffer_togo-=n; | 
 | 		mlen-=n; | 
 | 		mmem+=n; | 
 | 	} while(mlen>0); | 
 | 	return(1); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGReadSkip(OJPEGState* sp, uint16 len) | 
 | { | 
 | 	uint16 m; | 
 | 	uint16 n; | 
 | 	m=len; | 
 | 	n=m; | 
 | 	if (n>sp->in_buffer_togo) | 
 | 		n=sp->in_buffer_togo; | 
 | 	sp->in_buffer_cur+=n; | 
 | 	sp->in_buffer_togo-=n; | 
 | 	m-=n; | 
 | 	if (m>0) | 
 | 	{ | 
 | 		assert(sp->in_buffer_togo==0); | 
 | 		n=m; | 
 | 		if ((uint64)n>sp->in_buffer_file_togo) | 
 | 			n=(uint16)sp->in_buffer_file_togo; | 
 | 		sp->in_buffer_file_pos+=n; | 
 | 		sp->in_buffer_file_togo-=n; | 
 | 		sp->in_buffer_file_pos_log=0; | 
 | 		/* we don't skip past jpeginterchangeformat/strile block... | 
 | 		 * if that is asked from us, we're dealing with totally bazurk | 
 | 		 * data anyway, and we've not seen this happening on any | 
 | 		 * testfile, so we might as well likely cause some other | 
 | 		 * meaningless error to be passed at some later time | 
 | 		 */ | 
 | 	} | 
 | } | 
 |  | 
 | static int | 
 | OJPEGWriteStream(TIFF* tif, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	*len=0; | 
 | 	do | 
 | 	{ | 
 | 		assert(sp->out_state<=ososEoi); | 
 | 		switch(sp->out_state) | 
 | 		{ | 
 | 			case ososSoi: | 
 | 				OJPEGWriteStreamSoi(tif,mem,len); | 
 | 				break; | 
 | 			case ososQTable0: | 
 | 				OJPEGWriteStreamQTable(tif,0,mem,len); | 
 | 				break; | 
 | 			case ososQTable1: | 
 | 				OJPEGWriteStreamQTable(tif,1,mem,len); | 
 | 				break; | 
 | 			case ososQTable2: | 
 | 				OJPEGWriteStreamQTable(tif,2,mem,len); | 
 | 				break; | 
 | 			case ososQTable3: | 
 | 				OJPEGWriteStreamQTable(tif,3,mem,len); | 
 | 				break; | 
 | 			case ososDcTable0: | 
 | 				OJPEGWriteStreamDcTable(tif,0,mem,len); | 
 | 				break; | 
 | 			case ososDcTable1: | 
 | 				OJPEGWriteStreamDcTable(tif,1,mem,len); | 
 | 				break; | 
 | 			case ososDcTable2: | 
 | 				OJPEGWriteStreamDcTable(tif,2,mem,len); | 
 | 				break; | 
 | 			case ososDcTable3: | 
 | 				OJPEGWriteStreamDcTable(tif,3,mem,len); | 
 | 				break; | 
 | 			case ososAcTable0: | 
 | 				OJPEGWriteStreamAcTable(tif,0,mem,len); | 
 | 				break; | 
 | 			case ososAcTable1: | 
 | 				OJPEGWriteStreamAcTable(tif,1,mem,len); | 
 | 				break; | 
 | 			case ososAcTable2: | 
 | 				OJPEGWriteStreamAcTable(tif,2,mem,len); | 
 | 				break; | 
 | 			case ososAcTable3: | 
 | 				OJPEGWriteStreamAcTable(tif,3,mem,len); | 
 | 				break; | 
 | 			case ososDri: | 
 | 				OJPEGWriteStreamDri(tif,mem,len); | 
 | 				break; | 
 | 			case ososSof: | 
 | 				OJPEGWriteStreamSof(tif,mem,len); | 
 | 				break; | 
 | 			case ososSos: | 
 | 				OJPEGWriteStreamSos(tif,mem,len); | 
 | 				break; | 
 | 			case ososCompressed: | 
 | 				if (OJPEGWriteStreamCompressed(tif,mem,len)==0) | 
 | 					return(0); | 
 | 				break; | 
 | 			case ososRst: | 
 | 				OJPEGWriteStreamRst(tif,mem,len); | 
 | 				break; | 
 | 			case ososEoi: | 
 | 				OJPEGWriteStreamEoi(tif,mem,len); | 
 | 				break; | 
 | 		} | 
 | 	} while (*len==0); | 
 | 	return(1); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	assert(OJPEG_BUFFER>=2); | 
 | 	sp->out_buffer[0]=255; | 
 | 	sp->out_buffer[1]=JPEG_MARKER_SOI; | 
 | 	*len=2; | 
 | 	*mem=(void*)sp->out_buffer; | 
 | 	sp->out_state++; | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	if (sp->qtable[table_index]!=0) | 
 | 	{ | 
 | 		*mem=(void*)(sp->qtable[table_index]+sizeof(uint32)); | 
 | 		*len=*((uint32*)sp->qtable[table_index])-sizeof(uint32); | 
 | 	} | 
 | 	sp->out_state++; | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	if (sp->dctable[table_index]!=0) | 
 | 	{ | 
 | 		*mem=(void*)(sp->dctable[table_index]+sizeof(uint32)); | 
 | 		*len=*((uint32*)sp->dctable[table_index])-sizeof(uint32); | 
 | 	} | 
 | 	sp->out_state++; | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	if (sp->actable[table_index]!=0) | 
 | 	{ | 
 | 		*mem=(void*)(sp->actable[table_index]+sizeof(uint32)); | 
 | 		*len=*((uint32*)sp->actable[table_index])-sizeof(uint32); | 
 | 	} | 
 | 	sp->out_state++; | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	assert(OJPEG_BUFFER>=6); | 
 | 	if (sp->restart_interval!=0) | 
 | 	{ | 
 | 		sp->out_buffer[0]=255; | 
 | 		sp->out_buffer[1]=JPEG_MARKER_DRI; | 
 | 		sp->out_buffer[2]=0; | 
 | 		sp->out_buffer[3]=4; | 
 | 		sp->out_buffer[4]=(sp->restart_interval>>8); | 
 | 		sp->out_buffer[5]=(sp->restart_interval&255); | 
 | 		*len=6; | 
 | 		*mem=(void*)sp->out_buffer; | 
 | 	} | 
 | 	sp->out_state++; | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 m; | 
 | 	assert(OJPEG_BUFFER>=2+8+sp->samples_per_pixel_per_plane*3); | 
 | 	assert(255>=8+sp->samples_per_pixel_per_plane*3); | 
 | 	sp->out_buffer[0]=255; | 
 | 	sp->out_buffer[1]=sp->sof_marker_id; | 
 | 	/* Lf */ | 
 | 	sp->out_buffer[2]=0; | 
 | 	sp->out_buffer[3]=8+sp->samples_per_pixel_per_plane*3; | 
 | 	/* P */ | 
 | 	sp->out_buffer[4]=8; | 
 | 	/* Y */ | 
 | 	sp->out_buffer[5]=(uint8)(sp->sof_y>>8); | 
 | 	sp->out_buffer[6]=(sp->sof_y&255); | 
 | 	/* X */ | 
 | 	sp->out_buffer[7]=(uint8)(sp->sof_x>>8); | 
 | 	sp->out_buffer[8]=(sp->sof_x&255); | 
 | 	/* Nf */ | 
 | 	sp->out_buffer[9]=sp->samples_per_pixel_per_plane; | 
 | 	for (m=0; m<sp->samples_per_pixel_per_plane; m++) | 
 | 	{ | 
 | 		/* C */ | 
 | 		sp->out_buffer[10+m*3]=sp->sof_c[sp->plane_sample_offset+m]; | 
 | 		/* H and V */ | 
 | 		sp->out_buffer[10+m*3+1]=sp->sof_hv[sp->plane_sample_offset+m]; | 
 | 		/* Tq */ | 
 | 		sp->out_buffer[10+m*3+2]=sp->sof_tq[sp->plane_sample_offset+m]; | 
 | 	} | 
 | 	*len=10+sp->samples_per_pixel_per_plane*3; | 
 | 	*mem=(void*)sp->out_buffer; | 
 | 	sp->out_state++; | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	uint8 m; | 
 | 	assert(OJPEG_BUFFER>=2+6+sp->samples_per_pixel_per_plane*2); | 
 | 	assert(255>=6+sp->samples_per_pixel_per_plane*2); | 
 | 	sp->out_buffer[0]=255; | 
 | 	sp->out_buffer[1]=JPEG_MARKER_SOS; | 
 | 	/* Ls */ | 
 | 	sp->out_buffer[2]=0; | 
 | 	sp->out_buffer[3]=6+sp->samples_per_pixel_per_plane*2; | 
 | 	/* Ns */ | 
 | 	sp->out_buffer[4]=sp->samples_per_pixel_per_plane; | 
 | 	for (m=0; m<sp->samples_per_pixel_per_plane; m++) | 
 | 	{ | 
 | 		/* Cs */ | 
 | 		sp->out_buffer[5+m*2]=sp->sos_cs[sp->plane_sample_offset+m]; | 
 | 		/* Td and Ta */ | 
 | 		sp->out_buffer[5+m*2+1]=sp->sos_tda[sp->plane_sample_offset+m]; | 
 | 	} | 
 | 	/* Ss */ | 
 | 	sp->out_buffer[5+sp->samples_per_pixel_per_plane*2]=0; | 
 | 	/* Se */ | 
 | 	sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+1]=63; | 
 | 	/* Ah and Al */ | 
 | 	sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+2]=0; | 
 | 	*len=8+sp->samples_per_pixel_per_plane*2; | 
 | 	*mem=(void*)sp->out_buffer; | 
 | 	sp->out_state++; | 
 | } | 
 |  | 
 | static int | 
 | OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	if (sp->in_buffer_togo==0) | 
 | 	{ | 
 | 		if (OJPEGReadBufferFill(sp)==0) | 
 | 			return(0); | 
 | 		assert(sp->in_buffer_togo>0); | 
 | 	} | 
 | 	*len=sp->in_buffer_togo; | 
 | 	*mem=(void*)sp->in_buffer_cur; | 
 | 	sp->in_buffer_togo=0; | 
 | 	if (sp->in_buffer_file_togo==0) | 
 | 	{ | 
 | 		switch(sp->in_buffer_source) | 
 | 		{ | 
 | 			case osibsStrile: | 
 | 				if (sp->in_buffer_next_strile<sp->in_buffer_strile_count) | 
 | 					sp->out_state=ososRst; | 
 | 				else | 
 | 					sp->out_state=ososEoi; | 
 | 				break; | 
 | 			case osibsEof: | 
 | 				sp->out_state=ososEoi; | 
 | 				break; | 
 | 			default: | 
 | 				break; | 
 | 		} | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	assert(OJPEG_BUFFER>=2); | 
 | 	sp->out_buffer[0]=255; | 
 | 	sp->out_buffer[1]=JPEG_MARKER_RST0+sp->restart_index; | 
 | 	sp->restart_index++; | 
 | 	if (sp->restart_index==8) | 
 | 		sp->restart_index=0; | 
 | 	*len=2; | 
 | 	*mem=(void*)sp->out_buffer; | 
 | 	sp->out_state=ososCompressed; | 
 | } | 
 |  | 
 | static void | 
 | OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	assert(OJPEG_BUFFER>=2); | 
 | 	sp->out_buffer[0]=255; | 
 | 	sp->out_buffer[1]=JPEG_MARKER_EOI; | 
 | 	*len=2; | 
 | 	*mem=(void*)sp->out_buffer; | 
 | } | 
 |  | 
 | #ifndef LIBJPEG_ENCAP_EXTERNAL | 
 | static int | 
 | jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) | 
 | { | 
 | 	if( SETJMP(sp->exit_jmpbuf) ) | 
 | 		return 0; | 
 | 	else { | 
 | 		jpeg_create_decompress(cinfo); | 
 | 		return 1; | 
 | 	} | 
 | } | 
 | #endif | 
 |  | 
 | #ifndef LIBJPEG_ENCAP_EXTERNAL | 
 | static int | 
 | jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image) | 
 | { | 
 | 	if( SETJMP(sp->exit_jmpbuf) ) | 
 | 		return 0; | 
 | 	else { | 
 | 		jpeg_read_header(cinfo,require_image); | 
 | 		return 1; | 
 | 	} | 
 | } | 
 | #endif | 
 |  | 
 | #ifndef LIBJPEG_ENCAP_EXTERNAL | 
 | static int | 
 | jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) | 
 | { | 
 | 	if( SETJMP(sp->exit_jmpbuf) ) | 
 | 		return 0; | 
 | 	else { | 
 | 		jpeg_start_decompress(cinfo); | 
 | 		return 1; | 
 | 	} | 
 | } | 
 | #endif | 
 |  | 
 | #ifndef LIBJPEG_ENCAP_EXTERNAL | 
 | static int | 
 | jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines) | 
 | { | 
 | 	if( SETJMP(sp->exit_jmpbuf) ) | 
 | 		return 0; | 
 | 	else { | 
 | 		jpeg_read_scanlines(cinfo,scanlines,max_lines); | 
 | 		return 1; | 
 | 	} | 
 | } | 
 | #endif | 
 |  | 
 | #ifndef LIBJPEG_ENCAP_EXTERNAL | 
 | static int | 
 | jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines) | 
 | { | 
 | 	if( SETJMP(sp->exit_jmpbuf) ) | 
 | 		return 0; | 
 | 	else { | 
 | 		jpeg_read_raw_data(cinfo,data,max_lines); | 
 | 		return 1; | 
 | 	} | 
 | } | 
 | #endif | 
 |  | 
 | #ifndef LIBJPEG_ENCAP_EXTERNAL | 
 | static void | 
 | jpeg_encap_unwind(TIFF* tif) | 
 | { | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	LONGJMP(sp->exit_jmpbuf,1); | 
 | } | 
 | #endif | 
 |  | 
 | static void | 
 | OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo) | 
 | { | 
 | 	char buffer[JMSG_LENGTH_MAX]; | 
 | 	(*cinfo->err->format_message)(cinfo,buffer); | 
 | 	TIFFWarningExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo) | 
 | { | 
 | 	char buffer[JMSG_LENGTH_MAX]; | 
 | 	(*cinfo->err->format_message)(cinfo,buffer); | 
 | 	TIFFErrorExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer); | 
 | 	jpeg_encap_unwind((TIFF*)(cinfo->client_data)); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo) | 
 | { | 
 | 	(void)cinfo; | 
 | } | 
 |  | 
 | static boolean | 
 | OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo) | 
 | { | 
 | 	TIFF* tif=(TIFF*)cinfo->client_data; | 
 | 	OJPEGState* sp=(OJPEGState*)tif->tif_data; | 
 | 	void* mem=0; | 
 | 	uint32 len=0U; | 
 | 	if (OJPEGWriteStream(tif,&mem,&len)==0) | 
 | 	{ | 
 | 		TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Premature end of JPEG data"); | 
 | 		jpeg_encap_unwind(tif); | 
 | 	} | 
 | 	sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=len; | 
 | 	sp->libjpeg_jpeg_source_mgr.next_input_byte=mem; | 
 | 	return(1); | 
 | } | 
 |  | 
 | static void | 
 | OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes) | 
 | { | 
 | 	TIFF* tif=(TIFF*)cinfo->client_data; | 
 | 	(void)num_bytes; | 
 | 	TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error"); | 
 | 	jpeg_encap_unwind(tif); | 
 | } | 
 |  | 
 | #ifdef _MSC_VER | 
 | #pragma warning( push ) | 
 | #pragma warning( disable : 4702 ) /* unreachable code */ | 
 | #endif | 
 | static boolean | 
 | OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired) | 
 | { | 
 | 	TIFF* tif=(TIFF*)cinfo->client_data; | 
 | 	(void)desired; | 
 | 	TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error"); | 
 | 	jpeg_encap_unwind(tif); | 
 | 	return(0); | 
 | } | 
 | #ifdef _MSC_VER | 
 | #pragma warning( pop )  | 
 | #endif | 
 |  | 
 | static void | 
 | OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo) | 
 | { | 
 | 	(void)cinfo; | 
 | } | 
 |  | 
 | #endif | 
 |  | 
 |  | 
 | /* | 
 |  * Local Variables: | 
 |  * mode: c | 
 |  * c-basic-offset: 8 | 
 |  * fill-column: 78 | 
 |  * End: | 
 |  */ |