roentgen b75cab
/* $Id: tif_jpeg.c,v 1.111 2012-07-06 18:48:04 bfriesen Exp $ */
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Copyright (c) 1994-1997 Sam Leffler
roentgen b75cab
 * Copyright (c) 1994-1997 Silicon Graphics, Inc.
roentgen b75cab
 *
roentgen b75cab
 * Permission to use, copy, modify, distribute, and sell this software and 
roentgen b75cab
 * its documentation for any purpose is hereby granted without fee, provided
roentgen b75cab
 * that (i) the above copyright notices and this permission notice appear in
roentgen b75cab
 * all copies of the software and related documentation, and (ii) the names of
roentgen b75cab
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
roentgen b75cab
 * publicity relating to the software without the specific, prior written
roentgen b75cab
 * permission of Sam Leffler and Silicon Graphics.
roentgen b75cab
 * 
roentgen b75cab
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
roentgen b75cab
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
roentgen b75cab
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
roentgen b75cab
 * 
roentgen b75cab
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
roentgen b75cab
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
roentgen b75cab
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
roentgen b75cab
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
roentgen b75cab
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
roentgen b75cab
 * OF THIS SOFTWARE.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
#define WIN32_LEAN_AND_MEAN
roentgen b75cab
#define VC_EXTRALEAN
roentgen b75cab
roentgen b75cab
#include "tiffiop.h"
roentgen b75cab
#ifdef JPEG_SUPPORT
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * TIFF Library
roentgen b75cab
 *
roentgen b75cab
 * JPEG Compression support per TIFF Technical Note #2
roentgen b75cab
 * (*not* per the original TIFF 6.0 spec).
roentgen b75cab
 *
roentgen b75cab
 * This file is simply an interface to the libjpeg library written by
roentgen b75cab
 * the Independent JPEG Group.  You need release 5 or later of the IJG
roentgen b75cab
 * code, which you can find on the Internet at ftp.uu.net:/graphics/jpeg/.
roentgen b75cab
 *
roentgen b75cab
 * Contributed by Tom Lane <tgl@sss.pgh.pa.us>.</tgl@sss.pgh.pa.us>
roentgen b75cab
 */
roentgen b75cab
#include <setjmp.h></setjmp.h>
roentgen b75cab
roentgen b75cab
int TIFFFillStrip(TIFF* tif, uint32 strip);
roentgen b75cab
int TIFFFillTile(TIFF* tif, uint32 tile);
roentgen b75cab
int TIFFReInitJPEG_12( TIFF *tif, int scheme, int is_encode );
roentgen b75cab
roentgen b75cab
/* We undefine FAR to avoid conflict with JPEG definition */
roentgen b75cab
roentgen b75cab
#ifdef FAR
roentgen b75cab
#undef FAR
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
  Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
roentgen b75cab
  not defined.  Unfortunately, the MinGW and Borland compilers include
roentgen b75cab
  a typedef for INT32, which causes a conflict.  MSVC does not include
roentgen b75cab
  a conficting typedef given the headers which are included.
roentgen b75cab
*/
roentgen b75cab
#if defined(__BORLANDC__) || defined(__MINGW32__)
roentgen b75cab
# define XMD_H 1
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
   The windows RPCNDR.H file defines boolean, but defines it with the
roentgen b75cab
   unsigned char size.  You should compile JPEG library using appropriate
roentgen b75cab
   definitions in jconfig.h header, but many users compile library in wrong
roentgen b75cab
   way. That causes errors of the following type:
roentgen b75cab
roentgen b75cab
   "JPEGLib: JPEG parameter struct mismatch: library thinks size is 432,
roentgen b75cab
   caller expects 464"
roentgen b75cab
roentgen b75cab
   For such users we wil fix the problem here. See install.doc file from
roentgen b75cab
   the JPEG library distribution for details.
roentgen b75cab
*/
roentgen b75cab
roentgen b75cab
/* Define "boolean" as unsigned char, not int, per Windows custom. */
roentgen b75cab
#if defined(__WIN32__) && !defined(__MINGW32__)
roentgen b75cab
# ifndef __RPCNDR_H__            /* don't conflict if rpcndr.h already read */
roentgen b75cab
   typedef unsigned char boolean;
roentgen b75cab
# endif
roentgen b75cab
# define HAVE_BOOLEAN            /* prevent jmorecfg.h from redefining it */
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
#include "jpeglib.h"
roentgen b75cab
#include "jerror.h"
roentgen b75cab
roentgen b75cab
/* 
roentgen b75cab
 * Do we want to do special processing suitable for when JSAMPLE is a
roentgen b75cab
 * 16bit value?  
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
#if defined(JPEG_LIB_MK1)
roentgen b75cab
#  define JPEG_LIB_MK1_OR_12BIT 1
roentgen b75cab
#elif BITS_IN_JSAMPLE == 12
roentgen b75cab
#  define JPEG_LIB_MK1_OR_12BIT 1
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * We are using width_in_blocks which is supposed to be private to
roentgen b75cab
 * libjpeg. Unfortunately, the libjpeg delivered with Cygwin has
roentgen b75cab
 * renamed this member to width_in_data_units.  Since the header has
roentgen b75cab
 * also renamed a define, use that unique define name in order to
roentgen b75cab
 * detect the problem header and adjust to suit.
roentgen b75cab
 */
roentgen b75cab
#if defined(D_MAX_DATA_UNITS_IN_MCU)
roentgen b75cab
#define width_in_blocks width_in_data_units
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * On some machines it may be worthwhile to use _setjmp or sigsetjmp
roentgen b75cab
 * in place of plain setjmp.  These macros will make it easier.
roentgen b75cab
 */
roentgen b75cab
#define SETJMP(jbuf)		setjmp(jbuf)
roentgen b75cab
#define LONGJMP(jbuf,code)	longjmp(jbuf,code)
roentgen b75cab
#define JMP_BUF			jmp_buf
roentgen b75cab
roentgen b75cab
typedef struct jpeg_destination_mgr jpeg_destination_mgr;
roentgen b75cab
typedef struct jpeg_source_mgr jpeg_source_mgr;
roentgen b75cab
typedef struct jpeg_error_mgr jpeg_error_mgr;
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * State block for each open TIFF file using
roentgen b75cab
 * libjpeg to do JPEG compression/decompression.
roentgen b75cab
 *
roentgen b75cab
 * libjpeg's visible state is either a jpeg_compress_struct
roentgen b75cab
 * or jpeg_decompress_struct depending on which way we
roentgen b75cab
 * are going.  comm can be used to refer to the fields
roentgen b75cab
 * which are common to both.
roentgen b75cab
 *
roentgen b75cab
 * NB: cinfo is required to be the first member of JPEGState,
roentgen b75cab
 *     so we can safely cast JPEGState* -> jpeg_xxx_struct*
roentgen b75cab
 *     and vice versa!
roentgen b75cab
 */
