2497 lines
		
	
	
		
			86 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2497 lines
		
	
	
		
			86 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id: tif_ojpeg.c,v 1.56 2012-05-24 03:15:18 fwarmerdam Exp $ */
 | 
						|
 | 
						|
/* 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
 | 
						|
   developement. 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. Allthough
 | 
						|
   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
 | 
						|
   consistenly 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 dissadvantage 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
 | 
						|
 * 	conviniently 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 accomodate 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 conficting 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
 | 
						|
 | 
						|
#include "jpeglib.h"
 | 
						|
#include "jerror.h"
 | 
						|
 | 
						|
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;
 | 
						|
    #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;
 | 
						|
    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);
 | 
						|
    }
 | 
						|
    TIFFSetFieldBit(tif,TIFFFieldWithTag(tif,tag)->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++;
 | 
						|
    }
 | 
						|
    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;
 | 
						|
    }
 | 
						|
    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)
 | 
						|
{
 | 
						|
    OJPEGState* sp=(OJPEGState*)tif->tif_data;
 | 
						|
    (void)s;
 | 
						|
    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)
 | 
						|
        {
 | 
						|
            if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
 | 
						|
                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;
 | 
						|
        _TIFFFillStriles( tif );
 | 
						|
 | 
						|
    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->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=((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=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;
 | 
						|
            sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(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-1)/sp->subsampling_hor);
 | 
						|
            sp->subsampling_convert_state=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-1)/sp->subsampling_ver);
 | 
						|
            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+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 easilly cause trouble in some cases... but no such cases have occured sofar */
 | 
						|
    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)
 | 
						|
            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");
 | 
						|
                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");
 | 
						|
                return(0);
 | 
						|
            }
 | 
						|
            o&=15;
 | 
						|
            if (3<o)
 | 
						|
            {
 | 
						|
                TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
 | 
						|
                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=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64);
 | 
						|
            if (p!=64)
 | 
						|
                return(0);
 | 
						|
            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=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]=((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=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
 | 
						|
            if (p!=q)
 | 
						|
                return(0);
 | 
						|
            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=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]=((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=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
 | 
						|
            if (p!=q)
 | 
						|
                return(0);
 | 
						|
            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;
 | 
						|
            case osibsStrile:
 | 
						|
                if (!_TIFFFillStriles( sp->tif )
 | 
						|
                    || sp->tif->tif_dir.td_stripoffset == NULL
 | 
						|
                    || sp->tif->tif_dir.td_stripbytecount == NULL)
 | 
						|
                    return 0;
 | 
						|
 | 
						|
                if (sp->in_buffer_next_strile==sp->in_buffer_strile_count)
 | 
						|
                    sp->in_buffer_source=osibsEof;
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile];
 | 
						|
                    if (sp->in_buffer_file_pos!=0)
 | 
						|
                    {
 | 
						|
                        if (sp->in_buffer_file_pos>=sp->file_size)
 | 
						|
                            sp->in_buffer_file_pos=0;
 | 
						|
                        else if (sp->tif->tif_dir.td_stripbytecount==NULL)
 | 
						|
                            sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            if (sp->tif->tif_dir.td_stripbytecount == 0) {
 | 
						|
                                TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing");
 | 
						|
                                return(0);
 | 
						|
                            }
 | 
						|
                            sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile];
 | 
						|
                            if (sp->in_buffer_file_togo==0)
 | 
						|
                                sp->in_buffer_file_pos=0;
 | 
						|
                            else if (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]=(sp->sof_y>>8);
 | 
						|
    sp->out_buffer[6]=(sp->sof_y&255);
 | 
						|
    /* X */
 | 
						|
    sp->out_buffer[7]=(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)
 | 
						|
{
 | 
						|
    return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_create_decompress(cinfo),1));
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef LIBJPEG_ENCAP_EXTERNAL
 | 
						|
static int
 | 
						|
jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image)
 | 
						|
{
 | 
						|
    return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_header(cinfo,require_image),1));
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef LIBJPEG_ENCAP_EXTERNAL
 | 
						|
static int
 | 
						|
jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
 | 
						|
{
 | 
						|
    return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_start_decompress(cinfo),1));
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef LIBJPEG_ENCAP_EXTERNAL
 | 
						|
static int
 | 
						|
jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines)
 | 
						|
{
 | 
						|
    return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_scanlines(cinfo,scanlines,max_lines),1));
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef LIBJPEG_ENCAP_EXTERNAL
 | 
						|
static int
 | 
						|
jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines)
 | 
						|
{
 | 
						|
    return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_raw_data(cinfo,data,max_lines),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);
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo)
 | 
						|
{
 | 
						|
    (void)cinfo;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Local Variables:
 | 
						|
 * mode: c
 | 
						|
 * c-basic-offset: 8
 | 
						|
 * fill-column: 78
 | 
						|
 * End:
 | 
						|
 */
 |