roentgen b75cab
typedef struct {
roentgen b75cab
	union {
roentgen b75cab
		struct jpeg_compress_struct c;
roentgen b75cab
		struct jpeg_decompress_struct d;
roentgen b75cab
		struct jpeg_common_struct comm;
roentgen b75cab
	} cinfo;			/* NB: must be first */
roentgen b75cab
	int             cinfo_initialized;
roentgen b75cab
roentgen b75cab
	jpeg_error_mgr	err;		/* libjpeg error manager */
roentgen b75cab
	JMP_BUF		exit_jmpbuf;	/* for catching libjpeg failures */
roentgen b75cab
	/*
roentgen b75cab
	 * The following two members could be a union, but
roentgen b75cab
	 * they're small enough that it's not worth the effort.
roentgen b75cab
	 */
roentgen b75cab
	jpeg_destination_mgr dest;	/* data dest for compression */
roentgen b75cab
	jpeg_source_mgr	src;		/* data source for decompression */
roentgen b75cab
					/* private state */
roentgen b75cab
	TIFF*		tif;		/* back link needed by some code */
roentgen b75cab
	uint16		photometric;	/* copy of PhotometricInterpretation */
roentgen b75cab
	uint16		h_sampling;	/* luminance sampling factors */
roentgen b75cab
	uint16		v_sampling;
roentgen b75cab
	tmsize_t   	bytesperline;	/* decompressed bytes per scanline */
roentgen b75cab
	/* pointers to intermediate buffers when processing downsampled data */
roentgen b75cab
	JSAMPARRAY	ds_buffer[MAX_COMPONENTS];
roentgen b75cab
	int		scancount;	/* number of "scanlines" accumulated */
roentgen b75cab
	int		samplesperclump;
roentgen b75cab
roentgen b75cab
	TIFFVGetMethod	vgetparent;	/* super-class method */
roentgen b75cab
	TIFFVSetMethod	vsetparent;	/* super-class method */
roentgen b75cab
	TIFFPrintMethod printdir;	/* super-class method */
roentgen b75cab
	TIFFStripMethod	defsparent;	/* super-class method */
roentgen b75cab
	TIFFTileMethod	deftparent;	/* super-class method */
roentgen b75cab
					/* pseudo-tag fields */
roentgen b75cab
	void*		jpegtables;	/* JPEGTables tag value, or NULL */
roentgen b75cab
	uint32		jpegtables_length; /* number of bytes in same */
roentgen b75cab
	int		jpegquality;	/* Compression quality level */
roentgen b75cab
	int		jpegcolormode;	/* Auto RGB<=>YCbCr convert? */
roentgen b75cab
	int		jpegtablesmode;	/* What to put in JPEGTables */
roentgen b75cab
roentgen b75cab
        int             ycbcrsampling_fetched;
roentgen b75cab
} JPEGState;
roentgen b75cab
roentgen b75cab
#define	JState(tif)	((JPEGState*)(tif)->tif_data)
roentgen b75cab
roentgen b75cab
static int JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s);
roentgen b75cab
static int JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s);
roentgen b75cab
static int JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s);
roentgen b75cab
static int JPEGEncodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s);
roentgen b75cab
static int JPEGInitializeLibJPEG(TIFF * tif, int decode );
roentgen b75cab
static int DecodeRowError(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s);
roentgen b75cab
roentgen b75cab
#define	FIELD_JPEGTABLES	(FIELD_CODEC+0)
roentgen b75cab
roentgen b75cab
static const TIFFField jpegFields[] = {
roentgen b75cab
    { TIFFTAG_JPEGTABLES, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_C32_UINT8, FIELD_JPEGTABLES, FALSE, TRUE, "JPEGTables", NULL },
roentgen b75cab
    { TIFFTAG_JPEGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "", NULL },
roentgen b75cab
    { TIFFTAG_JPEGCOLORMODE, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL },
roentgen b75cab
    { TIFFTAG_JPEGTABLESMODE, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL }
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * libjpeg interface layer.
roentgen b75cab
 *
roentgen b75cab
 * We use setjmp/longjmp to return control to libtiff
roentgen b75cab
 * when a fatal error is encountered within the JPEG
roentgen b75cab
 * library.  We also direct libjpeg error and warning
roentgen b75cab
 * messages through the appropriate libtiff handlers.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Error handling routines (these replace corresponding
roentgen b75cab
 * IJG routines from jerror.c).  These are used for both
roentgen b75cab
 * compression and decompression.
roentgen b75cab
 */
roentgen b75cab
static void
roentgen b75cab
TIFFjpeg_error_exit(j_common_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = (JPEGState *) cinfo;	/* NB: cinfo assumed first */
roentgen b75cab
	char buffer[JMSG_LENGTH_MAX];
roentgen b75cab
roentgen b75cab
	(*cinfo->err->format_message) (cinfo, buffer);
roentgen b75cab
	TIFFErrorExt(sp->tif->tif_clientdata, "JPEGLib", "%s", buffer);		/* display the error message */
roentgen b75cab
	jpeg_abort(cinfo);			/* clean up libjpeg state */
roentgen b75cab
	LONGJMP(sp->exit_jmpbuf, 1);		/* return to libtiff caller */
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * This routine is invoked only for warning messages,
roentgen b75cab
 * since error_exit does its own thing and trace_level
roentgen b75cab
 * is never set > 0.
roentgen b75cab
 */
roentgen b75cab
static void
roentgen b75cab
TIFFjpeg_output_message(j_common_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	char buffer[JMSG_LENGTH_MAX];
roentgen b75cab
roentgen b75cab
	(*cinfo->err->format_message) (cinfo, buffer);
roentgen b75cab
	TIFFWarningExt(((JPEGState *) cinfo)->tif->tif_clientdata, "JPEGLib", "%s", buffer);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Interface routines.  This layer of routines exists
roentgen b75cab
 * primarily to limit side-effects from using setjmp.
roentgen b75cab
 * Also, normal/error returns are converted into return
roentgen b75cab
 * values per libtiff practice.
roentgen b75cab
 */
roentgen b75cab
#define	CALLJPEG(sp, fail, op)	(SETJMP((sp)->exit_jmpbuf) ? (fail) : (op))
roentgen b75cab
#define	CALLVJPEG(sp, op)	CALLJPEG(sp, 0, ((op),1))
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_create_compress(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	/* initialize JPEG error handling */
roentgen b75cab
	sp->cinfo.c.err = jpeg_std_error(&sp->err);
roentgen b75cab
	sp->err.error_exit = TIFFjpeg_error_exit;
roentgen b75cab
	sp->err.output_message = TIFFjpeg_output_message;
roentgen b75cab
roentgen b75cab
	return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_create_decompress(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	/* initialize JPEG error handling */
roentgen b75cab
	sp->cinfo.d.err = jpeg_std_error(&sp->err);
roentgen b75cab
	sp->err.error_exit = TIFFjpeg_error_exit;
roentgen b75cab
	sp->err.output_message = TIFFjpeg_output_message;
roentgen b75cab
roentgen b75cab
	return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_set_defaults(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_set_colorspace(JPEGState* sp, J_COLOR_SPACE colorspace)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_set_quality(JPEGState* sp, int quality, boolean force_baseline)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp,
roentgen b75cab
	    jpeg_set_quality(&sp->cinfo.c, quality, force_baseline));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_suppress_tables(JPEGState* sp, boolean suppress)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_start_compress(JPEGState* sp, boolean write_all_tables)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp,
roentgen b75cab
	    jpeg_start_compress(&sp->cinfo.c, write_all_tables));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_write_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int num_lines)
roentgen b75cab
{
roentgen b75cab
	return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c,
roentgen b75cab
	    scanlines, (JDIMENSION) num_lines));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_write_raw_data(JPEGState* sp, JSAMPIMAGE data, int num_lines)
roentgen b75cab
{
roentgen b75cab
	return CALLJPEG(sp, -1, (int) jpeg_write_raw_data(&sp->cinfo.c,
roentgen b75cab
	    data, (JDIMENSION) num_lines));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_finish_compress(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_write_tables(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_read_header(JPEGState* sp, boolean require_image)
roentgen b75cab
{
roentgen b75cab
	return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_start_decompress(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_read_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int max_lines)
roentgen b75cab
{
roentgen b75cab
	return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d,
roentgen b75cab
	    scanlines, (JDIMENSION) max_lines));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_read_raw_data(JPEGState* sp, JSAMPIMAGE data, int max_lines)
roentgen b75cab
{
roentgen b75cab
	return CALLJPEG(sp, -1, (int) jpeg_read_raw_data(&sp->cinfo.d,
roentgen b75cab
	    data, (JDIMENSION) max_lines));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_finish_decompress(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_abort(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_destroy(JPEGState* sp)
roentgen b75cab
{
roentgen b75cab
	return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static JSAMPARRAY
roentgen b75cab
TIFFjpeg_alloc_sarray(JPEGState* sp, int pool_id,
roentgen b75cab
		      JDIMENSION samplesperrow, JDIMENSION numrows)
roentgen b75cab
{
roentgen b75cab
	return CALLJPEG(sp, (JSAMPARRAY) NULL,
roentgen b75cab
	    (*sp->cinfo.comm.mem->alloc_sarray)
roentgen b75cab
		(&sp->cinfo.comm, pool_id, samplesperrow, numrows));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * JPEG library destination data manager.
roentgen b75cab
 * These routines direct compressed data from libjpeg into the
roentgen b75cab
 * libtiff output buffer.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
std_init_destination(j_compress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
	TIFF* tif = sp->tif;
roentgen b75cab
roentgen b75cab
	sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata;
roentgen b75cab
	sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static boolean
roentgen b75cab
std_empty_output_buffer(j_compress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
	TIFF* tif = sp->tif;
roentgen b75cab
roentgen b75cab
	/* the entire buffer has been filled */
roentgen b75cab
	tif->tif_rawcc = tif->tif_rawdatasize;
roentgen b75cab
roentgen b75cab
#ifdef IPPJ_HUFF
roentgen b75cab
       /*
roentgen b75cab
        * The Intel IPP performance library does not necessarily fill up
roentgen b75cab
        * the whole output buffer on each pass, so only dump out the parts
roentgen b75cab
        * that have been filled.
roentgen b75cab
        *   http://trac.osgeo.org/gdal/wiki/JpegIPP
roentgen b75cab
        */
roentgen b75cab
       if ( sp->dest.free_in_buffer >= 0 ) {
roentgen b75cab
               tif->tif_rawcc = tif->tif_rawdatasize - sp->dest.free_in_buffer;
roentgen b75cab
       }
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
	TIFFFlushData1(tif);
roentgen b75cab
	sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata;
roentgen b75cab
	sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize;
roentgen b75cab
roentgen b75cab
	return (TRUE);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
std_term_destination(j_compress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
	TIFF* tif = sp->tif;
roentgen b75cab
roentgen b75cab
	tif->tif_rawcp = (uint8*) sp->dest.next_output_byte;
roentgen b75cab
	tif->tif_rawcc =
roentgen b75cab
	    tif->tif_rawdatasize - (tmsize_t) sp->dest.free_in_buffer;
roentgen b75cab
	/* NB: libtiff does the final buffer flush */
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
TIFFjpeg_data_dest(JPEGState* sp, TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	(void) tif;
roentgen b75cab
	sp->cinfo.c.dest = &sp->dest;
roentgen b75cab
	sp->dest.init_destination = std_init_destination;
roentgen b75cab
	sp->dest.empty_output_buffer = std_empty_output_buffer;
roentgen b75cab
	sp->dest.term_destination = std_term_destination;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Alternate destination manager for outputting to JPEGTables field.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
tables_init_destination(j_compress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
roentgen b75cab
	/* while building, jpegtables_length is allocated buffer size */
roentgen b75cab
	sp->dest.next_output_byte = (JOCTET*) sp->jpegtables;
roentgen b75cab
	sp->dest.free_in_buffer = (size_t) sp->jpegtables_length;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static boolean
roentgen b75cab
tables_empty_output_buffer(j_compress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
	void* newbuf;
roentgen b75cab
roentgen b75cab
	/* the entire buffer has been filled; enlarge it by 1000 bytes */
roentgen b75cab
	newbuf = _TIFFrealloc((void*) sp->jpegtables,
roentgen b75cab
			      (tmsize_t) (sp->jpegtables_length + 1000));
roentgen b75cab
	if (newbuf == NULL)
roentgen b75cab
		ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100);
roentgen b75cab
	sp->dest.next_output_byte = (JOCTET*) newbuf + sp->jpegtables_length;
roentgen b75cab
	sp->dest.free_in_buffer = (size_t) 1000;
roentgen b75cab
	sp->jpegtables = newbuf;
roentgen b75cab
	sp->jpegtables_length += 1000;
roentgen b75cab
	return (TRUE);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
tables_term_destination(j_compress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
roentgen b75cab
	/* set tables length to number of bytes actually emitted */
roentgen b75cab
	sp->jpegtables_length -= (uint32) sp->dest.free_in_buffer;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
TIFFjpeg_tables_dest(JPEGState* sp, TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	(void) tif;
roentgen b75cab
	/*
roentgen b75cab
	 * Allocate a working buffer for building tables.
roentgen b75cab
	 * Initial size is 1000 bytes, which is usually adequate.
roentgen b75cab
	 */
roentgen b75cab
	if (sp->jpegtables)
roentgen b75cab
		_TIFFfree(sp->jpegtables);
roentgen b75cab
	sp->jpegtables_length = 1000;
roentgen b75cab
	sp->jpegtables = (void*) _TIFFmalloc((tmsize_t) sp->jpegtables_length);
roentgen b75cab
	if (sp->jpegtables == NULL) {
roentgen b75cab
		sp->jpegtables_length = 0;
roentgen b75cab
		TIFFErrorExt(sp->tif->tif_clientdata, "TIFFjpeg_tables_dest", "No space for JPEGTables");
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
	sp->cinfo.c.dest = &sp->dest;
roentgen b75cab
	sp->dest.init_destination = tables_init_destination;
roentgen b75cab
	sp->dest.empty_output_buffer = tables_empty_output_buffer;
roentgen b75cab
	sp->dest.term_destination = tables_term_destination;
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * JPEG library source data manager.
roentgen b75cab
 * These routines supply compressed data to libjpeg.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
std_init_source(j_decompress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
	TIFF* tif = sp->tif;
roentgen b75cab
roentgen b75cab
	sp->src.next_input_byte = (const JOCTET*) tif->tif_rawdata;
roentgen b75cab
	sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static boolean
roentgen b75cab
std_fill_input_buffer(j_decompress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState* ) cinfo;
roentgen b75cab
	static const JOCTET dummy_EOI[2] = { 0xFF, JPEG_EOI };
roentgen b75cab
roentgen b75cab
#ifdef IPPJ_HUFF
roentgen b75cab
        /*
roentgen b75cab
         * The Intel IPP performance library does not necessarily read the whole
roentgen b75cab
         * input buffer in one pass, so it is possible to get here with data
roentgen b75cab
         * yet to read. 
roentgen b75cab
         * 
roentgen b75cab
         * We just return without doing anything, until the entire buffer has
roentgen b75cab
         * been read.  
roentgen b75cab
         * http://trac.osgeo.org/gdal/wiki/JpegIPP
roentgen b75cab
         */
roentgen b75cab
        if( sp->src.bytes_in_buffer > 0 ) {
roentgen b75cab
            return (TRUE);
roentgen b75cab
        }
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
         * Normally the whole strip/tile is read and so we don't need to do
roentgen b75cab
         * a fill.  In the case of CHUNKY_STRIP_READ_SUPPORT we might not have
roentgen b75cab
         * all the data, but the rawdata is refreshed between scanlines and
roentgen b75cab
         * we push this into the io machinery in JPEGDecode(). 	 
roentgen b75cab
         * http://trac.osgeo.org/gdal/ticket/3894
roentgen b75cab
	 */
roentgen b75cab
        
roentgen b75cab
	WARNMS(cinfo, JWRN_JPEG_EOF);
roentgen b75cab
	/* insert a fake EOI marker */
roentgen b75cab
	sp->src.next_input_byte = dummy_EOI;
roentgen b75cab
	sp->src.bytes_in_buffer = 2;
roentgen b75cab
	return (TRUE);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
std_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
roentgen b75cab
	if (num_bytes > 0) {
roentgen b75cab
		if ((size_t)num_bytes > sp->src.bytes_in_buffer) {
roentgen b75cab
			/* oops, buffer overrun */
roentgen b75cab
			(void) std_fill_input_buffer(cinfo);
roentgen b75cab
		} else {
roentgen b75cab
			sp->src.next_input_byte += (size_t) num_bytes;
roentgen b75cab
			sp->src.bytes_in_buffer -= (size_t) num_bytes;
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
std_term_source(j_decompress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	/* No work necessary here */
roentgen b75cab
	(void) cinfo;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
TIFFjpeg_data_src(JPEGState* sp, TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	(void) tif;
roentgen b75cab
	sp->cinfo.d.src = &sp->src;
roentgen b75cab
	sp->src.init_source = std_init_source;
roentgen b75cab
	sp->src.fill_input_buffer = std_fill_input_buffer;
roentgen b75cab
	sp->src.skip_input_data = std_skip_input_data;
roentgen b75cab
	sp->src.resync_to_restart = jpeg_resync_to_restart;
roentgen b75cab
	sp->src.term_source = std_term_source;
roentgen b75cab
	sp->src.bytes_in_buffer = 0;		/* for safety */
roentgen b75cab
	sp->src.next_input_byte = NULL;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Alternate source manager for reading from JPEGTables.
roentgen b75cab
 * We can share all the code except for the init routine.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
tables_init_source(j_decompress_ptr cinfo)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = (JPEGState*) cinfo;
roentgen b75cab
roentgen b75cab
	sp->src.next_input_byte = (const JOCTET*) sp->jpegtables;
roentgen b75cab
	sp->src.bytes_in_buffer = (size_t) sp->jpegtables_length;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
TIFFjpeg_tables_src(JPEGState* sp, TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	TIFFjpeg_data_src(sp, tif);
roentgen b75cab
	sp->src.init_source = tables_init_source;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Allocate downsampled-data buffers needed for downsampled I/O.
roentgen b75cab
 * We use values computed in jpeg_start_compress or jpeg_start_decompress.
roentgen b75cab
 * We use libjpeg's allocator so that buffers will be released automatically
roentgen b75cab
 * when done with strip/tile.
roentgen b75cab
 * This is also a handy place to compute samplesperclump, bytesperline.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
alloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info,
roentgen b75cab
			  int num_components)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
	int ci;
roentgen b75cab
	jpeg_component_info* compptr;
roentgen b75cab
	JSAMPARRAY buf;
roentgen b75cab
	int samples_per_clump = 0;
roentgen b75cab
roentgen b75cab
	for (ci = 0, compptr = comp_info; ci < num_components;
roentgen b75cab
	     ci++, compptr++) {
roentgen b75cab
		samples_per_clump += compptr->h_samp_factor *
roentgen b75cab
			compptr->v_samp_factor;
roentgen b75cab
		buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE,
roentgen b75cab
				compptr->width_in_blocks * DCTSIZE,
roentgen b75cab
				(JDIMENSION) (compptr->v_samp_factor*DCTSIZE));
roentgen b75cab
		if (buf == NULL)
roentgen b75cab
			return (0);
roentgen b75cab
		sp->ds_buffer[ci] = buf;
roentgen b75cab
	}
roentgen b75cab
	sp->samplesperclump = samples_per_clump;
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * JPEG Decoding.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
roentgen b75cab
roentgen b75cab
#define JPEG_MARKER_SOF0 0xC0
roentgen b75cab
#define JPEG_MARKER_SOF1 0xC1
roentgen b75cab
#define JPEG_MARKER_SOF3 0xC3
roentgen b75cab
#define JPEG_MARKER_DHT 0xC4
roentgen b75cab
#define JPEG_MARKER_SOI 0xD8
roentgen b75cab
#define JPEG_MARKER_SOS 0xDA
roentgen b75cab
#define JPEG_MARKER_DQT 0xDB
roentgen b75cab
#define JPEG_MARKER_DRI 0xDD
roentgen b75cab
#define JPEG_MARKER_APP0 0xE0
roentgen b75cab
#define JPEG_MARKER_COM 0xFE
roentgen b75cab
struct JPEGFixupTagsSubsamplingData
roentgen b75cab
{
roentgen b75cab
	TIFF* tif;
roentgen b75cab
	void* buffer;
roentgen b75cab
	uint32 buffersize;
roentgen b75cab
	uint8* buffercurrentbyte;
roentgen b75cab
	uint32 bufferbytesleft;
roentgen b75cab
	uint64 fileoffset;
roentgen b75cab
	uint64 filebytesleft;
roentgen b75cab
	uint8 filepositioned;
roentgen b75cab
};
roentgen b75cab
static void JPEGFixupTagsSubsampling(TIFF* tif);
roentgen b75cab
static int JPEGFixupTagsSubsamplingSec(struct JPEGFixupTagsSubsamplingData* data);
roentgen b75cab
static int JPEGFixupTagsSubsamplingReadByte(struct JPEGFixupTagsSubsamplingData* data, uint8* result);
roentgen b75cab
static int JPEGFixupTagsSubsamplingReadWord(struct JPEGFixupTagsSubsamplingData* data, uint16* result);
roentgen b75cab
static void JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData* data, uint16 skiplength);
roentgen b75cab
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
JPEGFixupTags(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
roentgen b75cab
	if ((tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR)&&
roentgen b75cab
	    (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&&
roentgen b75cab
	    (tif->tif_dir.td_samplesperpixel==3))
roentgen b75cab
		JPEGFixupTagsSubsampling(tif);
roentgen b75cab
#endif
roentgen b75cab
        
roentgen b75cab
	return(1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
JPEGFixupTagsSubsampling(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	/*
roentgen b75cab
	 * Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in
roentgen b75cab
	 * the TIFF tags, but still use non-default (2,2) values within the jpeg
roentgen b75cab
	 * data stream itself.  In order for TIFF applications to work properly
roentgen b75cab
	 * - for instance to get the strip buffer size right - it is imperative
roentgen b75cab
	 * that the subsampling be available before we start reading the image
roentgen b75cab
	 * data normally.  This function will attempt to analyze the first strip in
roentgen b75cab
	 * order to get the sampling values from the jpeg data stream.
roentgen b75cab
	 *
roentgen b75cab
	 * Note that JPEGPreDeocode() will produce a fairly loud warning when the
roentgen b75cab
	 * discovered sampling does not match the default sampling (2,2) or whatever
roentgen b75cab
	 * was actually in the tiff tags.
roentgen b75cab
	 *
roentgen b75cab
	 * See the bug in bugzilla for details:
roentgen b75cab
	 *
roentgen b75cab
	 * http://bugzilla.remotesensing.org/show_bug.cgi?id=168
roentgen b75cab
	 *
roentgen b75cab
	 * Frank Warmerdam, July 2002
roentgen b75cab
	 * Joris Van Damme, May 2007
roentgen b75cab
	 */
roentgen b75cab
	static const char module[] = "JPEGFixupTagsSubsampling";
roentgen b75cab
	struct JPEGFixupTagsSubsamplingData m;
roentgen b75cab
roentgen b75cab
        _TIFFFillStriles( tif );
roentgen b75cab
        
roentgen b75cab
        if( tif->tif_dir.td_stripbytecount == NULL
roentgen b75cab
            || tif->tif_dir.td_stripbytecount[0] == 0 )
roentgen b75cab
        {
roentgen b75cab
            /* Do not even try to check if the first strip/tile does not
roentgen b75cab
               yet exist, as occurs when GDAL has created a new NULL file
roentgen b75cab
               for instance. */
roentgen b75cab
            return;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
	m.tif=tif;
roentgen b75cab
	m.buffersize=2048;
roentgen b75cab
	m.buffer=_TIFFmalloc(m.buffersize);
roentgen b75cab
	if (m.buffer==NULL)
roentgen b75cab
	{
roentgen b75cab
		TIFFWarningExt(tif->tif_clientdata,module,
roentgen b75cab
		    "Unable to allocate memory for auto-correcting of subsampling values; auto-correcting skipped");
roentgen b75cab
		return;
roentgen b75cab
	}
roentgen b75cab
	m.buffercurrentbyte=NULL;
roentgen b75cab
	m.bufferbytesleft=0;
roentgen b75cab
	m.fileoffset=tif->tif_dir.td_stripoffset[0];
roentgen b75cab
	m.filepositioned=0;
roentgen b75cab
	m.filebytesleft=tif->tif_dir.td_stripbytecount[0];
roentgen b75cab
	if (!JPEGFixupTagsSubsamplingSec(&m))
roentgen b75cab
		TIFFWarningExt(tif->tif_clientdata,module,
roentgen b75cab
		    "Unable to auto-correct subsampling values, likely corrupt JPEG compressed data in first strip/tile; auto-correcting skipped");
roentgen b75cab
	_TIFFfree(m.buffer);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
JPEGFixupTagsSubsamplingSec(struct JPEGFixupTagsSubsamplingData* data)
roentgen b75cab
{
roentgen b75cab
	static const char module[] = "JPEGFixupTagsSubsamplingSec";
roentgen b75cab
	uint8 m;
roentgen b75cab
	while (1)
roentgen b75cab
	{
roentgen b75cab
		while (1)
roentgen b75cab
		{
roentgen b75cab
			if (!JPEGFixupTagsSubsamplingReadByte(data,&m))
roentgen b75cab
				return(0);
roentgen b75cab
			if (m==255)
roentgen b75cab
				break;
roentgen b75cab
		}
roentgen b75cab
		while (1)
roentgen b75cab
		{
roentgen b75cab
			if (!JPEGFixupTagsSubsamplingReadByte(data,&m))
roentgen b75cab
				return(0);
roentgen b75cab
			if (m!=255)
roentgen b75cab
				break;
roentgen b75cab
		}
roentgen b75cab
		switch (m)
roentgen b75cab
		{
roentgen b75cab
			case JPEG_MARKER_SOI:
roentgen b75cab
				/* this type of marker has no data and should be skipped */
roentgen b75cab
				break;
roentgen b75cab
			case JPEG_MARKER_COM:
roentgen b75cab
			case JPEG_MARKER_APP0:
roentgen b75cab
			case JPEG_MARKER_APP0+1:
roentgen b75cab
			case JPEG_MARKER_APP0+2:
roentgen b75cab
			case JPEG_MARKER_APP0+3:
roentgen b75cab
			case JPEG_MARKER_APP0+4:
roentgen b75cab
			case JPEG_MARKER_APP0+5:
roentgen b75cab
			case JPEG_MARKER_APP0+6:
roentgen b75cab
			case JPEG_MARKER_APP0+7:
roentgen b75cab
			case JPEG_MARKER_APP0+8:
roentgen b75cab
			case JPEG_MARKER_APP0+9:
roentgen b75cab
			case JPEG_MARKER_APP0+10:
roentgen b75cab
			case JPEG_MARKER_APP0+11:
roentgen b75cab
			case JPEG_MARKER_APP0+12:
roentgen b75cab
			case JPEG_MARKER_APP0+13:
roentgen b75cab
			case JPEG_MARKER_APP0+14:
roentgen b75cab
			case JPEG_MARKER_APP0+15:
roentgen b75cab
			case JPEG_MARKER_DQT:
roentgen b75cab
			case JPEG_MARKER_SOS:
roentgen b75cab
			case JPEG_MARKER_DHT:
roentgen b75cab
			case JPEG_MARKER_DRI:
roentgen b75cab
				/* this type of marker has data, but it has no use to us and should be skipped */
roentgen b75cab
				{
roentgen b75cab
					uint16 n;
roentgen b75cab
					if (!JPEGFixupTagsSubsamplingReadWord(data,&n))
roentgen b75cab
						return(0);
roentgen b75cab
					if (n<2)
roentgen b75cab
						return(0);
roentgen b75cab
					n-=2;
roentgen b75cab
					if (n>0)
roentgen b75cab
						JPEGFixupTagsSubsamplingSkip(data,n);
roentgen b75cab
				}
roentgen b75cab
				break;
roentgen b75cab
			case JPEG_MARKER_SOF0:
roentgen b75cab
			case JPEG_MARKER_SOF1:
roentgen b75cab
				/* this marker contains the subsampling factors we're scanning for */
roentgen b75cab
				{
roentgen b75cab
					uint16 n;
roentgen b75cab
					uint16 o;
roentgen b75cab
					uint8 p;
roentgen b75cab
					uint8 ph,pv;
roentgen b75cab
					if (!JPEGFixupTagsSubsamplingReadWord(data,&n))
roentgen b75cab
						return(0);
roentgen b75cab
					if (n!=8+data->tif->tif_dir.td_samplesperpixel*3)
roentgen b75cab
						return(0);
roentgen b75cab
					JPEGFixupTagsSubsamplingSkip(data,7);
roentgen b75cab
					if (!JPEGFixupTagsSubsamplingReadByte(data,&p))
roentgen b75cab
						return(0);
roentgen b75cab
					ph=(p>>4);
roentgen b75cab
					pv=(p&15);
roentgen b75cab
					JPEGFixupTagsSubsamplingSkip(data,1);
roentgen b75cab
					for (o=1; o<data->tif->tif_dir.td_samplesperpixel; o++)</data->
roentgen b75cab
					{
roentgen b75cab
						JPEGFixupTagsSubsamplingSkip(data,1);
roentgen b75cab
						if (!JPEGFixupTagsSubsamplingReadByte(data,&p))
roentgen b75cab
							return(0);
roentgen b75cab
						if (p!=0x11)
roentgen b75cab
						{
roentgen b75cab
							TIFFWarningExt(data->tif->tif_clientdata,module,
roentgen b75cab
							    "Subsampling values inside JPEG compressed data have no TIFF equivalent, auto-correction of TIFF subsampling values failed");
roentgen b75cab
							return(1);
roentgen b75cab
						}
roentgen b75cab
						JPEGFixupTagsSubsamplingSkip(data,1);
roentgen b75cab
					}
roentgen b75cab
					if (((ph!=1)&&(ph!=2)&&(ph!=4))||((pv!=1)&&(pv!=2)&&(pv!=4)))
roentgen b75cab
					{
roentgen b75cab
						TIFFWarningExt(data->tif->tif_clientdata,module,
roentgen b75cab
						    "Subsampling values inside JPEG compressed data have no TIFF equivalent, auto-correction of TIFF subsampling values failed");
roentgen b75cab
						return(1);
roentgen b75cab
					}
roentgen b75cab
					if ((ph!=data->tif->tif_dir.td_ycbcrsubsampling[0])||(pv!=data->tif->tif_dir.td_ycbcrsubsampling[1]))
roentgen b75cab
					{
roentgen b75cab
						TIFFWarningExt(data->tif->tif_clientdata,module,
roentgen b75cab
						    "Auto-corrected former TIFF subsampling values [%d,%d] to match subsampling values inside JPEG compressed data [%d,%d]",
roentgen b75cab
						    (int)data->tif->tif_dir.td_ycbcrsubsampling[0],
roentgen b75cab
						    (int)data->tif->tif_dir.td_ycbcrsubsampling[1],
roentgen b75cab
						    (int)ph,(int)pv);
roentgen b75cab
						data->tif->tif_dir.td_ycbcrsubsampling[0]=ph;
roentgen b75cab
						data->tif->tif_dir.td_ycbcrsubsampling[1]=pv;
roentgen b75cab
					}
roentgen b75cab
				}
roentgen b75cab
				return(1);
roentgen b75cab
			default:
roentgen b75cab
				return(0);
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
JPEGFixupTagsSubsamplingReadByte(struct JPEGFixupTagsSubsamplingData* data, uint8* result)
roentgen b75cab
{
roentgen b75cab
	if (data->bufferbytesleft==0)
roentgen b75cab
	{
roentgen b75cab
		uint32 m;
roentgen b75cab
		if (data->filebytesleft==0)
roentgen b75cab
			return(0);
roentgen b75cab
		if (!data->filepositioned)
roentgen b75cab
		{
roentgen b75cab
			TIFFSeekFile(data->tif,data->fileoffset,SEEK_SET);
roentgen b75cab
			data->filepositioned=1;
roentgen b75cab
		}
roentgen b75cab
		m=data->buffersize;
roentgen b75cab
		if ((uint64)m>data->filebytesleft)
roentgen b75cab
			m=(uint32)data->filebytesleft;
roentgen b75cab
		assert(m<0x80000000UL);
roentgen b75cab
		if (TIFFReadFile(data->tif,data->buffer,(tmsize_t)m)!=(tmsize_t)m)
roentgen b75cab
			return(0);
roentgen b75cab
		data->buffercurrentbyte=data->buffer;
roentgen b75cab
		data->bufferbytesleft=m;
roentgen b75cab
		data->fileoffset+=m;
roentgen b75cab
		data->filebytesleft-=m;
roentgen b75cab
	}
roentgen b75cab
	*result=*data->buffercurrentbyte;
roentgen b75cab
	data->buffercurrentbyte++;
roentgen b75cab
	data->bufferbytesleft--;
roentgen b75cab
	return(1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
JPEGFixupTagsSubsamplingReadWord(struct JPEGFixupTagsSubsamplingData* data, uint16* result)
roentgen b75cab
{
roentgen b75cab
	uint8 ma;
roentgen b75cab
	uint8 mb;
roentgen b75cab
	if (!JPEGFixupTagsSubsamplingReadByte(data,&ma))
roentgen b75cab
		return(0);
roentgen b75cab
	if (!JPEGFixupTagsSubsamplingReadByte(data,&mb))
roentgen b75cab
		return(0);
roentgen b75cab
	*result=(ma<<8)|mb;
roentgen b75cab
	return(1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData* data, uint16 skiplength)
roentgen b75cab
{
roentgen b75cab
	if ((uint32)skiplength<=data->bufferbytesleft)
roentgen b75cab
	{
roentgen b75cab
		data->buffercurrentbyte+=skiplength;
roentgen b75cab
		data->bufferbytesleft-=skiplength;
roentgen b75cab
	}
roentgen b75cab
	else
roentgen b75cab
	{
roentgen b75cab
		uint16 m;
roentgen b75cab
		m=skiplength-data->bufferbytesleft;
roentgen b75cab
		if (m<=data->filebytesleft)
roentgen b75cab
		{
roentgen b75cab
			data->bufferbytesleft=0;
roentgen b75cab
			data->fileoffset+=m;
roentgen b75cab
			data->filebytesleft-=m;
roentgen b75cab
			data->filepositioned=0;
roentgen b75cab
		}
roentgen b75cab
		else
roentgen b75cab
		{
roentgen b75cab
			data->bufferbytesleft=0;
roentgen b75cab
			data->filebytesleft=0;
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
JPEGSetupDecode(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
	TIFFDirectory *td = &tif->tif_dir;
roentgen b75cab
roentgen b75cab
#if defined(JPEG_DUAL_MODE_8_12) && !defined(TIFFInitJPEG)
roentgen b75cab
        if( tif->tif_dir.td_bitspersample == 12 )
roentgen b75cab
            return TIFFReInitJPEG_12( tif, COMPRESSION_JPEG, 0 );
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
	JPEGInitializeLibJPEG( tif, TRUE );
roentgen b75cab
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
	assert(sp->cinfo.comm.is_decompressor);
roentgen b75cab
roentgen b75cab
	/* Read JPEGTables if it is present */
roentgen b75cab
	if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) {
roentgen b75cab
		TIFFjpeg_tables_src(sp, tif);
roentgen b75cab
		if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, "JPEGSetupDecode", "Bogus JPEGTables field");
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	/* Grab parameters that are same for all strips/tiles */
roentgen b75cab
	sp->photometric = td->td_photometric;
roentgen b75cab
	switch (sp->photometric) {
roentgen b75cab
	case PHOTOMETRIC_YCBCR:
roentgen b75cab
		sp->h_sampling = td->td_ycbcrsubsampling[0];
roentgen b75cab
		sp->v_sampling = td->td_ycbcrsubsampling[1];
roentgen b75cab
		break;
roentgen b75cab
	default:
roentgen b75cab
		/* TIFF 6.0 forbids subsampling of all other color spaces */
roentgen b75cab
		sp->h_sampling = 1;
roentgen b75cab
		sp->v_sampling = 1;
roentgen b75cab
		break;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	/* Set up for reading normal data */
roentgen b75cab
	TIFFjpeg_data_src(sp, tif);
roentgen b75cab
	tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Set up for decoding a strip or tile.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
JPEGPreDecode(TIFF* tif, uint16 s)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = JState(tif);
roentgen b75cab
	TIFFDirectory *td = &tif->tif_dir;
roentgen b75cab
	static const char module[] = "JPEGPreDecode";
roentgen b75cab
	uint32 segment_width, segment_height;
roentgen b75cab
	int downsampled_output;
roentgen b75cab
	int ci;
roentgen b75cab
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
  
roentgen b75cab
	if (sp->cinfo.comm.is_decompressor == 0)
roentgen b75cab
	{
roentgen b75cab
		tif->tif_setupdecode( tif );
roentgen b75cab
	}
roentgen b75cab
  
roentgen b75cab
	assert(sp->cinfo.comm.is_decompressor);
roentgen b75cab
	/*
roentgen b75cab
	 * Reset decoder state from any previous strip/tile,
roentgen b75cab
	 * in case application didn't read the whole strip.
roentgen b75cab
	 */
roentgen b75cab
	if (!TIFFjpeg_abort(sp))
roentgen b75cab
		return (0);
roentgen b75cab
	/*
roentgen b75cab
	 * Read the header for this strip/tile.
roentgen b75cab
	 */
roentgen b75cab
        
roentgen b75cab
	if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK)
roentgen b75cab
		return (0);
roentgen b75cab
roentgen b75cab
        tif->tif_rawcp = (uint8*) sp->src.next_input_byte;
roentgen b75cab
        tif->tif_rawcc = sp->src.bytes_in_buffer;
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Check image parameters and set decompression parameters.
roentgen b75cab
	 */
roentgen b75cab
	segment_width = td->td_imagewidth;
roentgen b75cab
	segment_height = td->td_imagelength - tif->tif_row;
roentgen b75cab
	if (isTiled(tif)) {
roentgen b75cab
                segment_width = td->td_tilewidth;
roentgen b75cab
                segment_height = td->td_tilelength;
roentgen b75cab
		sp->bytesperline = TIFFTileRowSize(tif);
roentgen b75cab
	} else {
roentgen b75cab
		if (segment_height > td->td_rowsperstrip)
roentgen b75cab
			segment_height = td->td_rowsperstrip;
roentgen b75cab
		sp->bytesperline = TIFFScanlineSize(tif);
roentgen b75cab
	}
roentgen b75cab
	if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) {
roentgen b75cab
		/*
roentgen b75cab
		 * For PC 2, scale down the expected strip/tile size
roentgen b75cab
		 * to match a downsampled component
roentgen b75cab
		 */
roentgen b75cab
		segment_width = TIFFhowmany_32(segment_width, sp->h_sampling);
roentgen b75cab
		segment_height = TIFFhowmany_32(segment_height, sp->v_sampling);
roentgen b75cab
	}
roentgen b75cab
	if (sp->cinfo.d.image_width < segment_width ||
roentgen b75cab
	    sp->cinfo.d.image_height < segment_height) {
roentgen b75cab
		TIFFWarningExt(tif->tif_clientdata, module,
roentgen b75cab
			       "Improper JPEG strip/tile size, "
roentgen b75cab
			       "expected %dx%d, got %dx%d",
roentgen b75cab
			       segment_width, segment_height,
roentgen b75cab
			       sp->cinfo.d.image_width,
roentgen b75cab
			       sp->cinfo.d.image_height);
roentgen b75cab
	} 
roentgen b75cab
	if (sp->cinfo.d.image_width > segment_width ||
roentgen b75cab
	    sp->cinfo.d.image_height > segment_height) {
roentgen b75cab
		/*
roentgen b75cab
		 * This case could be dangerous, if the strip or tile size has
roentgen b75cab
		 * been reported as less than the amount of data jpeg will
roentgen b75cab
		 * return, some potential security issues arise. Catch this
roentgen b75cab
		 * case and error out.
roentgen b75cab
		 */
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
			     "JPEG strip/tile size exceeds expected dimensions,"
roentgen b75cab
			     " expected %dx%d, got %dx%d",
roentgen b75cab
			     segment_width, segment_height,
roentgen b75cab
			     sp->cinfo.d.image_width, sp->cinfo.d.image_height);
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
	if (sp->cinfo.d.num_components !=
roentgen b75cab
	    (td->td_planarconfig == PLANARCONFIG_CONTIG ?
roentgen b75cab
	     td->td_samplesperpixel : 1)) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG component count");
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
#ifdef JPEG_LIB_MK1
roentgen b75cab
	if (12 != td->td_bitspersample && 8 != td->td_bitspersample) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision");
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
	sp->cinfo.d.data_precision = td->td_bitspersample;
roentgen b75cab
	sp->cinfo.d.bits_in_jsample = td->td_bitspersample;
roentgen b75cab
#else
roentgen b75cab
	if (sp->cinfo.d.data_precision != td->td_bitspersample) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision");
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
#endif
roentgen b75cab
	if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
roentgen b75cab
		/* Component 0 should have expected sampling factors */
roentgen b75cab
		if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling ||
roentgen b75cab
		    sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
				       "Improper JPEG sampling factors %d,%d\n"
roentgen b75cab
				       "Apparently should be %d,%d.",
roentgen b75cab
				       sp->cinfo.d.comp_info[0].h_samp_factor,
roentgen b75cab
				       sp->cinfo.d.comp_info[0].v_samp_factor,
roentgen b75cab
				       sp->h_sampling, sp->v_sampling);
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
		/* Rest should have sampling factors 1,1 */
roentgen b75cab
		for (ci = 1; ci < sp->cinfo.d.num_components; ci++) {
roentgen b75cab
			if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 ||
roentgen b75cab
			    sp->cinfo.d.comp_info[ci].v_samp_factor != 1) {
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors");
roentgen b75cab
				return (0);
roentgen b75cab
			}
roentgen b75cab
		}
roentgen b75cab
	} else {
roentgen b75cab
		/* PC 2's single component should have sampling factors 1,1 */
roentgen b75cab
		if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 ||
roentgen b75cab
		    sp->cinfo.d.comp_info[0].v_samp_factor != 1) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors");
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
	downsampled_output = FALSE;
roentgen b75cab
	if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
roentgen b75cab
	    sp->photometric == PHOTOMETRIC_YCBCR &&
roentgen b75cab
	    sp->jpegcolormode == JPEGCOLORMODE_RGB) {
roentgen b75cab
		/* Convert YCbCr to RGB */
roentgen b75cab
		sp->cinfo.d.jpeg_color_space = JCS_YCbCr;
roentgen b75cab
		sp->cinfo.d.out_color_space = JCS_RGB;
roentgen b75cab
	} else {
roentgen b75cab
		/* Suppress colorspace handling */
roentgen b75cab
		sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN;
roentgen b75cab
		sp->cinfo.d.out_color_space = JCS_UNKNOWN;
roentgen b75cab
		if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
roentgen b75cab
		    (sp->h_sampling != 1 || sp->v_sampling != 1))
roentgen b75cab
			downsampled_output = TRUE;
roentgen b75cab
		/* XXX what about up-sampling? */
roentgen b75cab
	}
roentgen b75cab
	if (downsampled_output) {
roentgen b75cab
		/* Need to use raw-data interface to libjpeg */
roentgen b75cab
		sp->cinfo.d.raw_data_out = TRUE;
roentgen b75cab
#if JPEG_LIB_VERSION >= 70
roentgen b75cab
		sp->cinfo.d.do_fancy_upsampling = FALSE;
roentgen b75cab
#endif /* JPEG_LIB_VERSION >= 70 */
roentgen b75cab
		tif->tif_decoderow = DecodeRowError;
roentgen b75cab
		tif->tif_decodestrip = JPEGDecodeRaw;
roentgen b75cab
		tif->tif_decodetile = JPEGDecodeRaw;
roentgen b75cab
	} else {
roentgen b75cab
		/* Use normal interface to libjpeg */
roentgen b75cab
		sp->cinfo.d.raw_data_out = FALSE;
roentgen b75cab
		tif->tif_decoderow = JPEGDecode;
roentgen b75cab
		tif->tif_decodestrip = JPEGDecode;
roentgen b75cab
		tif->tif_decodetile = JPEGDecode;  
roentgen b75cab
	}
roentgen b75cab
	/* Start JPEG decompressor */
roentgen b75cab
	if (!TIFFjpeg_start_decompress(sp))
roentgen b75cab
		return (0);
roentgen b75cab
	/* Allocate downsampled-data buffers if needed */
roentgen b75cab
	if (downsampled_output) {
roentgen b75cab
		if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info,
roentgen b75cab
					       sp->cinfo.d.num_components))
roentgen b75cab
			return (0);
roentgen b75cab
		sp->scancount = DCTSIZE;	/* mark buffer empty */
roentgen b75cab
	}
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Decode a chunk of pixels.
roentgen b75cab
 * "Standard" case: returned data is not downsampled.
roentgen b75cab
 */
roentgen b75cab
/*ARGSUSED*/ static int
roentgen b75cab
JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = JState(tif);
roentgen b75cab
	tmsize_t nrows;
roentgen b75cab
	(void) s;
roentgen b75cab
roentgen b75cab
        /*
roentgen b75cab
        ** Update available information, buffer may have been refilled
roentgen b75cab
        ** between decode requests
roentgen b75cab
        */
roentgen b75cab
	sp->src.next_input_byte = (const JOCTET*) tif->tif_rawcp;
roentgen b75cab
	sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc;
roentgen b75cab
roentgen b75cab
        if( sp->bytesperline == 0 )
roentgen b75cab
                return 0;
roentgen b75cab
        
roentgen b75cab
	nrows = cc / sp->bytesperline;
roentgen b75cab
	if (cc % sp->bytesperline)
roentgen b75cab
		TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline not read");
roentgen b75cab
roentgen b75cab
	if( nrows > (tmsize_t) sp->cinfo.d.image_height )
roentgen b75cab
		nrows = sp->cinfo.d.image_height;
roentgen b75cab
roentgen b75cab
	/* data is expected to be read in multiples of a scanline */
roentgen b75cab
	if (nrows)
roentgen b75cab
	{
roentgen b75cab
		JSAMPROW line_work_buf = NULL;
roentgen b75cab
roentgen b75cab
		/*
roentgen b75cab
		 * For 6B, only use temporary buffer for 12 bit imagery.
roentgen b75cab
		 * For Mk1 always use it.
roentgen b75cab
		 */
roentgen b75cab
#if !defined(JPEG_LIB_MK1)
roentgen b75cab
		if( sp->cinfo.d.data_precision == 12 )
roentgen b75cab
#endif
roentgen b75cab
		{
roentgen b75cab
			line_work_buf = (JSAMPROW)
roentgen b75cab
			    _TIFFmalloc(sizeof(short) * sp->cinfo.d.output_width
roentgen b75cab
			    * sp->cinfo.d.num_components );
roentgen b75cab
		}
roentgen b75cab
roentgen b75cab
		do {
roentgen b75cab
			if( line_work_buf != NULL )
roentgen b75cab
			{
roentgen b75cab
				/*
roentgen b75cab
				 * In the MK1 case, we aways read into a 16bit buffer, and then
roentgen b75cab
				 * pack down to 12bit or 8bit.  In 6B case we only read into 16
roentgen b75cab
				 * bit buffer for 12bit data, which we need to repack.
roentgen b75cab
				*/
roentgen b75cab
				if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
roentgen b75cab
					return (0);
roentgen b75cab
roentgen b75cab
				if( sp->cinfo.d.data_precision == 12 )
roentgen b75cab
				{
roentgen b75cab
					int value_pairs = (sp->cinfo.d.output_width
roentgen b75cab
					    * sp->cinfo.d.num_components) / 2;
roentgen b75cab
					int iPair;
roentgen b75cab
roentgen b75cab
					for( iPair = 0; iPair < value_pairs; iPair++ )
roentgen b75cab
					{
roentgen b75cab
						unsigned char *out_ptr =
roentgen b75cab
						    ((unsigned char *) buf) + iPair * 3;
roentgen b75cab
						JSAMPLE *in_ptr = line_work_buf + iPair * 2;
roentgen b75cab
roentgen b75cab
						out_ptr[0] = (in_ptr[0] & 0xff0) >> 4;
roentgen b75cab
						out_ptr[1] = ((in_ptr[0] & 0xf) << 4)
roentgen b75cab
						    | ((in_ptr[1] & 0xf00) >> 8);
roentgen b75cab
						out_ptr[2] = ((in_ptr[1] & 0xff) >> 0);
roentgen b75cab
					}
roentgen b75cab
				}
roentgen b75cab
				else if( sp->cinfo.d.data_precision == 8 )
roentgen b75cab
				{
roentgen b75cab
					int value_count = (sp->cinfo.d.output_width
roentgen b75cab
					    * sp->cinfo.d.num_components);
roentgen b75cab
					int iValue;
roentgen b75cab
roentgen b75cab
					for( iValue = 0; iValue < value_count; iValue++ )
roentgen b75cab
					{
roentgen b75cab
						((unsigned char *) buf)[iValue] =
roentgen b75cab
						    line_work_buf[iValue] & 0xff;
roentgen b75cab
					}
roentgen b75cab
				}
roentgen b75cab
			}
roentgen b75cab
			else
roentgen b75cab
			{
roentgen b75cab
				/*
roentgen b75cab
				 * In the libjpeg6b 8bit case.  We read directly into the
roentgen b75cab
				 * TIFF buffer.
roentgen b75cab
				*/
roentgen b75cab
				JSAMPROW bufptr = (JSAMPROW)buf;
roentgen b75cab
roentgen b75cab
				if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1)
roentgen b75cab
					return (0);
roentgen b75cab
			}
roentgen b75cab
roentgen b75cab
			++tif->tif_row;
roentgen b75cab
			buf += sp->bytesperline;
roentgen b75cab
			cc -= sp->bytesperline;
roentgen b75cab
		} while (--nrows > 0);
roentgen b75cab
roentgen b75cab
		if( line_work_buf != NULL )
roentgen b75cab
			_TIFFfree( line_work_buf );
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
        /* Update information on consumed data */
roentgen b75cab
        tif->tif_rawcp = (uint8*) sp->src.next_input_byte;
roentgen b75cab
        tif->tif_rawcc = sp->src.bytes_in_buffer;
roentgen b75cab
                
roentgen b75cab
	/* Close down the decompressor if we've finished the strip or tile. */
roentgen b75cab
	return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
roentgen b75cab
	    || TIFFjpeg_finish_decompress(sp);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*ARGSUSED*/ static int
roentgen b75cab
DecodeRowError(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
roentgen b75cab
roentgen b75cab
{
roentgen b75cab
    (void) buf;
roentgen b75cab
    (void) cc;
roentgen b75cab
    (void) s;
roentgen b75cab
roentgen b75cab
    TIFFErrorExt(tif->tif_clientdata, "TIFFReadScanline",
roentgen b75cab
                 "scanline oriented access is not supported for downsampled JPEG compressed images, consider enabling TIFF_JPEGCOLORMODE as JPEGCOLORMODE_RGB." );
roentgen b75cab
    return 0;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Decode a chunk of pixels.
roentgen b75cab
 * Returned data is downsampled per sampling factors.
roentgen b75cab
 */
roentgen b75cab
/*ARGSUSED*/ static int
roentgen b75cab
JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = JState(tif);
roentgen b75cab
	tmsize_t nrows;
roentgen b75cab
	(void) s;
roentgen b75cab
roentgen b75cab
	/* data is expected to be read in multiples of a scanline */
roentgen b75cab
	if ( (nrows = sp->cinfo.d.image_height) ) {
roentgen b75cab
roentgen b75cab
		/* Cb,Cr both have sampling factors 1, so this is correct */
roentgen b75cab
		JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width;            
roentgen b75cab
		int samples_per_clump = sp->samplesperclump;
roentgen b75cab
roentgen b75cab
#if defined(JPEG_LIB_MK1_OR_12BIT)
roentgen b75cab
		unsigned short* tmpbuf = _TIFFmalloc(sizeof(unsigned short) *
roentgen b75cab
						     sp->cinfo.d.output_width *
roentgen b75cab
						     sp->cinfo.d.num_components);
roentgen b75cab
		if(tmpbuf==NULL) {
roentgen b75cab
                        TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw",
roentgen b75cab
				     "Out of memory");
roentgen b75cab
			return 0;
roentgen b75cab
                }
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
		do {
roentgen b75cab
			jpeg_component_info *compptr;
roentgen b75cab
			int ci, clumpoffset;
roentgen b75cab
roentgen b75cab
                        if( cc < sp->bytesperline ) {
roentgen b75cab
				TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw",
roentgen b75cab
					     "application buffer not large enough for all data.");
roentgen b75cab
				return 0;
roentgen b75cab
                        }
roentgen b75cab
roentgen b75cab
			/* Reload downsampled-data buffer if needed */
roentgen b75cab
			if (sp->scancount >= DCTSIZE) {
roentgen b75cab
				int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE;
roentgen b75cab
				if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) != n)
roentgen b75cab
					return (0);
roentgen b75cab
				sp->scancount = 0;
roentgen b75cab
			}
roentgen b75cab
			/*
roentgen b75cab
			 * Fastest way to unseparate data is to make one pass
roentgen b75cab
			 * over the scanline for each row of each component.
roentgen b75cab
			 */
roentgen b75cab
			clumpoffset = 0;    /* first sample in clump */
roentgen b75cab
			for (ci = 0, compptr = sp->cinfo.d.comp_info;
roentgen b75cab
			     ci < sp->cinfo.d.num_components;
roentgen b75cab
			     ci++, compptr++) {
roentgen b75cab
				int hsamp = compptr->h_samp_factor;
roentgen b75cab
				int vsamp = compptr->v_samp_factor;
roentgen b75cab
				int ypos;
roentgen b75cab
roentgen b75cab
				for (ypos = 0; ypos < vsamp; ypos++) {
roentgen b75cab
					JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];
roentgen b75cab
					JDIMENSION nclump;
roentgen b75cab
#if defined(JPEG_LIB_MK1_OR_12BIT)
roentgen b75cab
					JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset;
roentgen b75cab
#else
roentgen b75cab
					JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset;
roentgen b75cab
					if (cc < (tmsize_t) (clumpoffset + samples_per_clump*(clumps_per_line-1) + hsamp)) {
roentgen b75cab
						TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw",
roentgen b75cab
							     "application buffer not large enough for all data, possible subsampling issue");
roentgen b75cab
						return 0;
roentgen b75cab
					}
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
					if (hsamp == 1) {
roentgen b75cab
						/* fast path for at least Cb and Cr */
roentgen b75cab
						for (nclump = clumps_per_line; nclump-- > 0; ) {
roentgen b75cab
							outptr[0] = *inptr++;
roentgen b75cab
							outptr += samples_per_clump;
roentgen b75cab
						}
roentgen b75cab
					} else {
roentgen b75cab
						int xpos;
roentgen b75cab
roentgen b75cab
						/* general case */
roentgen b75cab
						for (nclump = clumps_per_line; nclump-- > 0; ) {
roentgen b75cab
							for (xpos = 0; xpos < hsamp; xpos++)
roentgen b75cab
								outptr[xpos] = *inptr++;
roentgen b75cab
							outptr += samples_per_clump;
roentgen b75cab
						}
roentgen b75cab
					}
roentgen b75cab
					clumpoffset += hsamp;
roentgen b75cab
				}
roentgen b75cab
			}
roentgen b75cab
roentgen b75cab
#if defined(JPEG_LIB_MK1_OR_12BIT)
roentgen b75cab
			{
roentgen b75cab
				if (sp->cinfo.d.data_precision == 8)
roentgen b75cab
				{
roentgen b75cab
					int i=0;
roentgen b75cab
					int len = sp->cinfo.d.output_width * sp->cinfo.d.num_components;
roentgen b75cab
					for (i=0; i
roentgen b75cab
					{
roentgen b75cab
						((unsigned char*)buf)[i] = tmpbuf[i] & 0xff;
roentgen b75cab
					}
roentgen b75cab
				}
roentgen b75cab
				else
roentgen b75cab
				{         /* 12-bit */
roentgen b75cab
					int value_pairs = (sp->cinfo.d.output_width
roentgen b75cab
							   * sp->cinfo.d.num_components) / 2;
roentgen b75cab
					int iPair;
roentgen b75cab
					for( iPair = 0; iPair < value_pairs; iPair++ )
roentgen b75cab
					{
roentgen b75cab
						unsigned char *out_ptr = ((unsigned char *) buf) + iPair * 3;
roentgen b75cab
						JSAMPLE *in_ptr = (JSAMPLE *) (tmpbuf + iPair * 2);
roentgen b75cab
						out_ptr[0] = (in_ptr[0] & 0xff0) >> 4;
roentgen b75cab
						out_ptr[1] = ((in_ptr[0] & 0xf) << 4)
roentgen b75cab
							| ((in_ptr[1] & 0xf00) >> 8);
roentgen b75cab
						out_ptr[2] = ((in_ptr[1] & 0xff) >> 0);
roentgen b75cab
					}
roentgen b75cab
				}
roentgen b75cab
			}
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
			sp->scancount ++;
roentgen b75cab
			tif->tif_row += sp->v_sampling;
roentgen b75cab
roentgen b75cab
			buf += sp->bytesperline;
roentgen b75cab
			cc -= sp->bytesperline;
roentgen b75cab
roentgen b75cab
			nrows -= sp->v_sampling;
roentgen b75cab
		} while (nrows > 0);
roentgen b75cab
roentgen b75cab
#if defined(JPEG_LIB_MK1_OR_12BIT)
roentgen b75cab
		_TIFFfree(tmpbuf);
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	/* Close down the decompressor if done. */
roentgen b75cab
	return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
roentgen b75cab
		|| TIFFjpeg_finish_decompress(sp);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * JPEG Encoding.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
unsuppress_quant_table (JPEGState* sp, int tblno)
roentgen b75cab
{
roentgen b75cab
	JQUANT_TBL* qtbl;
roentgen b75cab
roentgen b75cab
	if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL)
roentgen b75cab
		qtbl->sent_table = FALSE;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
unsuppress_huff_table (JPEGState* sp, int tblno)
roentgen b75cab
{
roentgen b75cab
	JHUFF_TBL* htbl;
roentgen b75cab
roentgen b75cab
	if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL)
roentgen b75cab
		htbl->sent_table = FALSE;
roentgen b75cab
	if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL)
roentgen b75cab
		htbl->sent_table = FALSE;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
prepare_JPEGTables(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
roentgen b75cab
	/* Initialize quant tables for current quality setting */
roentgen b75cab
	if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))
roentgen b75cab
		return (0);
roentgen b75cab
	/* Mark only the tables we want for output */
roentgen b75cab
	/* NB: chrominance tables are currently used only with YCbCr */
roentgen b75cab
	if (!TIFFjpeg_suppress_tables(sp, TRUE))
roentgen b75cab
		return (0);
roentgen b75cab
	if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) {
roentgen b75cab
		unsuppress_quant_table(sp, 0);
roentgen b75cab
		if (sp->photometric == PHOTOMETRIC_YCBCR)
roentgen b75cab
			unsuppress_quant_table(sp, 1);
roentgen b75cab
	}
roentgen b75cab
	if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) {
roentgen b75cab
		unsuppress_huff_table(sp, 0);
roentgen b75cab
		if (sp->photometric == PHOTOMETRIC_YCBCR)
roentgen b75cab
			unsuppress_huff_table(sp, 1);
roentgen b75cab
	}
roentgen b75cab
	/* Direct libjpeg output into jpegtables */
roentgen b75cab
	if (!TIFFjpeg_tables_dest(sp, tif))
roentgen b75cab
		return (0);
roentgen b75cab
	/* Emit tables-only datastream */
roentgen b75cab
	if (!TIFFjpeg_write_tables(sp))
roentgen b75cab
		return (0);
roentgen b75cab
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
JPEGSetupEncode(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
	TIFFDirectory *td = &tif->tif_dir;
roentgen b75cab
	static const char module[] = "JPEGSetupEncode";
roentgen b75cab
roentgen b75cab
#if defined(JPEG_DUAL_MODE_8_12) && !defined(TIFFInitJPEG)
roentgen b75cab
        if( tif->tif_dir.td_bitspersample == 12 )
roentgen b75cab
            return TIFFReInitJPEG_12( tif, COMPRESSION_JPEG, 1 );
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
        JPEGInitializeLibJPEG( tif, FALSE );
roentgen b75cab
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
	assert(!sp->cinfo.comm.is_decompressor);
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Initialize all JPEG parameters to default values.
roentgen b75cab
	 * Note that jpeg_set_defaults needs legal values for
roentgen b75cab
	 * in_color_space and input_components.
roentgen b75cab
	 */
roentgen b75cab
	sp->cinfo.c.in_color_space = JCS_UNKNOWN;
roentgen b75cab
	sp->cinfo.c.input_components = 1;
roentgen b75cab
	if (!TIFFjpeg_set_defaults(sp))
roentgen b75cab
		return (0);
roentgen b75cab
	/* Set per-file parameters */
roentgen b75cab
	sp->photometric = td->td_photometric;
roentgen b75cab
	switch (sp->photometric) {
roentgen b75cab
	case PHOTOMETRIC_YCBCR:
roentgen b75cab
		sp->h_sampling = td->td_ycbcrsubsampling[0];
roentgen b75cab
		sp->v_sampling = td->td_ycbcrsubsampling[1];
roentgen b75cab
		/*
roentgen b75cab
		 * A ReferenceBlackWhite field *must* be present since the
roentgen b75cab
		 * default value is inappropriate for YCbCr.  Fill in the
roentgen b75cab
		 * proper value if application didn't set it.
roentgen b75cab
		 */
roentgen b75cab
		{
roentgen b75cab
			float *ref;
roentgen b75cab
			if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE,
roentgen b75cab
					  &ref)) {
roentgen b75cab
				float refbw[6];
roentgen b75cab
				long top = 1L << td->td_bitspersample;
roentgen b75cab
				refbw[0] = 0;
roentgen b75cab
				refbw[1] = (float)(top-1L);
roentgen b75cab
				refbw[2] = (float)(top>>1);
roentgen b75cab
				refbw[3] = refbw[1];
roentgen b75cab
				refbw[4] = refbw[2];
roentgen b75cab
				refbw[5] = refbw[1];
roentgen b75cab
				TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE,
roentgen b75cab
					     refbw);
roentgen b75cab
			}
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case PHOTOMETRIC_PALETTE:		/* disallowed by Tech Note */
roentgen b75cab
	case PHOTOMETRIC_MASK:
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
			  "PhotometricInterpretation %d not allowed for JPEG",
roentgen b75cab
			  (int) sp->photometric);
roentgen b75cab
		return (0);
roentgen b75cab
	default:
roentgen b75cab
		/* TIFF 6.0 forbids subsampling of all other color spaces */
roentgen b75cab
		sp->h_sampling = 1;
roentgen b75cab
		sp->v_sampling = 1;
roentgen b75cab
		break;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	/* Verify miscellaneous parameters */
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * This would need work if libtiff ever supports different
roentgen b75cab
	 * depths for different components, or if libjpeg ever supports
roentgen b75cab
	 * run-time selection of depth.  Neither is imminent.
roentgen b75cab
	 */
roentgen b75cab
#ifdef JPEG_LIB_MK1
roentgen b75cab
        /* BITS_IN_JSAMPLE now permits 8 and 12 --- dgilbert */
roentgen b75cab
	if (td->td_bitspersample != 8 && td->td_bitspersample != 12) 
roentgen b75cab
#else
roentgen b75cab
	if (td->td_bitspersample != BITS_IN_JSAMPLE )
roentgen b75cab
#endif
roentgen b75cab
	{
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module, "BitsPerSample %d not allowed for JPEG",
roentgen b75cab
			  (int) td->td_bitspersample);
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
	sp->cinfo.c.data_precision = td->td_bitspersample;
roentgen b75cab
#ifdef JPEG_LIB_MK1
roentgen b75cab
        sp->cinfo.c.bits_in_jsample = td->td_bitspersample;
roentgen b75cab
#endif
roentgen b75cab
	if (isTiled(tif)) {
roentgen b75cab
		if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
				  "JPEG tile height must be multiple of %d",
roentgen b75cab
				  sp->v_sampling * DCTSIZE);
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
		if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
				  "JPEG tile width must be multiple of %d",
roentgen b75cab
				  sp->h_sampling * DCTSIZE);
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
	} else {
roentgen b75cab
		if (td->td_rowsperstrip < td->td_imagelength &&
roentgen b75cab
		    (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, module,
roentgen b75cab
				  "RowsPerStrip must be multiple of %d for JPEG",
roentgen b75cab
				  sp->v_sampling * DCTSIZE);
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	/* Create a JPEGTables field if appropriate */
roentgen b75cab
	if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) {
roentgen b75cab
                if( sp->jpegtables == NULL
roentgen b75cab
                    || memcmp(sp->jpegtables,"\0\0\0\0\0\0\0\0\0",8) == 0 )
roentgen b75cab
                {
roentgen b75cab
                        if (!prepare_JPEGTables(tif))
roentgen b75cab
                                return (0);
roentgen b75cab
                        /* Mark the field present */
roentgen b75cab
                        /* Can't use TIFFSetField since BEENWRITING is already set! */
roentgen b75cab
                        tif->tif_flags |= TIFF_DIRTYDIRECT;
roentgen b75cab
                        TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
roentgen b75cab
                }
roentgen b75cab
	} else {
roentgen b75cab
		/* We do not support application-supplied JPEGTables, */
roentgen b75cab
		/* so mark the field not present */
roentgen b75cab
		TIFFClrFieldBit(tif, FIELD_JPEGTABLES);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	/* Direct libjpeg output to libtiff's output buffer */
roentgen b75cab
	TIFFjpeg_data_dest(sp, tif);
roentgen b75cab
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Set encoding state at the start of a strip or tile.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
JPEGPreEncode(TIFF* tif, uint16 s)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = JState(tif);
roentgen b75cab
	TIFFDirectory *td = &tif->tif_dir;
roentgen b75cab
	static const char module[] = "JPEGPreEncode";
roentgen b75cab
	uint32 segment_width, segment_height;
roentgen b75cab
	int downsampled_input;
roentgen b75cab
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
  
roentgen b75cab
	if (sp->cinfo.comm.is_decompressor == 1)
roentgen b75cab
	{
roentgen b75cab
		tif->tif_setupencode( tif );
roentgen b75cab
	}
roentgen b75cab
  
roentgen b75cab
	assert(!sp->cinfo.comm.is_decompressor);
roentgen b75cab
	/*
roentgen b75cab
	 * Set encoding parameters for this strip/tile.
roentgen b75cab
	 */
roentgen b75cab
	if (isTiled(tif)) {
roentgen b75cab
		segment_width = td->td_tilewidth;
roentgen b75cab
		segment_height = td->td_tilelength;
roentgen b75cab
		sp->bytesperline = TIFFTileRowSize(tif);
roentgen b75cab
	} else {
roentgen b75cab
		segment_width = td->td_imagewidth;
roentgen b75cab
		segment_height = td->td_imagelength - tif->tif_row;
roentgen b75cab
		if (segment_height > td->td_rowsperstrip)
roentgen b75cab
			segment_height = td->td_rowsperstrip;
roentgen b75cab
		sp->bytesperline = TIFFScanlineSize(tif);
roentgen b75cab
	}
roentgen b75cab
	if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) {
roentgen b75cab
		/* for PC 2, scale down the strip/tile size
roentgen b75cab
		 * to match a downsampled component
roentgen b75cab
		 */
roentgen b75cab
		segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); 
roentgen b75cab
		segment_height = TIFFhowmany_32(segment_height, sp->v_sampling);
roentgen b75cab
	}
roentgen b75cab
	if (segment_width > 65535 || segment_height > 65535) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, module, "Strip/tile too large for JPEG");
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
	sp->cinfo.c.image_width = segment_width;
roentgen b75cab
	sp->cinfo.c.image_height = segment_height;
roentgen b75cab
	downsampled_input = FALSE;
roentgen b75cab
	if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
roentgen b75cab
		sp->cinfo.c.input_components = td->td_samplesperpixel;
roentgen b75cab
		if (sp->photometric == PHOTOMETRIC_YCBCR) {
roentgen b75cab
			if (sp->jpegcolormode == JPEGCOLORMODE_RGB) {
roentgen b75cab
				sp->cinfo.c.in_color_space = JCS_RGB;
roentgen b75cab
			} else {
roentgen b75cab
				sp->cinfo.c.in_color_space = JCS_YCbCr;
roentgen b75cab
				if (sp->h_sampling != 1 || sp->v_sampling != 1)
roentgen b75cab
					downsampled_input = TRUE;
roentgen b75cab
			}
roentgen b75cab
			if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr))
roentgen b75cab
				return (0);
roentgen b75cab
			/*
roentgen b75cab
			 * Set Y sampling factors;
roentgen b75cab
			 * we assume jpeg_set_colorspace() set the rest to 1
roentgen b75cab
			 */
roentgen b75cab
			sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling;
roentgen b75cab
			sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling;
roentgen b75cab
		} else {
roentgen b75cab
			if ((td->td_photometric == PHOTOMETRIC_MINISWHITE || td->td_photometric == PHOTOMETRIC_MINISBLACK) && td->td_samplesperpixel == 1)
roentgen b75cab
				sp->cinfo.c.in_color_space = JCS_GRAYSCALE;
roentgen b75cab
			else if (td->td_photometric == PHOTOMETRIC_RGB && td->td_samplesperpixel == 3)
roentgen b75cab
				sp->cinfo.c.in_color_space = JCS_RGB;
roentgen b75cab
			else if (td->td_photometric == PHOTOMETRIC_SEPARATED && td->td_samplesperpixel == 4)
roentgen b75cab
				sp->cinfo.c.in_color_space = JCS_CMYK;
roentgen b75cab
			else
roentgen b75cab
				sp->cinfo.c.in_color_space = JCS_UNKNOWN;
roentgen b75cab
			if (!TIFFjpeg_set_colorspace(sp, sp->cinfo.c.in_color_space))
roentgen b75cab
				return (0);
roentgen b75cab
			/* jpeg_set_colorspace set all sampling factors to 1 */
roentgen b75cab
		}
roentgen b75cab
	} else {
roentgen b75cab
		sp->cinfo.c.input_components = 1;
roentgen b75cab
		sp->cinfo.c.in_color_space = JCS_UNKNOWN;
roentgen b75cab
		if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN))
roentgen b75cab
			return (0);
roentgen b75cab
		sp->cinfo.c.comp_info[0].component_id = s;
roentgen b75cab
		/* jpeg_set_colorspace() set sampling factors to 1 */
roentgen b75cab
		if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) {
roentgen b75cab
			sp->cinfo.c.comp_info[0].quant_tbl_no = 1;
roentgen b75cab
			sp->cinfo.c.comp_info[0].dc_tbl_no = 1;
roentgen b75cab
			sp->cinfo.c.comp_info[0].ac_tbl_no = 1;
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
	/* ensure libjpeg won't write any extraneous markers */
roentgen b75cab
	sp->cinfo.c.write_JFIF_header = FALSE;
roentgen b75cab
	sp->cinfo.c.write_Adobe_marker = FALSE;
roentgen b75cab
	/* set up table handling correctly */
roentgen b75cab
        if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))
roentgen b75cab
		return (0);
roentgen b75cab
	if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) {
roentgen b75cab
		unsuppress_quant_table(sp, 0);
roentgen b75cab
		unsuppress_quant_table(sp, 1);
roentgen b75cab
	}
roentgen b75cab
	if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF)
roentgen b75cab
		sp->cinfo.c.optimize_coding = FALSE;
roentgen b75cab
	else
roentgen b75cab
		sp->cinfo.c.optimize_coding = TRUE;
roentgen b75cab
	if (downsampled_input) {
roentgen b75cab
		/* Need to use raw-data interface to libjpeg */
roentgen b75cab
		sp->cinfo.c.raw_data_in = TRUE;
roentgen b75cab
		tif->tif_encoderow = JPEGEncodeRaw;
roentgen b75cab
		tif->tif_encodestrip = JPEGEncodeRaw;
roentgen b75cab
		tif->tif_encodetile = JPEGEncodeRaw;
roentgen b75cab
	} else {
roentgen b75cab
		/* Use normal interface to libjpeg */
roentgen b75cab
		sp->cinfo.c.raw_data_in = FALSE;
roentgen b75cab
		tif->tif_encoderow = JPEGEncode;
roentgen b75cab
		tif->tif_encodestrip = JPEGEncode;
roentgen b75cab
		tif->tif_encodetile = JPEGEncode;
roentgen b75cab
	}
roentgen b75cab
	/* Start JPEG compressor */
roentgen b75cab
	if (!TIFFjpeg_start_compress(sp, FALSE))
roentgen b75cab
		return (0);
roentgen b75cab
	/* Allocate downsampled-data buffers if needed */
roentgen b75cab
	if (downsampled_input) {
roentgen b75cab
		if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info,
roentgen b75cab
					       sp->cinfo.c.num_components))
roentgen b75cab
			return (0);
roentgen b75cab
	}
roentgen b75cab
	sp->scancount = 0;
roentgen b75cab
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Encode a chunk of pixels.
roentgen b75cab
 * "Standard" case: incoming data is not downsampled.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = JState(tif);
roentgen b75cab
	tmsize_t nrows;
roentgen b75cab
	JSAMPROW bufptr[1];
roentgen b75cab
        short *line16 = NULL;
roentgen b75cab
        int    line16_count = 0;
roentgen b75cab
roentgen b75cab
	(void) s;
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
	/* data is expected to be supplied in multiples of a scanline */
roentgen b75cab
	nrows = cc / sp->bytesperline;
roentgen b75cab
	if (cc % sp->bytesperline)
roentgen b75cab
            TIFFWarningExt(tif->tif_clientdata, tif->tif_name, 
roentgen b75cab
                           "fractional scanline discarded");
roentgen b75cab
roentgen b75cab
        /* The last strip will be limited to image size */
roentgen b75cab
        if( !isTiled(tif) && tif->tif_row+nrows > tif->tif_dir.td_imagelength )
roentgen b75cab
            nrows = tif->tif_dir.td_imagelength - tif->tif_row;
roentgen b75cab
roentgen b75cab
        if( sp->cinfo.c.data_precision == 12 )
roentgen b75cab
        {
roentgen b75cab
            line16_count = (sp->bytesperline * 2) / 3;
roentgen b75cab
            line16 = (short *) _TIFFmalloc(sizeof(short) * line16_count);
roentgen b75cab
	    // FIXME: undiagnosed malloc failure
roentgen b75cab
        }
roentgen b75cab
            
roentgen b75cab
	while (nrows-- > 0) {
roentgen b75cab
roentgen b75cab
            if( sp->cinfo.c.data_precision == 12 )
roentgen b75cab
            {
roentgen b75cab
roentgen b75cab
                int value_pairs = line16_count / 2;
roentgen b75cab
                int iPair;
roentgen b75cab
roentgen b75cab
		bufptr[0] = (JSAMPROW) line16;
roentgen b75cab
roentgen b75cab
                for( iPair = 0; iPair < value_pairs; iPair++ )
roentgen b75cab
                {
roentgen b75cab
                    unsigned char *in_ptr =
roentgen b75cab
                        ((unsigned char *) buf) + iPair * 3;
roentgen b75cab
                    JSAMPLE *out_ptr = (JSAMPLE *) (line16 + iPair * 2);
roentgen b75cab
roentgen b75cab
                    out_ptr[0] = (in_ptr[0] << 4) | ((in_ptr[1] & 0xf0) >> 4);
roentgen b75cab
                    out_ptr[1] = ((in_ptr[1] & 0x0f) << 8) | in_ptr[2];
roentgen b75cab
                }
roentgen b75cab
            }
roentgen b75cab
            else
roentgen b75cab
            {
roentgen b75cab
		bufptr[0] = (JSAMPROW) buf;
roentgen b75cab
            }
roentgen b75cab
            if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1)
roentgen b75cab
                return (0);
roentgen b75cab
            if (nrows > 0)
roentgen b75cab
                tif->tif_row++;
roentgen b75cab
            buf += sp->bytesperline;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
        if( sp->cinfo.c.data_precision == 12 )
roentgen b75cab
        {
roentgen b75cab
            _TIFFfree( line16 );
roentgen b75cab
        }
roentgen b75cab
            
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Encode a chunk of pixels.
roentgen b75cab
 * Incoming data is expected to be downsampled per sampling factors.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
JPEGEncodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = JState(tif);
roentgen b75cab
	JSAMPLE* inptr;
roentgen b75cab
	JSAMPLE* outptr;
roentgen b75cab
	tmsize_t nrows;
roentgen b75cab
	JDIMENSION clumps_per_line, nclump;
roentgen b75cab
	int clumpoffset, ci, xpos, ypos;
roentgen b75cab
	jpeg_component_info* compptr;
roentgen b75cab
	int samples_per_clump = sp->samplesperclump;
roentgen b75cab
	tmsize_t bytesperclumpline;
roentgen b75cab
roentgen b75cab
	(void) s;
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
	/* data is expected to be supplied in multiples of a clumpline */
roentgen b75cab
	/* a clumpline is equivalent to v_sampling desubsampled scanlines */
roentgen b75cab
	/* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */
roentgen b75cab
	bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling)
roentgen b75cab
			     *(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7)
roentgen b75cab
			    /8;
roentgen b75cab
roentgen b75cab
	nrows = ( cc / bytesperclumpline ) * sp->v_sampling;
roentgen b75cab
	if (cc % bytesperclumpline)
roentgen b75cab
		TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded");
roentgen b75cab
roentgen b75cab
	/* Cb,Cr both have sampling factors 1, so this is correct */
roentgen b75cab
	clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width;
roentgen b75cab
roentgen b75cab
	while (nrows > 0) {
roentgen b75cab
		/*
roentgen b75cab
		 * Fastest way to separate the data is to make one pass
roentgen b75cab
		 * over the scanline for each row of each component.
roentgen b75cab
		 */
roentgen b75cab
		clumpoffset = 0;		/* first sample in clump */
roentgen b75cab
		for (ci = 0, compptr = sp->cinfo.c.comp_info;
roentgen b75cab
		     ci < sp->cinfo.c.num_components;
roentgen b75cab
		     ci++, compptr++) {
roentgen b75cab
		    int hsamp = compptr->h_samp_factor;
roentgen b75cab
		    int vsamp = compptr->v_samp_factor;
roentgen b75cab
		    int padding = (int) (compptr->width_in_blocks * DCTSIZE -
roentgen b75cab
					 clumps_per_line * hsamp);
roentgen b75cab
		    for (ypos = 0; ypos < vsamp; ypos++) {
roentgen b75cab
			inptr = ((JSAMPLE*) buf) + clumpoffset;
roentgen b75cab
			outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];
roentgen b75cab
			if (hsamp == 1) {
roentgen b75cab
			    /* fast path for at least Cb and Cr */
roentgen b75cab
			    for (nclump = clumps_per_line; nclump-- > 0; ) {
roentgen b75cab
				*outptr++ = inptr[0];
roentgen b75cab
				inptr += samples_per_clump;
roentgen b75cab
			    }
roentgen b75cab
			} else {
roentgen b75cab
			    /* general case */
roentgen b75cab
			    for (nclump = clumps_per_line; nclump-- > 0; ) {
roentgen b75cab
				for (xpos = 0; xpos < hsamp; xpos++)
roentgen b75cab
				    *outptr++ = inptr[xpos];
roentgen b75cab
				inptr += samples_per_clump;
roentgen b75cab
			    }
roentgen b75cab
			}
roentgen b75cab
			/* pad each scanline as needed */
roentgen b75cab
			for (xpos = 0; xpos < padding; xpos++) {
roentgen b75cab
			    *outptr = outptr[-1];
roentgen b75cab
			    outptr++;
roentgen b75cab
			}
roentgen b75cab
			clumpoffset += hsamp;
roentgen b75cab
		    }
roentgen b75cab
		}
roentgen b75cab
		sp->scancount++;
roentgen b75cab
		if (sp->scancount >= DCTSIZE) {
roentgen b75cab
			int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE;
roentgen b75cab
			if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n)
roentgen b75cab
				return (0);
roentgen b75cab
			sp->scancount = 0;
roentgen b75cab
		}
roentgen b75cab
		tif->tif_row += sp->v_sampling;
roentgen b75cab
		buf += bytesperclumpline;
roentgen b75cab
		nrows -= sp->v_sampling;
roentgen b75cab
	}
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Finish up at the end of a strip or tile.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
JPEGPostEncode(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = JState(tif);
roentgen b75cab
roentgen b75cab
	if (sp->scancount > 0) {
roentgen b75cab
		/*
roentgen b75cab
		 * Need to emit a partial bufferload of downsampled data.
roentgen b75cab
		 * Pad the data vertically.
roentgen b75cab
		 */
roentgen b75cab
		int ci, ypos, n;
roentgen b75cab
		jpeg_component_info* compptr;
roentgen b75cab
roentgen b75cab
		for (ci = 0, compptr = sp->cinfo.c.comp_info;
roentgen b75cab
		     ci < sp->cinfo.c.num_components;
roentgen b75cab
		     ci++, compptr++) {
roentgen b75cab
			int vsamp = compptr->v_samp_factor;
roentgen b75cab
			tmsize_t row_width = compptr->width_in_blocks * DCTSIZE
roentgen b75cab
				* sizeof(JSAMPLE);
roentgen b75cab
			for (ypos = sp->scancount * vsamp;
roentgen b75cab
			     ypos < DCTSIZE * vsamp; ypos++) {
roentgen b75cab
				_TIFFmemcpy((void*)sp->ds_buffer[ci][ypos],
roentgen b75cab
					    (void*)sp->ds_buffer[ci][ypos-1],
roentgen b75cab
					    row_width);
roentgen b75cab
roentgen b75cab
			}
roentgen b75cab
		}
roentgen b75cab
		n = sp->cinfo.c.max_v_samp_factor * DCTSIZE;
roentgen b75cab
		if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n)
roentgen b75cab
			return (0);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	return (TIFFjpeg_finish_compress(JState(tif)));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
JPEGCleanup(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	JPEGState *sp = JState(tif);
roentgen b75cab
	
roentgen b75cab
	assert(sp != 0);
roentgen b75cab
roentgen b75cab
	tif->tif_tagmethods.vgetfield = sp->vgetparent;
roentgen b75cab
	tif->tif_tagmethods.vsetfield = sp->vsetparent;
roentgen b75cab
	tif->tif_tagmethods.printdir = sp->printdir;
roentgen b75cab
roentgen b75cab
	if( sp != NULL ) {
roentgen b75cab
		if( sp->cinfo_initialized )
roentgen b75cab
		    TIFFjpeg_destroy(sp);	/* release libjpeg resources */
roentgen b75cab
		if (sp->jpegtables)		/* tag value */
roentgen b75cab
			_TIFFfree(sp->jpegtables);
roentgen b75cab
	}
roentgen b75cab
	_TIFFfree(tif->tif_data);	/* release local state */
roentgen b75cab
	tif->tif_data = NULL;
roentgen b75cab
roentgen b75cab
	_TIFFSetDefaultCompressionState(tif);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void 
roentgen b75cab
JPEGResetUpsampled( TIFF* tif )
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
	TIFFDirectory* td = &tif->tif_dir;
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Mark whether returned data is up-sampled or not so TIFFStripSize
roentgen b75cab
	 * and TIFFTileSize return values that reflect the true amount of
roentgen b75cab
	 * data.
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_flags &= ~TIFF_UPSAMPLED;
roentgen b75cab
	if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
roentgen b75cab
		if (td->td_photometric == PHOTOMETRIC_YCBCR &&
roentgen b75cab
		    sp->jpegcolormode == JPEGCOLORMODE_RGB) {
roentgen b75cab
			tif->tif_flags |= TIFF_UPSAMPLED;
roentgen b75cab
		} else {
roentgen b75cab
#ifdef notdef
roentgen b75cab
			if (td->td_ycbcrsubsampling[0] != 1 ||
roentgen b75cab
			    td->td_ycbcrsubsampling[1] != 1)
roentgen b75cab
				; /* XXX what about up-sampling? */
roentgen b75cab
#endif
roentgen b75cab
		}
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Must recalculate cached tile size in case sampling state changed.
roentgen b75cab
	 * Should we really be doing this now if image size isn't set? 
roentgen b75cab
	 */
roentgen b75cab
        if( tif->tif_tilesize > 0 )
roentgen b75cab
            tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);   
roentgen b75cab
        if( tif->tif_scanlinesize > 0 )
roentgen b75cab
            tif->tif_scanlinesize = TIFFScanlineSize(tif); 
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
JPEGVSetField(TIFF* tif, uint32 tag, va_list ap)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
	const TIFFField* fip;
roentgen b75cab
	uint32 v32;
roentgen b75cab
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
roentgen b75cab
	switch (tag) {
roentgen b75cab
	case TIFFTAG_JPEGTABLES:
roentgen b75cab
		v32 = (uint32) va_arg(ap, uint32);
roentgen b75cab
		if (v32 == 0) {
roentgen b75cab
			/* XXX */
roentgen b75cab
			return (0);
roentgen b75cab
		}
roentgen b75cab
		_TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*),
roentgen b75cab
		    (long) v32);
roentgen b75cab
		sp->jpegtables_length = v32;
roentgen b75cab
		TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
roentgen b75cab
		break;
roentgen b75cab
	case TIFFTAG_JPEGQUALITY:
roentgen b75cab
		sp->jpegquality = (int) va_arg(ap, int);
roentgen b75cab
		return (1);			/* pseudo tag */
roentgen b75cab
	case TIFFTAG_JPEGCOLORMODE:
roentgen b75cab
		sp->jpegcolormode = (int) va_arg(ap, int);
roentgen b75cab
		JPEGResetUpsampled( tif );
roentgen b75cab
		return (1);			/* pseudo tag */
roentgen b75cab
	case TIFFTAG_PHOTOMETRIC:
roentgen b75cab
	{
roentgen b75cab
		int ret_value = (*sp->vsetparent)(tif, tag, ap);
roentgen b75cab
		JPEGResetUpsampled( tif );
roentgen b75cab
		return ret_value;
roentgen b75cab
	}
roentgen b75cab
	case TIFFTAG_JPEGTABLESMODE:
roentgen b75cab
		sp->jpegtablesmode = (int) va_arg(ap, int);
roentgen b75cab
		return (1);			/* pseudo tag */
roentgen b75cab
	case TIFFTAG_YCBCRSUBSAMPLING:
roentgen b75cab
		/* mark the fact that we have a real ycbcrsubsampling! */
roentgen b75cab
		sp->ycbcrsampling_fetched = 1;
roentgen b75cab
		/* should we be recomputing upsampling info here? */
roentgen b75cab
		return (*sp->vsetparent)(tif, tag, ap);
roentgen b75cab
	default:
roentgen b75cab
		return (*sp->vsetparent)(tif, tag, ap);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	if ((fip = TIFFFieldWithTag(tif, tag))) {
roentgen b75cab
		TIFFSetFieldBit(tif, fip->field_bit);
roentgen b75cab
	} else {
roentgen b75cab
		return (0);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	tif->tif_flags |= TIFF_DIRTYDIRECT;
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
JPEGVGetField(TIFF* tif, uint32 tag, va_list ap)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
roentgen b75cab
	switch (tag) {
roentgen b75cab
		case TIFFTAG_JPEGTABLES:
roentgen b75cab
			*va_arg(ap, uint32*) = sp->jpegtables_length;
roentgen b75cab
			*va_arg(ap, void**) = sp->jpegtables;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_JPEGQUALITY:
roentgen b75cab
			*va_arg(ap, int*) = sp->jpegquality;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_JPEGCOLORMODE:
roentgen b75cab
			*va_arg(ap, int*) = sp->jpegcolormode;
roentgen b75cab
			break;
roentgen b75cab
		case TIFFTAG_JPEGTABLESMODE:
roentgen b75cab
			*va_arg(ap, int*) = sp->jpegtablesmode;
roentgen b75cab
			break;
roentgen b75cab
		default:
roentgen b75cab
			return (*sp->vgetparent)(tif, tag, ap);
roentgen b75cab
	}
roentgen b75cab
	return (1);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
JPEGPrintDir(TIFF* tif, FILE* fd, long flags)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
roentgen b75cab
	assert(sp != NULL);
roentgen b75cab
	(void) flags;
roentgen b75cab
roentgen b75cab
        if( sp != NULL ) {
roentgen b75cab
		if (TIFFFieldSet(tif,FIELD_JPEGTABLES))
roentgen b75cab
			fprintf(fd, "  JPEG Tables: (%lu bytes)\n",
roentgen b75cab
				(unsigned long) sp->jpegtables_length);
roentgen b75cab
		if (sp->printdir)
roentgen b75cab
			(*sp->printdir)(tif, fd, flags);
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static uint32
roentgen b75cab
JPEGDefaultStripSize(TIFF* tif, uint32 s)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
	TIFFDirectory *td = &tif->tif_dir;
roentgen b75cab
roentgen b75cab
	s = (*sp->defsparent)(tif, s);
roentgen b75cab
	if (s < td->td_imagelength)
roentgen b75cab
		s = TIFFroundup_32(s, td->td_ycbcrsubsampling[1] * DCTSIZE);
roentgen b75cab
	return (s);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
JPEGDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp = JState(tif);
roentgen b75cab
	TIFFDirectory *td = &tif->tif_dir;
roentgen b75cab
roentgen b75cab
	(*sp->deftparent)(tif, tw, th);
roentgen b75cab
	*tw = TIFFroundup_32(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE);
roentgen b75cab
	*th = TIFFroundup_32(*th, td->td_ycbcrsubsampling[1] * DCTSIZE);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * The JPEG library initialized used to be done in TIFFInitJPEG(), but
roentgen b75cab
 * now that we allow a TIFF file to be opened in update mode it is necessary
roentgen b75cab
 * to have some way of deciding whether compression or decompression is
roentgen b75cab
 * desired other than looking at tif->tif_mode.  We accomplish this by 
roentgen b75cab
 * examining {TILE/STRIP}BYTECOUNTS to see if there is a non-zero entry.
roentgen b75cab
 * If so, we assume decompression is desired. 
roentgen b75cab
 *
roentgen b75cab
 * This is tricky, because TIFFInitJPEG() is called while the directory is
roentgen b75cab
 * being read, and generally speaking the BYTECOUNTS tag won't have been read
roentgen b75cab
 * at that point.  So we try to defer jpeg library initialization till we
roentgen b75cab
 * do have that tag ... basically any access that might require the compressor
roentgen b75cab
 * or decompressor that occurs after the reading of the directory. 
roentgen b75cab
 *
roentgen b75cab
 * In an ideal world compressors or decompressors would be setup
roentgen b75cab
 * at the point where a single tile or strip was accessed (for read or write)
roentgen b75cab
 * so that stuff like update of missing tiles, or replacement of tiles could
roentgen b75cab
 * be done. However, we aren't trying to crack that nut just yet ...
roentgen b75cab
 *
roentgen b75cab
 * NFW, Feb 3rd, 2003.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static int JPEGInitializeLibJPEG( TIFF * tif, int decompress )
roentgen b75cab
{
roentgen b75cab
    JPEGState* sp = JState(tif);
roentgen b75cab
roentgen b75cab
    if(sp->cinfo_initialized)
roentgen b75cab
    {
roentgen b75cab
        if( !decompress && sp->cinfo.comm.is_decompressor )
roentgen b75cab
            TIFFjpeg_destroy( sp );
roentgen b75cab
        else if( decompress && !sp->cinfo.comm.is_decompressor )
roentgen b75cab
            TIFFjpeg_destroy( sp );
roentgen b75cab
        else
roentgen b75cab
            return 1;
roentgen b75cab
roentgen b75cab
        sp->cinfo_initialized = 0;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
    /*
roentgen b75cab
     * Initialize libjpeg.
roentgen b75cab
     */
roentgen b75cab
    if ( decompress ) {
roentgen b75cab
        if (!TIFFjpeg_create_decompress(sp))
roentgen b75cab
            return (0);
roentgen b75cab
    } else {
roentgen b75cab
        if (!TIFFjpeg_create_compress(sp))
roentgen b75cab
            return (0);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
    sp->cinfo_initialized = TRUE;
roentgen b75cab
roentgen b75cab
    return 1;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
int
roentgen b75cab
TIFFInitJPEG(TIFF* tif, int scheme)
roentgen b75cab
{
roentgen b75cab
	JPEGState* sp;
roentgen b75cab
roentgen b75cab
	assert(scheme == COMPRESSION_JPEG);
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Merge codec-specific tag information.
roentgen b75cab
	 */
roentgen b75cab
	if (!_TIFFMergeFields(tif, jpegFields, TIFFArrayCount(jpegFields))) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata,
roentgen b75cab
			     "TIFFInitJPEG",
roentgen b75cab
			     "Merging JPEG codec-specific tags failed");
roentgen b75cab
		return 0;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Allocate state block so tag methods have storage to record values.
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_data = (uint8*) _TIFFmalloc(sizeof (JPEGState));
roentgen b75cab
roentgen b75cab
	if (tif->tif_data == NULL) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata,
roentgen b75cab
			     "TIFFInitJPEG", "No space for JPEG state block");
roentgen b75cab
		return 0;
roentgen b75cab
	}
roentgen b75cab
        _TIFFmemset(tif->tif_data, 0, sizeof(JPEGState));
roentgen b75cab
roentgen b75cab
	sp = JState(tif);
roentgen b75cab
	sp->tif = tif;				/* back link */
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Override parent get/set field methods.
roentgen b75cab
	 */
roentgen b75cab
	sp->vgetparent = tif->tif_tagmethods.vgetfield;
roentgen b75cab
	tif->tif_tagmethods.vgetfield = JPEGVGetField; /* hook for codec tags */
roentgen b75cab
	sp->vsetparent = tif->tif_tagmethods.vsetfield;
roentgen b75cab
	tif->tif_tagmethods.vsetfield = JPEGVSetField; /* hook for codec tags */
roentgen b75cab
	sp->printdir = tif->tif_tagmethods.printdir;
roentgen b75cab
	tif->tif_tagmethods.printdir = JPEGPrintDir;   /* hook for codec tags */
roentgen b75cab
roentgen b75cab
	/* Default values for codec-specific fields */
roentgen b75cab
	sp->jpegtables = NULL;
roentgen b75cab
	sp->jpegtables_length = 0;
roentgen b75cab
	sp->jpegquality = 75;			/* Default IJG quality */
roentgen b75cab
	sp->jpegcolormode = JPEGCOLORMODE_RAW;
roentgen b75cab
	sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF;
roentgen b75cab
        sp->ycbcrsampling_fetched = 0;
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Install codec methods.
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_fixuptags = JPEGFixupTags;
roentgen b75cab
	tif->tif_setupdecode = JPEGSetupDecode;
roentgen b75cab
	tif->tif_predecode = JPEGPreDecode;
roentgen b75cab
	tif->tif_decoderow = JPEGDecode;
roentgen b75cab
	tif->tif_decodestrip = JPEGDecode;
roentgen b75cab
	tif->tif_decodetile = JPEGDecode;
roentgen b75cab
	tif->tif_setupencode = JPEGSetupEncode;
roentgen b75cab
	tif->tif_preencode = JPEGPreEncode;
roentgen b75cab
	tif->tif_postencode = JPEGPostEncode;
roentgen b75cab
	tif->tif_encoderow = JPEGEncode;
roentgen b75cab
	tif->tif_encodestrip = JPEGEncode;
roentgen b75cab
	tif->tif_encodetile = JPEGEncode;  
roentgen b75cab
	tif->tif_cleanup = JPEGCleanup;
roentgen b75cab
	sp->defsparent = tif->tif_defstripsize;
roentgen b75cab
	tif->tif_defstripsize = JPEGDefaultStripSize;
roentgen b75cab
	sp->deftparent = tif->tif_deftilesize;
roentgen b75cab
	tif->tif_deftilesize = JPEGDefaultTileSize;
roentgen b75cab
	tif->tif_flags |= TIFF_NOBITREV;	/* no bit reversal, please */
roentgen b75cab
roentgen b75cab
        sp->cinfo_initialized = FALSE;
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
        ** Create a JPEGTables field if no directory has yet been created. 
roentgen b75cab
        ** We do this just to ensure that sufficient space is reserved for
roentgen b75cab
        ** the JPEGTables field.  It will be properly created the right
roentgen b75cab
        ** size later. 
roentgen b75cab
        */
roentgen b75cab
        if( tif->tif_diroff == 0 )
roentgen b75cab
        {
roentgen b75cab
#define SIZE_OF_JPEGTABLES 2000
roentgen b75cab
/*
roentgen b75cab
The following line assumes incorrectly that all JPEG-in-TIFF files will have
roentgen b75cab
a JPEGTABLES tag generated and causes null-filled JPEGTABLES tags to be written
roentgen b75cab
when the JPEG data is placed with TIFFWriteRawStrip.  The field bit should be 
roentgen b75cab
set, anyway, later when actual JPEGTABLES header is generated, so removing it 
roentgen b75cab
here hopefully is harmless.
roentgen b75cab
            TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
roentgen b75cab
*/
roentgen b75cab
            sp->jpegtables_length = SIZE_OF_JPEGTABLES;
roentgen b75cab
            sp->jpegtables = (void *) _TIFFmalloc(sp->jpegtables_length);
roentgen b75cab
	    // FIXME: NULL-deref after malloc failure
roentgen b75cab
	    _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES);
roentgen b75cab
#undef SIZE_OF_JPEGTABLES
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
	return 1;
roentgen b75cab
}
roentgen b75cab
#endif /* JPEG_SUPPORT */
roentgen b75cab
roentgen b75cab
/* vim: set ts=8 sts=8 sw=8 noet: */
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Local Variables:
roentgen b75cab
 * mode: c
roentgen b75cab
 * c-basic-offset: 8
roentgen b75cab
 * fill-column: 78
roentgen b75cab
 * End:
roentgen b75cab
 */