diff options
Diffstat (limited to 'src/3rdparty/libtiff/libtiff/tif_jpeg.c')
-rw-r--r-- | src/3rdparty/libtiff/libtiff/tif_jpeg.c | 4124 |
1 files changed, 2244 insertions, 1880 deletions
diff --git a/src/3rdparty/libtiff/libtiff/tif_jpeg.c b/src/3rdparty/libtiff/libtiff/tif_jpeg.c index dc57b85..250144f 100644 --- a/src/3rdparty/libtiff/libtiff/tif_jpeg.c +++ b/src/3rdparty/libtiff/libtiff/tif_jpeg.c @@ -47,23 +47,24 @@ /* Settings that are independent of libjpeg ABI. Used when reinitializing the */ /* JPEGState from libjpegs 8 bit to libjpeg 12 bits, which have potentially */ /* different ABI */ -typedef struct { - TIFFVGetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ - TIFFPrintMethod printdir; /* super-class method */ - TIFFStripMethod defsparent; /* super-class method */ - TIFFTileMethod deftparent; /* super-class method */ - - /* pseudo-tag fields */ - void *jpegtables; /* JPEGTables tag value, or NULL */ - uint32_t jpegtables_length; /* number of bytes in same */ - int jpegquality; /* Compression quality level */ - int jpegcolormode; /* Auto RGB<=>YCbCr convert? */ - int jpegtablesmode; /* What to put in JPEGTables */ - - int ycbcrsampling_fetched; - int max_allowed_scan_number; - int has_warned_about_progressive_mode; +typedef struct +{ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ + TIFFStripMethod defsparent; /* super-class method */ + TIFFTileMethod deftparent; /* super-class method */ + + /* pseudo-tag fields */ + void *jpegtables; /* JPEGTables tag value, or NULL */ + uint32_t jpegtables_length; /* number of bytes in same */ + int jpegquality; /* Compression quality level */ + int jpegcolormode; /* Auto RGB<=>YCbCr convert? */ + int jpegtablesmode; /* What to put in JPEGTables */ + + int ycbcrsampling_fetched; + int max_allowed_scan_number; + int has_warned_about_progressive_mode; } JPEGOtherSettings; int TIFFFillStrip(TIFF *tif, uint32_t strip); @@ -112,11 +113,50 @@ typedef unsigned char boolean; #include "jerror.h" #include "jpeglib.h" +/* Do optional compile-time version check */ +#if defined(EXPECTED_JPEG_LIB_VERSION) && !defined(LIBJPEG_12_PATH) +#if EXPECTED_JPEG_LIB_VERSION != JPEG_LIB_VERSION +#error EXPECTED_JPEG_LIB_VERSION != JPEG_LIB_VERSION +#endif +#endif + /* * Do we want to do special processing suitable for when JSAMPLE is a * 16bit value? */ +/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 2.2 which + * adds a dual-mode 8/12 bit API in the same library. + */ + +#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) +#define JPEG_DUAL_MODE_8_12 +/* Start by undefining BITS_IN_JSAMPLE which is always set to 8 in libjpeg-turbo + * >= 2.2 Cf + * https://github.com/libjpeg-turbo/libjpeg-turbo/commit/8b9bc4b9635a2a047fb23ebe70c9acd728d3f99b + */ +#undef BITS_IN_JSAMPLE +/* libjpeg-turbo >= 2.2 adds J12xxxx datatypes for the 12-bit mode. */ +#if defined(FROM_TIF_JPEG_12) +#define BITS_IN_JSAMPLE 12 +#define TIFF_JSAMPLE J12SAMPLE +#define TIFF_JSAMPARRAY J12SAMPARRAY +#define TIFF_JSAMPIMAGE J12SAMPIMAGE +#define TIFF_JSAMPROW J12SAMPROW +#else +#define BITS_IN_JSAMPLE 8 +#define TIFF_JSAMPLE JSAMPLE +#define TIFF_JSAMPARRAY JSAMPARRAY +#define TIFF_JSAMPIMAGE JSAMPIMAGE +#define TIFF_JSAMPROW JSAMPROW +#endif +#else +#define TIFF_JSAMPLE JSAMPLE +#define TIFF_JSAMPARRAY JSAMPARRAY +#define TIFF_JSAMPIMAGE JSAMPIMAGE +#define TIFF_JSAMPROW JSAMPROW +#endif + #if defined(JPEG_LIB_MK1) #define JPEG_LIB_MK1_OR_12BIT 1 #elif BITS_IN_JSAMPLE == 12 @@ -159,36 +199,38 @@ typedef struct jpeg_error_mgr jpeg_error_mgr; * so we can safely cast JPEGState* -> jpeg_xxx_struct* * and vice versa! */ -typedef struct { - union { - struct jpeg_compress_struct c; - struct jpeg_decompress_struct d; - struct jpeg_common_struct comm; - } cinfo; /* NB: must be first */ - int cinfo_initialized; - - jpeg_error_mgr err; /* libjpeg error manager */ - JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */ - - struct jpeg_progress_mgr progress; - /* - * The following two members could be a union, but - * they're small enough that it's not worth the effort. - */ - jpeg_destination_mgr dest; /* data dest for compression */ - jpeg_source_mgr src; /* data source for decompression */ - /* private state */ - TIFF *tif; /* back link needed by some code */ - uint16_t photometric; /* copy of PhotometricInterpretation */ - uint16_t h_sampling; /* luminance sampling factors */ - uint16_t v_sampling; - tmsize_t bytesperline; /* decompressed bytes per scanline */ - /* pointers to intermediate buffers when processing downsampled data */ - JSAMPARRAY ds_buffer[MAX_COMPONENTS]; - int scancount; /* number of "scanlines" accumulated */ - int samplesperclump; - - JPEGOtherSettings otherSettings; +typedef struct +{ + union + { + struct jpeg_compress_struct c; + struct jpeg_decompress_struct d; + struct jpeg_common_struct comm; + } cinfo; /* NB: must be first */ + int cinfo_initialized; + + jpeg_error_mgr err; /* libjpeg error manager */ + JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */ + + struct jpeg_progress_mgr progress; + /* + * The following two members could be a union, but + * they're small enough that it's not worth the effort. + */ + jpeg_destination_mgr dest; /* data dest for compression */ + jpeg_source_mgr src; /* data source for decompression */ + /* private state */ + TIFF *tif; /* back link needed by some code */ + uint16_t photometric; /* copy of PhotometricInterpretation */ + uint16_t h_sampling; /* luminance sampling factors */ + uint16_t v_sampling; + tmsize_t bytesperline; /* decompressed bytes per scanline */ + /* pointers to intermediate buffers when processing downsampled data */ + TIFF_JSAMPARRAY ds_buffer[MAX_COMPONENTS]; + int scancount; /* number of "scanlines" accumulated */ + int samplesperclump; + + JPEGOtherSettings otherSettings; } JPEGState; #define JState(tif) ((JPEGState *)(tif)->tif_data) @@ -226,15 +268,16 @@ static const TIFFField jpegFields[] = { * IJG routines from jerror.c). These are used for both * compression and decompression. */ -static void TIFFjpeg_error_exit(j_common_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; /* NB: cinfo assumed first */ - char buffer[JMSG_LENGTH_MAX]; +static void TIFFjpeg_error_exit(j_common_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; /* NB: cinfo assumed first */ + char buffer[JMSG_LENGTH_MAX]; - (*cinfo->err->format_message)(cinfo, buffer); - TIFFErrorExt(sp->tif->tif_clientdata, "JPEGLib", "%s", - buffer); /* display the error message */ - jpeg_abort(cinfo); /* clean up libjpeg state */ - LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ + (*cinfo->err->format_message)(cinfo, buffer); + TIFFErrorExtR(sp->tif, "JPEGLib", "%s", + buffer); /* display the error message */ + jpeg_abort(cinfo); /* clean up libjpeg state */ + LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ } /* @@ -242,12 +285,12 @@ static void TIFFjpeg_error_exit(j_common_ptr cinfo) { * since error_exit does its own thing and trace_level * is never set > 0. */ -static void TIFFjpeg_output_message(j_common_ptr cinfo) { - char buffer[JMSG_LENGTH_MAX]; +static void TIFFjpeg_output_message(j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; - (*cinfo->err->format_message)(cinfo, buffer); - TIFFWarningExt(((JPEGState *)cinfo)->tif->tif_clientdata, "JPEGLib", "%s", - buffer); + (*cinfo->err->format_message)(cinfo, buffer); + TIFFWarningExtR(((JPEGState *)cinfo)->tif, "JPEGLib", "%s", buffer); } /* Avoid the risk of denial-of-service on crafted JPEGs with an insane */ @@ -255,23 +298,26 @@ static void TIFFjpeg_output_message(j_common_ptr cinfo) { /* See * http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf */ -static void TIFFjpeg_progress_monitor(j_common_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; /* NB: cinfo assumed first */ - if (cinfo->is_decompressor) { - const int scan_no = ((j_decompress_ptr)cinfo)->input_scan_number; - if (scan_no >= sp->otherSettings.max_allowed_scan_number) { - TIFFErrorExt( - ((JPEGState *)cinfo)->tif->tif_clientdata, - "TIFFjpeg_progress_monitor", - "Scan number %d exceeds maximum scans (%d). This limit " - "can be raised through the LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER " - "environment variable.", - scan_no, sp->otherSettings.max_allowed_scan_number); - - jpeg_abort(cinfo); /* clean up libjpeg state */ - LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ +static void TIFFjpeg_progress_monitor(j_common_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; /* NB: cinfo assumed first */ + if (cinfo->is_decompressor) + { + const int scan_no = ((j_decompress_ptr)cinfo)->input_scan_number; + if (scan_no >= sp->otherSettings.max_allowed_scan_number) + { + TIFFErrorExtR( + ((JPEGState *)cinfo)->tif, "TIFFjpeg_progress_monitor", + "Scan number %d exceeds maximum scans (%d). This limit " + "can be raised through the " + "LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER " + "environment variable.", + scan_no, sp->otherSettings.max_allowed_scan_number); + + jpeg_abort(cinfo); /* clean up libjpeg state */ + LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ + } } - } } /* @@ -283,127 +329,172 @@ static void TIFFjpeg_progress_monitor(j_common_ptr cinfo) { #define CALLJPEG(sp, fail, op) (SETJMP((sp)->exit_jmpbuf) ? (fail) : (op)) #define CALLVJPEG(sp, op) CALLJPEG(sp, 0, ((op), 1)) -static int TIFFjpeg_create_compress(JPEGState *sp) { - /* initialize JPEG error handling */ - sp->cinfo.c.err = jpeg_std_error(&sp->err); - sp->err.error_exit = TIFFjpeg_error_exit; - sp->err.output_message = TIFFjpeg_output_message; +static int TIFFjpeg_create_compress(JPEGState *sp) +{ + /* initialize JPEG error handling */ + sp->cinfo.c.err = jpeg_std_error(&sp->err); + sp->err.error_exit = TIFFjpeg_error_exit; + sp->err.output_message = TIFFjpeg_output_message; - /* set client_data to avoid UMR warning from tools like Purify */ - sp->cinfo.c.client_data = NULL; + /* set client_data to avoid UMR warning from tools like Purify */ + sp->cinfo.c.client_data = NULL; - return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c)); + return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c)); } -static int TIFFjpeg_create_decompress(JPEGState *sp) { - /* initialize JPEG error handling */ - sp->cinfo.d.err = jpeg_std_error(&sp->err); - sp->err.error_exit = TIFFjpeg_error_exit; - sp->err.output_message = TIFFjpeg_output_message; +static int TIFFjpeg_create_decompress(JPEGState *sp) +{ + /* initialize JPEG error handling */ + sp->cinfo.d.err = jpeg_std_error(&sp->err); + sp->err.error_exit = TIFFjpeg_error_exit; + sp->err.output_message = TIFFjpeg_output_message; - /* set client_data to avoid UMR warning from tools like Purify */ - sp->cinfo.d.client_data = NULL; + /* set client_data to avoid UMR warning from tools like Purify */ + sp->cinfo.d.client_data = NULL; - return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d)); + return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d)); } -static int TIFFjpeg_set_defaults(JPEGState *sp) { - return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c)); +static int TIFFjpeg_set_defaults(JPEGState *sp) +{ + return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c)); } -static int TIFFjpeg_set_colorspace(JPEGState *sp, J_COLOR_SPACE colorspace) { - return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace)); +static int TIFFjpeg_set_colorspace(JPEGState *sp, J_COLOR_SPACE colorspace) +{ + return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace)); } static int TIFFjpeg_set_quality(JPEGState *sp, int quality, - boolean force_baseline) { - return CALLVJPEG(sp, jpeg_set_quality(&sp->cinfo.c, quality, force_baseline)); + boolean force_baseline) +{ + return CALLVJPEG(sp, + jpeg_set_quality(&sp->cinfo.c, quality, force_baseline)); } -static int TIFFjpeg_suppress_tables(JPEGState *sp, boolean suppress) { - return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress)); +static int TIFFjpeg_suppress_tables(JPEGState *sp, boolean suppress) +{ + return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress)); } -static int TIFFjpeg_start_compress(JPEGState *sp, boolean write_all_tables) { - return CALLVJPEG(sp, jpeg_start_compress(&sp->cinfo.c, write_all_tables)); +static int TIFFjpeg_start_compress(JPEGState *sp, boolean write_all_tables) +{ + return CALLVJPEG(sp, jpeg_start_compress(&sp->cinfo.c, write_all_tables)); } -static int TIFFjpeg_write_scanlines(JPEGState *sp, JSAMPARRAY scanlines, - int num_lines) { - return CALLJPEG(sp, -1, - (int)jpeg_write_scanlines(&sp->cinfo.c, scanlines, - (JDIMENSION)num_lines)); +static int TIFFjpeg_write_scanlines(JPEGState *sp, TIFF_JSAMPARRAY scanlines, + int num_lines) +{ +#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && BITS_IN_JSAMPLE == 12 + return CALLJPEG(sp, -1, + (int)jpeg12_write_scanlines(&sp->cinfo.c, scanlines, + (JDIMENSION)num_lines)); +#else + return CALLJPEG(sp, -1, + (int)jpeg_write_scanlines(&sp->cinfo.c, scanlines, + (JDIMENSION)num_lines)); +#endif } -static int TIFFjpeg_write_raw_data(JPEGState *sp, JSAMPIMAGE data, - int num_lines) { - return CALLJPEG( - sp, -1, - (int)jpeg_write_raw_data(&sp->cinfo.c, data, (JDIMENSION)num_lines)); +static int TIFFjpeg_write_raw_data(JPEGState *sp, TIFF_JSAMPIMAGE data, + int num_lines) +{ +#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && BITS_IN_JSAMPLE == 12 + return CALLJPEG( + sp, -1, + (int)jpeg12_write_raw_data(&sp->cinfo.c, data, (JDIMENSION)num_lines)); +#else + return CALLJPEG( + sp, -1, + (int)jpeg_write_raw_data(&sp->cinfo.c, data, (JDIMENSION)num_lines)); +#endif } -static int TIFFjpeg_finish_compress(JPEGState *sp) { - return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c)); +static int TIFFjpeg_finish_compress(JPEGState *sp) +{ + return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c)); } -static int TIFFjpeg_write_tables(JPEGState *sp) { - return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c)); +static int TIFFjpeg_write_tables(JPEGState *sp) +{ + return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c)); } -static int TIFFjpeg_read_header(JPEGState *sp, boolean require_image) { - return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image)); +static int TIFFjpeg_read_header(JPEGState *sp, boolean require_image) +{ + return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image)); } -static int TIFFjpeg_has_multiple_scans(JPEGState *sp) { - return CALLJPEG(sp, 0, jpeg_has_multiple_scans(&sp->cinfo.d)); +static int TIFFjpeg_has_multiple_scans(JPEGState *sp) +{ + return CALLJPEG(sp, 0, jpeg_has_multiple_scans(&sp->cinfo.d)); } -static int TIFFjpeg_start_decompress(JPEGState *sp) { - const char *sz_max_allowed_scan_number; - /* progress monitor */ - sp->cinfo.d.progress = &sp->progress; - sp->progress.progress_monitor = TIFFjpeg_progress_monitor; - sp->otherSettings.max_allowed_scan_number = 100; - sz_max_allowed_scan_number = getenv("LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER"); - if (sz_max_allowed_scan_number) - sp->otherSettings.max_allowed_scan_number = - atoi(sz_max_allowed_scan_number); +static int TIFFjpeg_start_decompress(JPEGState *sp) +{ + const char *sz_max_allowed_scan_number; + /* progress monitor */ + sp->cinfo.d.progress = &sp->progress; + sp->progress.progress_monitor = TIFFjpeg_progress_monitor; + sp->otherSettings.max_allowed_scan_number = 100; + sz_max_allowed_scan_number = getenv("LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER"); + if (sz_max_allowed_scan_number) + sp->otherSettings.max_allowed_scan_number = + atoi(sz_max_allowed_scan_number); - return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d)); + return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d)); } -static int TIFFjpeg_read_scanlines(JPEGState *sp, JSAMPARRAY scanlines, - int max_lines) { - return CALLJPEG( - sp, -1, - (int)jpeg_read_scanlines(&sp->cinfo.d, scanlines, (JDIMENSION)max_lines)); +static int TIFFjpeg_read_scanlines(JPEGState *sp, TIFF_JSAMPARRAY scanlines, + int max_lines) +{ +#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && BITS_IN_JSAMPLE == 12 + return CALLJPEG(sp, -1, + (int)jpeg12_read_scanlines(&sp->cinfo.d, scanlines, + (JDIMENSION)max_lines)); +#else + return CALLJPEG(sp, -1, + (int)jpeg_read_scanlines(&sp->cinfo.d, scanlines, + (JDIMENSION)max_lines)); +#endif } -static int TIFFjpeg_read_raw_data(JPEGState *sp, JSAMPIMAGE data, - int max_lines) { - return CALLJPEG( - sp, -1, - (int)jpeg_read_raw_data(&sp->cinfo.d, data, (JDIMENSION)max_lines)); +static int TIFFjpeg_read_raw_data(JPEGState *sp, TIFF_JSAMPIMAGE data, + int max_lines) +{ +#if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) && BITS_IN_JSAMPLE == 12 + return CALLJPEG( + sp, -1, + (int)jpeg12_read_raw_data(&sp->cinfo.d, data, (JDIMENSION)max_lines)); +#else + return CALLJPEG( + sp, -1, + (int)jpeg_read_raw_data(&sp->cinfo.d, data, (JDIMENSION)max_lines)); +#endif } -static int TIFFjpeg_finish_decompress(JPEGState *sp) { - return CALLJPEG(sp, -1, (int)jpeg_finish_decompress(&sp->cinfo.d)); +static int TIFFjpeg_finish_decompress(JPEGState *sp) +{ + return CALLJPEG(sp, -1, (int)jpeg_finish_decompress(&sp->cinfo.d)); } -static int TIFFjpeg_abort(JPEGState *sp) { - return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm)); +static int TIFFjpeg_abort(JPEGState *sp) +{ + return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm)); } -static int TIFFjpeg_destroy(JPEGState *sp) { - return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm)); +static int TIFFjpeg_destroy(JPEGState *sp) +{ + return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm)); } static JSAMPARRAY TIFFjpeg_alloc_sarray(JPEGState *sp, int pool_id, JDIMENSION samplesperrow, - JDIMENSION numrows) { - return CALLJPEG(sp, (JSAMPARRAY)NULL, - (*sp->cinfo.comm.mem->alloc_sarray)(&sp->cinfo.comm, pool_id, - samplesperrow, numrows)); + JDIMENSION numrows) +{ + return CALLJPEG(sp, (JSAMPARRAY)NULL, + (*sp->cinfo.comm.mem->alloc_sarray)( + &sp->cinfo.comm, pool_id, samplesperrow, numrows)); } /* @@ -412,116 +503,128 @@ static JSAMPARRAY TIFFjpeg_alloc_sarray(JPEGState *sp, int pool_id, * libtiff output buffer. */ -static void std_init_destination(j_compress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; - TIFF *tif = sp->tif; +static void std_init_destination(j_compress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; + TIFF *tif = sp->tif; - sp->dest.next_output_byte = (JOCTET *)tif->tif_rawdata; - sp->dest.free_in_buffer = (size_t)tif->tif_rawdatasize; + sp->dest.next_output_byte = (JOCTET *)tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t)tif->tif_rawdatasize; } -static boolean std_empty_output_buffer(j_compress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; - TIFF *tif = sp->tif; +static boolean std_empty_output_buffer(j_compress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; + TIFF *tif = sp->tif; - /* the entire buffer has been filled */ - tif->tif_rawcc = tif->tif_rawdatasize; + /* the entire buffer has been filled */ + tif->tif_rawcc = tif->tif_rawdatasize; #ifdef IPPJ_HUFF - /* - * The Intel IPP performance library does not necessarily fill up - * the whole output buffer on each pass, so only dump out the parts - * that have been filled. - * http://trac.osgeo.org/gdal/wiki/JpegIPP - */ - if (sp->dest.free_in_buffer >= 0) { - tif->tif_rawcc = tif->tif_rawdatasize - sp->dest.free_in_buffer; - } + /* + * The Intel IPP performance library does not necessarily fill up + * the whole output buffer on each pass, so only dump out the parts + * that have been filled. + * http://trac.osgeo.org/gdal/wiki/JpegIPP + */ + if (sp->dest.free_in_buffer >= 0) + { + tif->tif_rawcc = tif->tif_rawdatasize - sp->dest.free_in_buffer; + } #endif - if (!TIFFFlushData1(tif)) - return FALSE; - sp->dest.next_output_byte = (JOCTET *)tif->tif_rawdata; - sp->dest.free_in_buffer = (size_t)tif->tif_rawdatasize; + if (!TIFFFlushData1(tif)) + return FALSE; + sp->dest.next_output_byte = (JOCTET *)tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t)tif->tif_rawdatasize; - return (TRUE); + return (TRUE); } -static void std_term_destination(j_compress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; - TIFF *tif = sp->tif; +static void std_term_destination(j_compress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; + TIFF *tif = sp->tif; - tif->tif_rawcp = (uint8_t *)sp->dest.next_output_byte; - tif->tif_rawcc = tif->tif_rawdatasize - (tmsize_t)sp->dest.free_in_buffer; - /* NB: libtiff does the final buffer flush */ + tif->tif_rawcp = (uint8_t *)sp->dest.next_output_byte; + tif->tif_rawcc = tif->tif_rawdatasize - (tmsize_t)sp->dest.free_in_buffer; + /* NB: libtiff does the final buffer flush */ } -static void TIFFjpeg_data_dest(JPEGState *sp, TIFF *tif) { - (void)tif; - sp->cinfo.c.dest = &sp->dest; - sp->dest.init_destination = std_init_destination; - sp->dest.empty_output_buffer = std_empty_output_buffer; - sp->dest.term_destination = std_term_destination; +static void TIFFjpeg_data_dest(JPEGState *sp, TIFF *tif) +{ + (void)tif; + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = std_init_destination; + sp->dest.empty_output_buffer = std_empty_output_buffer; + sp->dest.term_destination = std_term_destination; } /* * Alternate destination manager for outputting to JPEGTables field. */ -static void tables_init_destination(j_compress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; +static void tables_init_destination(j_compress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; - /* while building, otherSettings.jpegtables_length is allocated buffer size */ - sp->dest.next_output_byte = (JOCTET *)sp->otherSettings.jpegtables; - sp->dest.free_in_buffer = (size_t)sp->otherSettings.jpegtables_length; + /* while building, otherSettings.jpegtables_length is allocated buffer size + */ + sp->dest.next_output_byte = (JOCTET *)sp->otherSettings.jpegtables; + sp->dest.free_in_buffer = (size_t)sp->otherSettings.jpegtables_length; } -static boolean tables_empty_output_buffer(j_compress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; - void *newbuf; +static boolean tables_empty_output_buffer(j_compress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; + void *newbuf; - /* the entire buffer has been filled; enlarge it by 1000 bytes */ - newbuf = _TIFFrealloc((void *)sp->otherSettings.jpegtables, + /* the entire buffer has been filled; enlarge it by 1000 bytes */ + newbuf = + _TIFFreallocExt(sp->tif, (void *)sp->otherSettings.jpegtables, (tmsize_t)(sp->otherSettings.jpegtables_length + 1000)); - if (newbuf == NULL) - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100); - sp->dest.next_output_byte = - (JOCTET *)newbuf + sp->otherSettings.jpegtables_length; - sp->dest.free_in_buffer = (size_t)1000; - sp->otherSettings.jpegtables = newbuf; - sp->otherSettings.jpegtables_length += 1000; - return (TRUE); -} - -static void tables_term_destination(j_compress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; - - /* set tables length to number of bytes actually emitted */ - sp->otherSettings.jpegtables_length -= (uint32_t)sp->dest.free_in_buffer; -} - -static int TIFFjpeg_tables_dest(JPEGState *sp, TIFF *tif) { - (void)tif; - /* - * Allocate a working buffer for building tables. - * Initial size is 1000 bytes, which is usually adequate. - */ - if (sp->otherSettings.jpegtables) - _TIFFfree(sp->otherSettings.jpegtables); - sp->otherSettings.jpegtables_length = 1000; - sp->otherSettings.jpegtables = - (void *)_TIFFmalloc((tmsize_t)sp->otherSettings.jpegtables_length); - if (sp->otherSettings.jpegtables == NULL) { - sp->otherSettings.jpegtables_length = 0; - TIFFErrorExt(sp->tif->tif_clientdata, "TIFFjpeg_tables_dest", - "No space for JPEGTables"); - return (0); - } - sp->cinfo.c.dest = &sp->dest; - sp->dest.init_destination = tables_init_destination; - sp->dest.empty_output_buffer = tables_empty_output_buffer; - sp->dest.term_destination = tables_term_destination; - return (1); + if (newbuf == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100); + sp->dest.next_output_byte = + (JOCTET *)newbuf + sp->otherSettings.jpegtables_length; + sp->dest.free_in_buffer = (size_t)1000; + sp->otherSettings.jpegtables = newbuf; + sp->otherSettings.jpegtables_length += 1000; + return (TRUE); +} + +static void tables_term_destination(j_compress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; + + /* set tables length to number of bytes actually emitted */ + sp->otherSettings.jpegtables_length -= (uint32_t)sp->dest.free_in_buffer; +} + +static int TIFFjpeg_tables_dest(JPEGState *sp, TIFF *tif) +{ + (void)tif; + /* + * Allocate a working buffer for building tables. + * Initial size is 1000 bytes, which is usually adequate. + */ + if (sp->otherSettings.jpegtables) + _TIFFfreeExt(tif, sp->otherSettings.jpegtables); + sp->otherSettings.jpegtables_length = 1000; + sp->otherSettings.jpegtables = (void *)_TIFFmallocExt( + tif, (tmsize_t)sp->otherSettings.jpegtables_length); + if (sp->otherSettings.jpegtables == NULL) + { + sp->otherSettings.jpegtables_length = 0; + TIFFErrorExtR(sp->tif, "TIFFjpeg_tables_dest", + "No space for JPEGTables"); + return (0); + } + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = tables_init_destination; + sp->dest.empty_output_buffer = tables_empty_output_buffer; + sp->dest.term_destination = tables_term_destination; + return (1); } /* @@ -529,76 +632,86 @@ static int TIFFjpeg_tables_dest(JPEGState *sp, TIFF *tif) { * These routines supply compressed data to libjpeg. */ -static void std_init_source(j_decompress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; - TIFF *tif = sp->tif; +static void std_init_source(j_decompress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; + TIFF *tif = sp->tif; - sp->src.next_input_byte = (const JOCTET *)tif->tif_rawdata; - sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; + sp->src.next_input_byte = (const JOCTET *)tif->tif_rawdata; + sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; } -static boolean std_fill_input_buffer(j_decompress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; - static const JOCTET dummy_EOI[2] = {0xFF, JPEG_EOI}; +static boolean std_fill_input_buffer(j_decompress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; + static const JOCTET dummy_EOI[2] = {0xFF, JPEG_EOI}; #ifdef IPPJ_HUFF - /* - * The Intel IPP performance library does not necessarily read the whole - * input buffer in one pass, so it is possible to get here with data - * yet to read. - * - * We just return without doing anything, until the entire buffer has - * been read. - * http://trac.osgeo.org/gdal/wiki/JpegIPP - */ - if (sp->src.bytes_in_buffer > 0) { - return (TRUE); - } + /* + * The Intel IPP performance library does not necessarily read the whole + * input buffer in one pass, so it is possible to get here with data + * yet to read. + * + * We just return without doing anything, until the entire buffer has + * been read. + * http://trac.osgeo.org/gdal/wiki/JpegIPP + */ + if (sp->src.bytes_in_buffer > 0) + { + return (TRUE); + } #endif - /* - * Normally the whole strip/tile is read and so we don't need to do - * a fill. In the case of CHUNKY_STRIP_READ_SUPPORT we might not have - * all the data, but the rawdata is refreshed between scanlines and - * we push this into the io machinery in JPEGDecode(). - * http://trac.osgeo.org/gdal/ticket/3894 - */ + /* + * Normally the whole strip/tile is read and so we don't need to do + * a fill. In the case of CHUNKY_STRIP_READ_SUPPORT we might not have + * all the data, but the rawdata is refreshed between scanlines and + * we push this into the io machinery in JPEGDecode(). + * http://trac.osgeo.org/gdal/ticket/3894 + */ - WARNMS(cinfo, JWRN_JPEG_EOF); - /* insert a fake EOI marker */ - sp->src.next_input_byte = dummy_EOI; - sp->src.bytes_in_buffer = 2; - return (TRUE); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* insert a fake EOI marker */ + sp->src.next_input_byte = dummy_EOI; + sp->src.bytes_in_buffer = 2; + return (TRUE); } -static void std_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - JPEGState *sp = (JPEGState *)cinfo; +static void std_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + JPEGState *sp = (JPEGState *)cinfo; - if (num_bytes > 0) { - if ((size_t)num_bytes > sp->src.bytes_in_buffer) { - /* oops, buffer overrun */ - (void)std_fill_input_buffer(cinfo); - } else { - sp->src.next_input_byte += (size_t)num_bytes; - sp->src.bytes_in_buffer -= (size_t)num_bytes; + if (num_bytes > 0) + { + if ((size_t)num_bytes > sp->src.bytes_in_buffer) + { + /* oops, buffer overrun */ + (void)std_fill_input_buffer(cinfo); + } + else + { + sp->src.next_input_byte += (size_t)num_bytes; + sp->src.bytes_in_buffer -= (size_t)num_bytes; + } } - } } -static void std_term_source(j_decompress_ptr cinfo) { - /* No work necessary here */ - (void)cinfo; +static void std_term_source(j_decompress_ptr cinfo) +{ + /* No work necessary here */ + (void)cinfo; } -static void TIFFjpeg_data_src(JPEGState *sp) { - sp->cinfo.d.src = &sp->src; - sp->src.init_source = std_init_source; - sp->src.fill_input_buffer = std_fill_input_buffer; - sp->src.skip_input_data = std_skip_input_data; - sp->src.resync_to_restart = jpeg_resync_to_restart; - sp->src.term_source = std_term_source; - sp->src.bytes_in_buffer = 0; /* for safety */ - sp->src.next_input_byte = NULL; +static void TIFFjpeg_data_src(JPEGState *sp) +{ + sp->cinfo.d.src = &sp->src; + sp->src.init_source = std_init_source; + sp->src.fill_input_buffer = std_fill_input_buffer; + sp->src.skip_input_data = std_skip_input_data; + sp->src.resync_to_restart = jpeg_resync_to_restart; + sp->src.term_source = std_term_source; + sp->src.bytes_in_buffer = 0; /* for safety */ + sp->src.next_input_byte = NULL; } /* @@ -606,16 +719,18 @@ static void TIFFjpeg_data_src(JPEGState *sp) { * We can share all the code except for the init routine. */ -static void tables_init_source(j_decompress_ptr cinfo) { - JPEGState *sp = (JPEGState *)cinfo; +static void tables_init_source(j_decompress_ptr cinfo) +{ + JPEGState *sp = (JPEGState *)cinfo; - sp->src.next_input_byte = (const JOCTET *)sp->otherSettings.jpegtables; - sp->src.bytes_in_buffer = (size_t)sp->otherSettings.jpegtables_length; + sp->src.next_input_byte = (const JOCTET *)sp->otherSettings.jpegtables; + sp->src.bytes_in_buffer = (size_t)sp->otherSettings.jpegtables_length; } -static void TIFFjpeg_tables_src(JPEGState *sp) { - TIFFjpeg_data_src(sp); - sp->src.init_source = tables_init_source; +static void TIFFjpeg_tables_src(JPEGState *sp) +{ + TIFFjpeg_data_src(sp); + sp->src.init_source = tables_init_source; } /* @@ -626,24 +741,26 @@ static void TIFFjpeg_tables_src(JPEGState *sp) { * This is also a handy place to compute samplesperclump, bytesperline. */ static int alloc_downsampled_buffers(TIFF *tif, jpeg_component_info *comp_info, - int num_components) { - JPEGState *sp = JState(tif); - int ci; - jpeg_component_info *compptr; - JSAMPARRAY buf; - int samples_per_clump = 0; - - for (ci = 0, compptr = comp_info; ci < num_components; ci++, compptr++) { - samples_per_clump += compptr->h_samp_factor * compptr->v_samp_factor; - buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION)(compptr->v_samp_factor * DCTSIZE)); - if (buf == NULL) - return (0); - sp->ds_buffer[ci] = buf; - } - sp->samplesperclump = samples_per_clump; - return (1); + int num_components) +{ + JPEGState *sp = JState(tif); + int ci; + jpeg_component_info *compptr; + TIFF_JSAMPARRAY buf; + int samples_per_clump = 0; + + for (ci = 0, compptr = comp_info; ci < num_components; ci++, compptr++) + { + samples_per_clump += compptr->h_samp_factor * compptr->v_samp_factor; + buf = (TIFF_JSAMPARRAY)TIFFjpeg_alloc_sarray( + sp, JPOOL_IMAGE, compptr->width_in_blocks * DCTSIZE, + (JDIMENSION)(compptr->v_samp_factor * DCTSIZE)); + if (buf == NULL) + return (0); + sp->ds_buffer[ci] = buf; + } + sp->samplesperclump = samples_per_clump; + return (1); } /* @@ -664,15 +781,16 @@ static int alloc_downsampled_buffers(TIFF *tif, jpeg_component_info *comp_info, #define JPEG_MARKER_DRI 0xDD #define JPEG_MARKER_APP0 0xE0 #define JPEG_MARKER_COM 0xFE -struct JPEGFixupTagsSubsamplingData { - TIFF *tif; - void *buffer; - uint32_t buffersize; - uint8_t *buffercurrentbyte; - uint32_t bufferbytesleft; - uint64_t fileoffset; - uint64_t filebytesleft; - uint8_t filepositioned; +struct JPEGFixupTagsSubsamplingData +{ + TIFF *tif; + void *buffer; + uint32_t buffersize; + uint8_t *buffercurrentbyte; + uint32_t bufferbytesleft; + uint64_t fileoffset; + uint64_t filebytesleft; + uint8_t filepositioned; }; static void JPEGFixupTagsSubsampling(TIFF *tif); static int @@ -689,306 +807,343 @@ JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData *data, #endif -static int JPEGFixupTags(TIFF *tif) { +static int JPEGFixupTags(TIFF *tif) +{ #ifdef CHECK_JPEG_YCBCR_SUBSAMPLING - JPEGState *sp = JState(tif); - if ((tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR) && - (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG) && - (tif->tif_dir.td_samplesperpixel == 3) && - !sp->otherSettings.ycbcrsampling_fetched) - JPEGFixupTagsSubsampling(tif); + JPEGState *sp = JState(tif); + if ((tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR) && + (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG) && + (tif->tif_dir.td_samplesperpixel == 3) && + !sp->otherSettings.ycbcrsampling_fetched) + JPEGFixupTagsSubsampling(tif); #endif - return (1); + return (1); } #ifdef CHECK_JPEG_YCBCR_SUBSAMPLING -static void JPEGFixupTagsSubsampling(TIFF *tif) { - /* - * Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in - * the TIFF tags, but still use non-default (2,2) values within the jpeg - * data stream itself. In order for TIFF applications to work properly - * - for instance to get the strip buffer size right - it is imperative - * that the subsampling be available before we start reading the image - * data normally. This function will attempt to analyze the first strip in - * order to get the sampling values from the jpeg data stream. - * - * Note that JPEGPreDeocode() will produce a fairly loud warning when the - * discovered sampling does not match the default sampling (2,2) or whatever - * was actually in the tiff tags. - * - * See the bug in bugzilla for details: - * - * http://bugzilla.remotesensing.org/show_bug.cgi?id=168 - * - * Frank Warmerdam, July 2002 - * Joris Van Damme, May 2007 - */ - static const char module[] = "JPEGFixupTagsSubsampling"; - struct JPEGFixupTagsSubsamplingData m; - uint64_t fileoffset = TIFFGetStrileOffset(tif, 0); - - if (fileoffset == 0) { - /* Do not even try to check if the first strip/tile does not - yet exist, as occurs when GDAL has created a new NULL file - for instance. */ - return; - } - - m.tif = tif; - m.buffersize = 2048; - m.buffer = _TIFFmalloc(m.buffersize); - if (m.buffer == NULL) { - TIFFWarningExt(tif->tif_clientdata, module, - "Unable to allocate memory for auto-correcting of " - "subsampling values; auto-correcting skipped"); - return; - } - m.buffercurrentbyte = NULL; - m.bufferbytesleft = 0; - m.fileoffset = fileoffset; - m.filepositioned = 0; - m.filebytesleft = TIFFGetStrileByteCount(tif, 0); - if (!JPEGFixupTagsSubsamplingSec(&m)) - TIFFWarningExt( - tif->tif_clientdata, module, - "Unable to auto-correct subsampling values, likely corrupt JPEG " - "compressed data in first strip/tile; auto-correcting skipped"); - _TIFFfree(m.buffer); +static void JPEGFixupTagsSubsampling(TIFF *tif) +{ + /* + * Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in + * the TIFF tags, but still use non-default (2,2) values within the jpeg + * data stream itself. In order for TIFF applications to work properly + * - for instance to get the strip buffer size right - it is imperative + * that the subsampling be available before we start reading the image + * data normally. This function will attempt to analyze the first strip in + * order to get the sampling values from the jpeg data stream. + * + * Note that JPEGPreDeocode() will produce a fairly loud warning when the + * discovered sampling does not match the default sampling (2,2) or whatever + * was actually in the tiff tags. + * + * See the bug in bugzilla for details: + * + * http://bugzilla.remotesensing.org/show_bug.cgi?id=168 + * + * Frank Warmerdam, July 2002 + * Joris Van Damme, May 2007 + */ + static const char module[] = "JPEGFixupTagsSubsampling"; + struct JPEGFixupTagsSubsamplingData m; + uint64_t fileoffset = TIFFGetStrileOffset(tif, 0); + + if (fileoffset == 0) + { + /* Do not even try to check if the first strip/tile does not + yet exist, as occurs when GDAL has created a new NULL file + for instance. */ + return; + } + + m.tif = tif; + m.buffersize = 2048; + m.buffer = _TIFFmallocExt(tif, m.buffersize); + if (m.buffer == NULL) + { + TIFFWarningExtR(tif, module, + "Unable to allocate memory for auto-correcting of " + "subsampling values; auto-correcting skipped"); + return; + } + m.buffercurrentbyte = NULL; + m.bufferbytesleft = 0; + m.fileoffset = fileoffset; + m.filepositioned = 0; + m.filebytesleft = TIFFGetStrileByteCount(tif, 0); + if (!JPEGFixupTagsSubsamplingSec(&m)) + TIFFWarningExtR( + tif, module, + "Unable to auto-correct subsampling values, likely corrupt JPEG " + "compressed data in first strip/tile; auto-correcting skipped"); + _TIFFfreeExt(tif, m.buffer); } static int -JPEGFixupTagsSubsamplingSec(struct JPEGFixupTagsSubsamplingData *data) { - static const char module[] = "JPEGFixupTagsSubsamplingSec"; - uint8_t m; - while (1) { - while (1) { - if (!JPEGFixupTagsSubsamplingReadByte(data, &m)) - return (0); - if (m == 255) - break; - } - while (1) { - if (!JPEGFixupTagsSubsamplingReadByte(data, &m)) - return (0); - if (m != 255) - break; - } - switch (m) { - case JPEG_MARKER_SOI: - /* this type of marker has no data and should be skipped */ - break; - case JPEG_MARKER_COM: - case JPEG_MARKER_APP0: - case JPEG_MARKER_APP0 + 1: - case JPEG_MARKER_APP0 + 2: - case JPEG_MARKER_APP0 + 3: - case JPEG_MARKER_APP0 + 4: - case JPEG_MARKER_APP0 + 5: - case JPEG_MARKER_APP0 + 6: - case JPEG_MARKER_APP0 + 7: - case JPEG_MARKER_APP0 + 8: - case JPEG_MARKER_APP0 + 9: - case JPEG_MARKER_APP0 + 10: - case JPEG_MARKER_APP0 + 11: - case JPEG_MARKER_APP0 + 12: - case JPEG_MARKER_APP0 + 13: - case JPEG_MARKER_APP0 + 14: - case JPEG_MARKER_APP0 + 15: - case JPEG_MARKER_DQT: - case JPEG_MARKER_SOS: - case JPEG_MARKER_DHT: - case JPEG_MARKER_DRI: - /* this type of marker has data, but it has no use to us and should be - * skipped */ - { - uint16_t n; - if (!JPEGFixupTagsSubsamplingReadWord(data, &n)) - return (0); - if (n < 2) - return (0); - n -= 2; - if (n > 0) - JPEGFixupTagsSubsamplingSkip(data, n); - } - break; - case JPEG_MARKER_SOF0: /* Baseline sequential Huffman */ - case JPEG_MARKER_SOF1: /* Extended sequential Huffman */ - case JPEG_MARKER_SOF2: /* Progressive Huffman: normally not allowed by - TechNote, but that doesn't hurt supporting it */ - case JPEG_MARKER_SOF9: /* Extended sequential arithmetic */ - case JPEG_MARKER_SOF10: /* Progressive arithmetic: normally not allowed by - TechNote, but that doesn't hurt supporting it */ - /* this marker contains the subsampling factors we're scanning for */ - { - uint16_t n; - uint16_t o; - uint8_t p; - uint8_t ph, pv; - if (!JPEGFixupTagsSubsamplingReadWord(data, &n)) - return (0); - if (n != 8 + data->tif->tif_dir.td_samplesperpixel * 3) - return (0); - JPEGFixupTagsSubsamplingSkip(data, 7); - if (!JPEGFixupTagsSubsamplingReadByte(data, &p)) - return (0); - ph = (p >> 4); - pv = (p & 15); - JPEGFixupTagsSubsamplingSkip(data, 1); - for (o = 1; o < data->tif->tif_dir.td_samplesperpixel; o++) { - JPEGFixupTagsSubsamplingSkip(data, 1); - if (!JPEGFixupTagsSubsamplingReadByte(data, &p)) - return (0); - if (p != 0x11) { - TIFFWarningExt(data->tif->tif_clientdata, module, - "Subsampling values inside JPEG compressed data " - "have no TIFF equivalent, auto-correction of TIFF " - "subsampling values failed"); - return (1); - } - JPEGFixupTagsSubsamplingSkip(data, 1); +JPEGFixupTagsSubsamplingSec(struct JPEGFixupTagsSubsamplingData *data) +{ + static const char module[] = "JPEGFixupTagsSubsamplingSec"; + uint8_t m; + while (1) + { + while (1) + { + if (!JPEGFixupTagsSubsamplingReadByte(data, &m)) + return (0); + if (m == 255) + break; } - if (((ph != 1) && (ph != 2) && (ph != 4)) || - ((pv != 1) && (pv != 2) && (pv != 4))) { - TIFFWarningExt( - data->tif->tif_clientdata, module, - "Subsampling values inside JPEG compressed data have no TIFF " - "equivalent, auto-correction of TIFF subsampling values failed"); - return (1); + while (1) + { + if (!JPEGFixupTagsSubsamplingReadByte(data, &m)) + return (0); + if (m != 255) + break; } - if ((ph != data->tif->tif_dir.td_ycbcrsubsampling[0]) || - (pv != data->tif->tif_dir.td_ycbcrsubsampling[1])) { - TIFFWarningExt( - data->tif->tif_clientdata, module, - "Auto-corrected former TIFF subsampling values [%" PRIu16 - ",%" PRIu16 "] to match subsampling values inside JPEG " - "compressed data [%" PRIu8 ",%" PRIu8 "]", - data->tif->tif_dir.td_ycbcrsubsampling[0], - data->tif->tif_dir.td_ycbcrsubsampling[1], ph, pv); - data->tif->tif_dir.td_ycbcrsubsampling[0] = ph; - data->tif->tif_dir.td_ycbcrsubsampling[1] = pv; + switch (m) + { + case JPEG_MARKER_SOI: + /* this type of marker has no data and should be skipped */ + break; + case JPEG_MARKER_COM: + case JPEG_MARKER_APP0: + case JPEG_MARKER_APP0 + 1: + case JPEG_MARKER_APP0 + 2: + case JPEG_MARKER_APP0 + 3: + case JPEG_MARKER_APP0 + 4: + case JPEG_MARKER_APP0 + 5: + case JPEG_MARKER_APP0 + 6: + case JPEG_MARKER_APP0 + 7: + case JPEG_MARKER_APP0 + 8: + case JPEG_MARKER_APP0 + 9: + case JPEG_MARKER_APP0 + 10: + case JPEG_MARKER_APP0 + 11: + case JPEG_MARKER_APP0 + 12: + case JPEG_MARKER_APP0 + 13: + case JPEG_MARKER_APP0 + 14: + case JPEG_MARKER_APP0 + 15: + case JPEG_MARKER_DQT: + case JPEG_MARKER_SOS: + case JPEG_MARKER_DHT: + case JPEG_MARKER_DRI: + /* this type of marker has data, but it has no use to us and + * should be skipped */ + { + uint16_t n; + if (!JPEGFixupTagsSubsamplingReadWord(data, &n)) + return (0); + if (n < 2) + return (0); + n -= 2; + if (n > 0) + JPEGFixupTagsSubsamplingSkip(data, n); + } + break; + case JPEG_MARKER_SOF0: /* Baseline sequential Huffman */ + case JPEG_MARKER_SOF1: /* Extended sequential Huffman */ + case JPEG_MARKER_SOF2: /* Progressive Huffman: normally not allowed + by TechNote, but that doesn't hurt + supporting it */ + case JPEG_MARKER_SOF9: /* Extended sequential arithmetic */ + case JPEG_MARKER_SOF10: /* Progressive arithmetic: normally not + allowed by TechNote, but that doesn't + hurt supporting it */ + /* this marker contains the subsampling factors we're scanning + * for */ + { + uint16_t n; + uint16_t o; + uint8_t p; + uint8_t ph, pv; + if (!JPEGFixupTagsSubsamplingReadWord(data, &n)) + return (0); + if (n != 8 + data->tif->tif_dir.td_samplesperpixel * 3) + return (0); + JPEGFixupTagsSubsamplingSkip(data, 7); + if (!JPEGFixupTagsSubsamplingReadByte(data, &p)) + return (0); + ph = (p >> 4); + pv = (p & 15); + JPEGFixupTagsSubsamplingSkip(data, 1); + for (o = 1; o < data->tif->tif_dir.td_samplesperpixel; o++) + { + JPEGFixupTagsSubsamplingSkip(data, 1); + if (!JPEGFixupTagsSubsamplingReadByte(data, &p)) + return (0); + if (p != 0x11) + { + TIFFWarningExtR(data->tif, module, + "Subsampling values inside JPEG " + "compressed data " + "have no TIFF equivalent, " + "auto-correction of TIFF " + "subsampling values failed"); + return (1); + } + JPEGFixupTagsSubsamplingSkip(data, 1); + } + if (((ph != 1) && (ph != 2) && (ph != 4)) || + ((pv != 1) && (pv != 2) && (pv != 4))) + { + TIFFWarningExtR(data->tif, module, + "Subsampling values inside JPEG " + "compressed data have no TIFF " + "equivalent, auto-correction of TIFF " + "subsampling values failed"); + return (1); + } + if ((ph != data->tif->tif_dir.td_ycbcrsubsampling[0]) || + (pv != data->tif->tif_dir.td_ycbcrsubsampling[1])) + { + TIFFWarningExtR( + data->tif, module, + "Auto-corrected former TIFF subsampling values " + "[%" PRIu16 ",%" PRIu16 + "] to match subsampling values inside JPEG " + "compressed data [%" PRIu8 ",%" PRIu8 "]", + data->tif->tif_dir.td_ycbcrsubsampling[0], + data->tif->tif_dir.td_ycbcrsubsampling[1], ph, pv); + data->tif->tif_dir.td_ycbcrsubsampling[0] = ph; + data->tif->tif_dir.td_ycbcrsubsampling[1] = pv; + } + } + return (1); + default: + return (0); } - } - return (1); - default: - return (0); } - } } static int JPEGFixupTagsSubsamplingReadByte(struct JPEGFixupTagsSubsamplingData *data, - uint8_t *result) { - if (data->bufferbytesleft == 0) { - uint32_t m; - if (data->filebytesleft == 0) - return (0); - if (!data->filepositioned) { - if (TIFFSeekFile(data->tif, data->fileoffset, SEEK_SET) == (toff_t)-1) { - return 0; - } - data->filepositioned = 1; - } - m = data->buffersize; - if ((uint64_t)m > data->filebytesleft) - m = (uint32_t)data->filebytesleft; - assert(m < 0x80000000UL); - if (TIFFReadFile(data->tif, data->buffer, (tmsize_t)m) != (tmsize_t)m) - return (0); - data->buffercurrentbyte = data->buffer; - data->bufferbytesleft = m; - data->fileoffset += m; - data->filebytesleft -= m; - } - *result = *data->buffercurrentbyte; - data->buffercurrentbyte++; - data->bufferbytesleft--; - return (1); + uint8_t *result) +{ + if (data->bufferbytesleft == 0) + { + uint32_t m; + if (data->filebytesleft == 0) + return (0); + if (!data->filepositioned) + { + if (TIFFSeekFile(data->tif, data->fileoffset, SEEK_SET) == + (toff_t)-1) + { + return 0; + } + data->filepositioned = 1; + } + m = data->buffersize; + if ((uint64_t)m > data->filebytesleft) + m = (uint32_t)data->filebytesleft; + assert(m < 0x80000000UL); + if (TIFFReadFile(data->tif, data->buffer, (tmsize_t)m) != (tmsize_t)m) + return (0); + data->buffercurrentbyte = data->buffer; + data->bufferbytesleft = m; + data->fileoffset += m; + data->filebytesleft -= m; + } + *result = *data->buffercurrentbyte; + data->buffercurrentbyte++; + data->bufferbytesleft--; + return (1); } static int JPEGFixupTagsSubsamplingReadWord(struct JPEGFixupTagsSubsamplingData *data, - uint16_t *result) { - uint8_t ma; - uint8_t mb; - if (!JPEGFixupTagsSubsamplingReadByte(data, &ma)) - return (0); - if (!JPEGFixupTagsSubsamplingReadByte(data, &mb)) - return (0); - *result = (ma << 8) | mb; - return (1); + uint16_t *result) +{ + uint8_t ma; + uint8_t mb; + if (!JPEGFixupTagsSubsamplingReadByte(data, &ma)) + return (0); + if (!JPEGFixupTagsSubsamplingReadByte(data, &mb)) + return (0); + *result = (ma << 8) | mb; + return (1); } static void JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData *data, - uint16_t skiplength) { - if ((uint32_t)skiplength <= data->bufferbytesleft) { - data->buffercurrentbyte += skiplength; - data->bufferbytesleft -= skiplength; - } else { - uint16_t m; - m = (uint16_t)(skiplength - data->bufferbytesleft); - if (m <= data->filebytesleft) { - data->bufferbytesleft = 0; - data->fileoffset += m; - data->filebytesleft -= m; - data->filepositioned = 0; - } else { - data->bufferbytesleft = 0; - data->filebytesleft = 0; - } - } + uint16_t skiplength) +{ + if ((uint32_t)skiplength <= data->bufferbytesleft) + { + data->buffercurrentbyte += skiplength; + data->bufferbytesleft -= skiplength; + } + else + { + uint16_t m; + m = (uint16_t)(skiplength - data->bufferbytesleft); + if (m <= data->filebytesleft) + { + data->bufferbytesleft = 0; + data->fileoffset += m; + data->filebytesleft -= m; + data->filepositioned = 0; + } + else + { + data->bufferbytesleft = 0; + data->filebytesleft = 0; + } + } } #endif -static int JPEGSetupDecode(TIFF *tif) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; +static int JPEGSetupDecode(TIFF *tif) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; #if defined(JPEG_DUAL_MODE_8_12) && !defined(FROM_TIF_JPEG_12) - if (tif->tif_dir.td_bitspersample == 12) { - /* We pass a pointer to a copy of otherSettings, since */ - /* TIFFReInitJPEG_12() will clear sp */ - JPEGOtherSettings savedOtherSettings = sp->otherSettings; - return TIFFReInitJPEG_12(tif, &savedOtherSettings, COMPRESSION_JPEG, 0); - } + if (tif->tif_dir.td_bitspersample == 12) + { + /* We pass a pointer to a copy of otherSettings, since */ + /* TIFFReInitJPEG_12() will clear sp */ + JPEGOtherSettings savedOtherSettings = sp->otherSettings; + return TIFFReInitJPEG_12(tif, &savedOtherSettings, COMPRESSION_JPEG, 0); + } #endif - JPEGInitializeLibJPEG(tif, TRUE); - - assert(sp != NULL); - assert(sp->cinfo.comm.is_decompressor); - - /* Read JPEGTables if it is present */ - if (TIFFFieldSet(tif, FIELD_JPEGTABLES)) { - TIFFjpeg_tables_src(sp); - if (TIFFjpeg_read_header(sp, FALSE) != JPEG_HEADER_TABLES_ONLY) { - TIFFErrorExt(tif->tif_clientdata, "JPEGSetupDecode", - "Bogus JPEGTables field"); - return (0); - } - } - - /* Grab parameters that are same for all strips/tiles */ - sp->photometric = td->td_photometric; - switch (sp->photometric) { - case PHOTOMETRIC_YCBCR: - sp->h_sampling = td->td_ycbcrsubsampling[0]; - sp->v_sampling = td->td_ycbcrsubsampling[1]; - break; - default: - /* TIFF 6.0 forbids subsampling of all other color spaces */ - sp->h_sampling = 1; - sp->v_sampling = 1; - break; - } - - /* Set up for reading normal data */ - TIFFjpeg_data_src(sp); - tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */ - return (1); + JPEGInitializeLibJPEG(tif, TRUE); + + assert(sp != NULL); + assert(sp->cinfo.comm.is_decompressor); + + /* Read JPEGTables if it is present */ + if (TIFFFieldSet(tif, FIELD_JPEGTABLES)) + { + TIFFjpeg_tables_src(sp); + if (TIFFjpeg_read_header(sp, FALSE) != JPEG_HEADER_TABLES_ONLY) + { + TIFFErrorExtR(tif, "JPEGSetupDecode", "Bogus JPEGTables field"); + return (0); + } + } + + /* Grab parameters that are same for all strips/tiles */ + sp->photometric = td->td_photometric; + switch (sp->photometric) + { + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + break; + default: + /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = 1; + sp->v_sampling = 1; + break; + } + + /* Set up for reading normal data */ + TIFFjpeg_data_src(sp); + tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */ + return (1); } /* Returns 1 if the full strip should be read, even when doing scanline per */ @@ -998,269 +1153,303 @@ static int JPEGSetupDecode(TIFF *tif) { /* Only reads tif->tif_dir.td_bitspersample, tif->tif_rawdata and */ /* tif->tif_rawcc members. */ /* Can be called independently of the usual setup/predecode/decode states */ -int TIFFJPEGIsFullStripRequired(TIFF *tif) { - int ret; - JPEGState state; +int TIFFJPEGIsFullStripRequired(TIFF *tif) +{ + int ret; + JPEGState state; #if defined(JPEG_DUAL_MODE_8_12) && !defined(FROM_TIF_JPEG_12) - if (tif->tif_dir.td_bitspersample == 12) - return TIFFJPEGIsFullStripRequired_12(tif); + if (tif->tif_dir.td_bitspersample == 12) + return TIFFJPEGIsFullStripRequired_12(tif); #endif - memset(&state, 0, sizeof(JPEGState)); - state.tif = tif; + memset(&state, 0, sizeof(JPEGState)); + state.tif = tif; - TIFFjpeg_create_decompress(&state); + TIFFjpeg_create_decompress(&state); - TIFFjpeg_data_src(&state); + TIFFjpeg_data_src(&state); - if (TIFFjpeg_read_header(&state, TRUE) != JPEG_HEADER_OK) { - TIFFjpeg_destroy(&state); - return (0); - } - ret = TIFFjpeg_has_multiple_scans(&state); + if (TIFFjpeg_read_header(&state, TRUE) != JPEG_HEADER_OK) + { + TIFFjpeg_destroy(&state); + return (0); + } + ret = TIFFjpeg_has_multiple_scans(&state); - TIFFjpeg_destroy(&state); + TIFFjpeg_destroy(&state); - return ret; + return ret; } /* * Set up for decoding a strip or tile. */ -/*ARGSUSED*/ static int JPEGPreDecode(TIFF *tif, uint16_t s) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; - static const char module[] = "JPEGPreDecode"; - uint32_t segment_width, segment_height; - int downsampled_output; - int ci; - - assert(sp != NULL); - - if (sp->cinfo.comm.is_decompressor == 0) { - tif->tif_setupdecode(tif); - } - - assert(sp->cinfo.comm.is_decompressor); - /* - * Reset decoder state from any previous strip/tile, - * in case application didn't read the whole strip. - */ - if (!TIFFjpeg_abort(sp)) - return (0); - /* - * Read the header for this strip/tile. - */ - - if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK) - return (0); - - tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; - tif->tif_rawcc = sp->src.bytes_in_buffer; - - /* - * Check image parameters and set decompression parameters. - */ - if (isTiled(tif)) { - segment_width = td->td_tilewidth; - segment_height = td->td_tilelength; - sp->bytesperline = TIFFTileRowSize(tif); - } else { - segment_width = td->td_imagewidth; - segment_height = td->td_imagelength - tif->tif_row; - if (segment_height > td->td_rowsperstrip) - segment_height = td->td_rowsperstrip; - sp->bytesperline = TIFFScanlineSize(tif); - } - if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { +/*ARGSUSED*/ static int JPEGPreDecode(TIFF *tif, uint16_t s) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGPreDecode"; + uint32_t segment_width, segment_height; + int downsampled_output; + int ci; + + assert(sp != NULL); + + if (sp->cinfo.comm.is_decompressor == 0) + { + tif->tif_setupdecode(tif); + } + + assert(sp->cinfo.comm.is_decompressor); /* - * For PC 2, scale down the expected strip/tile size - * to match a downsampled component + * Reset decoder state from any previous strip/tile, + * in case application didn't read the whole strip. */ - segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); - segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); - } - if (sp->cinfo.d.image_width < segment_width || - sp->cinfo.d.image_height < segment_height) { - TIFFWarningExt(tif->tif_clientdata, module, - "Improper JPEG strip/tile size, " - "expected %" PRIu32 "x%" PRIu32 ", got %ux%u", - segment_width, segment_height, sp->cinfo.d.image_width, - sp->cinfo.d.image_height); - } - if (sp->cinfo.d.image_width == segment_width && - sp->cinfo.d.image_height > segment_height && - tif->tif_row + segment_height == td->td_imagelength && !isTiled(tif)) { - /* Some files have a last strip, that should be truncated, */ - /* but their JPEG codestream has still the maximum strip */ - /* height. Warn about this as this is non compliant, but */ - /* we can safely recover from that. */ - TIFFWarningExt(tif->tif_clientdata, module, - "JPEG strip size exceeds expected dimensions," - " expected %" PRIu32 "x%" PRIu32 ", got %ux%u", - segment_width, segment_height, sp->cinfo.d.image_width, - sp->cinfo.d.image_height); - } else if (sp->cinfo.d.image_width > segment_width || - sp->cinfo.d.image_height > segment_height) { + if (!TIFFjpeg_abort(sp)) + return (0); /* - * This case could be dangerous, if the strip or tile size has - * been reported as less than the amount of data jpeg will - * return, some potential security issues arise. Catch this - * case and error out. + * Read the header for this strip/tile. */ - TIFFErrorExt(tif->tif_clientdata, module, - "JPEG strip/tile size exceeds expected dimensions," - " expected %" PRIu32 "x%" PRIu32 ", got %ux%u", - segment_width, segment_height, sp->cinfo.d.image_width, - sp->cinfo.d.image_height); - return (0); - } - if (sp->cinfo.d.num_components != (td->td_planarconfig == PLANARCONFIG_CONTIG - ? td->td_samplesperpixel - : 1)) { - TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG component count"); - return (0); - } + + if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK) + return (0); + + tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; + tif->tif_rawcc = sp->src.bytes_in_buffer; + + /* + * Check image parameters and set decompression parameters. + */ + if (isTiled(tif)) + { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + sp->bytesperline = TIFFTileRowSize(tif); + } + else + { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFScanlineSize(tif); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) + { + /* + * For PC 2, scale down the expected strip/tile size + * to match a downsampled component + */ + segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); + segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); + } + if (sp->cinfo.d.image_width < segment_width || + sp->cinfo.d.image_height < segment_height) + { + TIFFWarningExtR(tif, module, + "Improper JPEG strip/tile size, " + "expected %" PRIu32 "x%" PRIu32 ", got %ux%u", + segment_width, segment_height, sp->cinfo.d.image_width, + sp->cinfo.d.image_height); + } + if (sp->cinfo.d.image_width == segment_width && + sp->cinfo.d.image_height > segment_height && + tif->tif_row + segment_height == td->td_imagelength && !isTiled(tif)) + { + /* Some files have a last strip, that should be truncated, */ + /* but their JPEG codestream has still the maximum strip */ + /* height. Warn about this as this is non compliant, but */ + /* we can safely recover from that. */ + TIFFWarningExtR(tif, module, + "JPEG strip size exceeds expected dimensions," + " expected %" PRIu32 "x%" PRIu32 ", got %ux%u", + segment_width, segment_height, sp->cinfo.d.image_width, + sp->cinfo.d.image_height); + } + else if (sp->cinfo.d.image_width > segment_width || + sp->cinfo.d.image_height > segment_height) + { + /* + * This case could be dangerous, if the strip or tile size has + * been reported as less than the amount of data jpeg will + * return, some potential security issues arise. Catch this + * case and error out. + */ + TIFFErrorExtR(tif, module, + "JPEG strip/tile size exceeds expected dimensions," + " expected %" PRIu32 "x%" PRIu32 ", got %ux%u", + segment_width, segment_height, sp->cinfo.d.image_width, + sp->cinfo.d.image_height); + return (0); + } + if (sp->cinfo.d.num_components != + (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel + : 1)) + { + TIFFErrorExtR(tif, module, "Improper JPEG component count"); + return (0); + } #ifdef JPEG_LIB_MK1 - if (12 != td->td_bitspersample && 8 != td->td_bitspersample) { - TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision"); - return (0); - } - sp->cinfo.d.data_precision = td->td_bitspersample; - sp->cinfo.d.bits_in_jsample = td->td_bitspersample; + if (12 != td->td_bitspersample && 8 != td->td_bitspersample) + { + TIFFErrorExtR(tif, module, "Improper JPEG data precision"); + return (0); + } + sp->cinfo.d.data_precision = td->td_bitspersample; + sp->cinfo.d.bits_in_jsample = td->td_bitspersample; #else - if (sp->cinfo.d.data_precision != td->td_bitspersample) { - TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision"); - return (0); - } + if (sp->cinfo.d.data_precision != td->td_bitspersample) + { + TIFFErrorExtR(tif, module, "Improper JPEG data precision"); + return (0); + } #endif - if (sp->cinfo.d.progressive_mode && - !sp->otherSettings.has_warned_about_progressive_mode) { - TIFFWarningExt(tif->tif_clientdata, module, - "The JPEG strip/tile is encoded with progressive mode, " - "which is normally not legal for JPEG-in-TIFF.\n" - "libtiff should be able to decode it, but it might " - "cause compatibility issues with other readers"); - sp->otherSettings.has_warned_about_progressive_mode = TRUE; - } - - /* In some cases, libjpeg needs to allocate a lot of memory */ - /* http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf - */ - if (TIFFjpeg_has_multiple_scans(sp)) { - /* In this case libjpeg will need to allocate memory or backing */ - /* store for all coefficients */ - /* See call to jinit_d_coef_controller() from master_selection() */ - /* in libjpeg */ - - /* 1 MB for regular libjpeg usage */ - toff_t nRequiredMemory = 1024 * 1024; - - for (ci = 0; ci < sp->cinfo.d.num_components; ci++) { - const jpeg_component_info *compptr = &(sp->cinfo.d.comp_info[ci]); - if (compptr->h_samp_factor > 0 && compptr->v_samp_factor > 0) { - nRequiredMemory += - (toff_t)(((compptr->width_in_blocks + compptr->h_samp_factor - 1) / - compptr->h_samp_factor)) * - ((compptr->height_in_blocks + compptr->v_samp_factor - 1) / - compptr->v_samp_factor) * - sizeof(JBLOCK); - } - } - - if (sp->cinfo.d.mem->max_memory_to_use > 0 && - nRequiredMemory > (toff_t)(sp->cinfo.d.mem->max_memory_to_use) && - getenv("LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC") == NULL) { - TIFFErrorExt( - tif->tif_clientdata, module, - "Reading this image would require libjpeg to allocate " - "at least %" PRIu64 " bytes. " - "This is disabled since above the %ld threshold. " - "You may override this restriction by defining the " - "LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, " - "or setting the JPEGMEM environment variable to a value greater " - "or equal to '%" PRIu64 "M'", - nRequiredMemory, sp->cinfo.d.mem->max_memory_to_use, - (nRequiredMemory + 1000000u - 1u) / 1000000u); - return 0; - } - } - - if (td->td_planarconfig == PLANARCONFIG_CONTIG) { - /* Component 0 should have expected sampling factors */ - if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling || - sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) { - TIFFErrorExt(tif->tif_clientdata, module, - "Improper JPEG sampling factors %d,%d\n" - "Apparently should be %" PRIu16 ",%" PRIu16 ".", - sp->cinfo.d.comp_info[0].h_samp_factor, - sp->cinfo.d.comp_info[0].v_samp_factor, sp->h_sampling, - sp->v_sampling); - return (0); - } - /* Rest should have sampling factors 1,1 */ - for (ci = 1; ci < sp->cinfo.d.num_components; ci++) { - if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 || - sp->cinfo.d.comp_info[ci].v_samp_factor != 1) { - TIFFErrorExt(tif->tif_clientdata, module, - "Improper JPEG sampling factors"); - return (0); - } - } - } else { - /* PC 2's single component should have sampling factors 1,1 */ - if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 || - sp->cinfo.d.comp_info[0].v_samp_factor != 1) { - TIFFErrorExt(tif->tif_clientdata, module, - "Improper JPEG sampling factors"); - return (0); - } - } - downsampled_output = FALSE; - if (td->td_planarconfig == PLANARCONFIG_CONTIG && - sp->photometric == PHOTOMETRIC_YCBCR && - sp->otherSettings.jpegcolormode == JPEGCOLORMODE_RGB) { - /* Convert YCbCr to RGB */ - sp->cinfo.d.jpeg_color_space = JCS_YCbCr; - sp->cinfo.d.out_color_space = JCS_RGB; - } else { - /* Suppress colorspace handling */ - sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN; - sp->cinfo.d.out_color_space = JCS_UNKNOWN; + if (sp->cinfo.d.progressive_mode && + !sp->otherSettings.has_warned_about_progressive_mode) + { + TIFFWarningExtR(tif, module, + "The JPEG strip/tile is encoded with progressive mode, " + "which is normally not legal for JPEG-in-TIFF.\n" + "libtiff should be able to decode it, but it might " + "cause compatibility issues with other readers"); + sp->otherSettings.has_warned_about_progressive_mode = TRUE; + } + + /* In some cases, libjpeg needs to allocate a lot of memory */ + /* http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf + */ + if (TIFFjpeg_has_multiple_scans(sp)) + { + /* In this case libjpeg will need to allocate memory or backing */ + /* store for all coefficients */ + /* See call to jinit_d_coef_controller() from master_selection() */ + /* in libjpeg */ + + /* 1 MB for regular libjpeg usage */ + toff_t nRequiredMemory = 1024 * 1024; + + for (ci = 0; ci < sp->cinfo.d.num_components; ci++) + { + const jpeg_component_info *compptr = &(sp->cinfo.d.comp_info[ci]); + if (compptr->h_samp_factor > 0 && compptr->v_samp_factor > 0) + { + nRequiredMemory += + (toff_t)(((compptr->width_in_blocks + + compptr->h_samp_factor - 1) / + compptr->h_samp_factor)) * + ((compptr->height_in_blocks + compptr->v_samp_factor - 1) / + compptr->v_samp_factor) * + sizeof(JBLOCK); + } + } + + if (sp->cinfo.d.mem->max_memory_to_use > 0 && + nRequiredMemory > (toff_t)(sp->cinfo.d.mem->max_memory_to_use) && + getenv("LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC") == NULL) + { + TIFFErrorExtR( + tif, module, + "Reading this image would require libjpeg to allocate " + "at least %" PRIu64 " bytes. " + "This is disabled since above the %ld threshold. " + "You may override this restriction by defining the " + "LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, " + "or setting the JPEGMEM environment variable to a value " + "greater " + "or equal to '%" PRIu64 "M'", + nRequiredMemory, sp->cinfo.d.mem->max_memory_to_use, + (nRequiredMemory + 1000000u - 1u) / 1000000u); + return 0; + } + } + + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + { + /* Component 0 should have expected sampling factors */ + if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling || + sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) + { + TIFFErrorExtR(tif, module, + "Improper JPEG sampling factors %d,%d\n" + "Apparently should be %" PRIu16 ",%" PRIu16 ".", + sp->cinfo.d.comp_info[0].h_samp_factor, + sp->cinfo.d.comp_info[0].v_samp_factor, + sp->h_sampling, sp->v_sampling); + return (0); + } + /* Rest should have sampling factors 1,1 */ + for (ci = 1; ci < sp->cinfo.d.num_components; ci++) + { + if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 || + sp->cinfo.d.comp_info[ci].v_samp_factor != 1) + { + TIFFErrorExtR(tif, module, "Improper JPEG sampling factors"); + return (0); + } + } + } + else + { + /* PC 2's single component should have sampling factors 1,1 */ + if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 || + sp->cinfo.d.comp_info[0].v_samp_factor != 1) + { + TIFFErrorExtR(tif, module, "Improper JPEG sampling factors"); + return (0); + } + } + downsampled_output = FALSE; if (td->td_planarconfig == PLANARCONFIG_CONTIG && - (sp->h_sampling != 1 || sp->v_sampling != 1)) - downsampled_output = TRUE; - /* XXX what about up-sampling? */ - } - if (downsampled_output) { - /* Need to use raw-data interface to libjpeg */ - sp->cinfo.d.raw_data_out = TRUE; + sp->photometric == PHOTOMETRIC_YCBCR && + sp->otherSettings.jpegcolormode == JPEGCOLORMODE_RGB) + { + /* Convert YCbCr to RGB */ + sp->cinfo.d.jpeg_color_space = JCS_YCbCr; + sp->cinfo.d.out_color_space = JCS_RGB; + } + else + { + /* Suppress colorspace handling */ + sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN; + sp->cinfo.d.out_color_space = JCS_UNKNOWN; + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + (sp->h_sampling != 1 || sp->v_sampling != 1)) + downsampled_output = TRUE; + /* XXX what about up-sampling? */ + } + if (downsampled_output) + { + /* Need to use raw-data interface to libjpeg */ + sp->cinfo.d.raw_data_out = TRUE; #if JPEG_LIB_VERSION >= 70 - sp->cinfo.d.do_fancy_upsampling = FALSE; + sp->cinfo.d.do_fancy_upsampling = FALSE; #endif /* JPEG_LIB_VERSION >= 70 */ - tif->tif_decoderow = DecodeRowError; - tif->tif_decodestrip = JPEGDecodeRaw; - tif->tif_decodetile = JPEGDecodeRaw; - } else { - /* Use normal interface to libjpeg */ - sp->cinfo.d.raw_data_out = FALSE; - tif->tif_decoderow = JPEGDecode; - tif->tif_decodestrip = JPEGDecode; - tif->tif_decodetile = JPEGDecode; - } - /* Start JPEG decompressor */ - if (!TIFFjpeg_start_decompress(sp)) - return (0); - /* Allocate downsampled-data buffers if needed */ - if (downsampled_output) { - if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info, - sp->cinfo.d.num_components)) - return (0); - sp->scancount = DCTSIZE; /* mark buffer empty */ - } - return (1); + tif->tif_decoderow = DecodeRowError; + tif->tif_decodestrip = JPEGDecodeRaw; + tif->tif_decodetile = JPEGDecodeRaw; + } + else + { + /* Use normal interface to libjpeg */ + sp->cinfo.d.raw_data_out = FALSE; + tif->tif_decoderow = JPEGDecode; + tif->tif_decodestrip = JPEGDecode; + tif->tif_decodetile = JPEGDecode; + } + /* Start JPEG decompressor */ + if (!TIFFjpeg_start_decompress(sp)) + return (0); + /* Allocate downsampled-data buffers if needed */ + if (downsampled_output) + { + if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info, + sp->cinfo.d.num_components)) + return (0); + sp->scancount = DCTSIZE; /* mark buffer empty */ + } + return (1); } /* @@ -1268,148 +1457,163 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif) { * "Standard" case: returned data is not downsampled. */ #if !JPEG_LIB_MK1_OR_12BIT -static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) { - JPEGState *sp = JState(tif); - tmsize_t nrows; - (void)s; - - /* - ** Update available information, buffer may have been refilled - ** between decode requests - */ - sp->src.next_input_byte = (const JOCTET *)tif->tif_rawcp; - sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; - - if (sp->bytesperline == 0) - return 0; +static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) +{ + JPEGState *sp = JState(tif); + tmsize_t nrows; + (void)s; - nrows = cc / sp->bytesperline; - if (cc % sp->bytesperline) - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "fractional scanline not read"); + /* + ** Update available information, buffer may have been refilled + ** between decode requests + */ + sp->src.next_input_byte = (const JOCTET *)tif->tif_rawcp; + sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; - if (nrows > (tmsize_t)sp->cinfo.d.image_height) - nrows = sp->cinfo.d.image_height; + if (sp->bytesperline == 0) + return 0; - /* data is expected to be read in multiples of a scanline */ - if (nrows) { - do { - /* - * In the libjpeg6b-9a 8bit case. We read directly into - * the TIFF buffer. - */ - JSAMPROW bufptr = (JSAMPROW)buf; + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarningExtR(tif, tif->tif_name, "fractional scanline not read"); - if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) - return (0); + if (nrows > (tmsize_t)sp->cinfo.d.image_height) + nrows = sp->cinfo.d.image_height; - ++tif->tif_row; - buf += sp->bytesperline; - cc -= sp->bytesperline; - } while (--nrows > 0); - } + /* data is expected to be read in multiples of a scanline */ + if (nrows) + { + do + { + /* + * In the libjpeg6b-9a 8bit case. We read directly into + * the TIFF buffer. + */ + JSAMPROW bufptr = (JSAMPROW)buf; + + if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) + return (0); + + ++tif->tif_row; + buf += sp->bytesperline; + cc -= sp->bytesperline; + } while (--nrows > 0); + } - /* Update information on consumed data */ - tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; - tif->tif_rawcc = sp->src.bytes_in_buffer; + /* Update information on consumed data */ + tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; + tif->tif_rawcc = sp->src.bytes_in_buffer; - /* Close down the decompressor if we've finished the strip or tile. */ - return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || - TIFFjpeg_finish_decompress(sp); + /* Close down the decompressor if we've finished the strip or tile. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || + TIFFjpeg_finish_decompress(sp); } #endif /* !JPEG_LIB_MK1_OR_12BIT */ #if JPEG_LIB_MK1_OR_12BIT /*ARGSUSED*/ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, - uint16_t s) { - JPEGState *sp = JState(tif); - tmsize_t nrows; - (void)s; - - /* - ** Update available information, buffer may have been refilled - ** between decode requests - */ - sp->src.next_input_byte = (const JOCTET *)tif->tif_rawcp; - sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; - - if (sp->bytesperline == 0) - return 0; + uint16_t s) +{ + JPEGState *sp = JState(tif); + tmsize_t nrows; + (void)s; - nrows = cc / sp->bytesperline; - if (cc % sp->bytesperline) - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "fractional scanline not read"); + /* + ** Update available information, buffer may have been refilled + ** between decode requests + */ + sp->src.next_input_byte = (const JOCTET *)tif->tif_rawcp; + sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; - if (nrows > (tmsize_t)sp->cinfo.d.image_height) - nrows = sp->cinfo.d.image_height; + if (sp->bytesperline == 0) + return 0; - /* data is expected to be read in multiples of a scanline */ - if (nrows) { - JSAMPROW line_work_buf = NULL; + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarningExtR(tif, tif->tif_name, "fractional scanline not read"); - /* - * For 6B, only use temporary buffer for 12 bit imagery. - * For Mk1 always use it. - */ - if (sp->cinfo.d.data_precision == 12) { - line_work_buf = - (JSAMPROW)_TIFFmalloc(sizeof(short) * sp->cinfo.d.output_width * - sp->cinfo.d.num_components); - } + if (nrows > (tmsize_t)sp->cinfo.d.image_height) + nrows = sp->cinfo.d.image_height; + + /* data is expected to be read in multiples of a scanline */ + if (nrows) + { + TIFF_JSAMPROW line_work_buf = NULL; - do { - if (line_work_buf != NULL) { /* - * In the MK1 case, we always read into a 16bit - * buffer, and then pack down to 12bit or 8bit. - * In 6B case we only read into 16 bit buffer - * for 12bit data, which we need to repack. + * For 6B, only use temporary buffer for 12 bit imagery. + * For Mk1 always use it. */ - if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1) - return (0); - - if (sp->cinfo.d.data_precision == 12) { - int value_pairs = - (sp->cinfo.d.output_width * sp->cinfo.d.num_components) / 2; - int iPair; - - for (iPair = 0; iPair < value_pairs; iPair++) { - unsigned char *out_ptr = ((unsigned char *)buf) + iPair * 3; - JSAMPLE *in_ptr = line_work_buf + iPair * 2; - - out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4); - out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4) | - ((in_ptr[1] & 0xf00) >> 8)); - out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0)); - } - } else if (sp->cinfo.d.data_precision == 8) { - int value_count = - (sp->cinfo.d.output_width * sp->cinfo.d.num_components); - int iValue; - - for (iValue = 0; iValue < value_count; iValue++) { - ((unsigned char *)buf)[iValue] = line_work_buf[iValue] & 0xff; - } + if (sp->cinfo.d.data_precision == 12) + { + line_work_buf = (TIFF_JSAMPROW)_TIFFmallocExt( + tif, sizeof(short) * sp->cinfo.d.output_width * + sp->cinfo.d.num_components); } - } - ++tif->tif_row; - buf += sp->bytesperline; - cc -= sp->bytesperline; - } while (--nrows > 0); + do + { + if (line_work_buf != NULL) + { + /* + * In the MK1 case, we always read into a 16bit + * buffer, and then pack down to 12bit or 8bit. + * In 6B case we only read into 16 bit buffer + * for 12bit data, which we need to repack. + */ + if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1) + return (0); + + if (sp->cinfo.d.data_precision == 12) + { + int value_pairs = (sp->cinfo.d.output_width * + sp->cinfo.d.num_components) / + 2; + int iPair; + + for (iPair = 0; iPair < value_pairs; iPair++) + { + unsigned char *out_ptr = + ((unsigned char *)buf) + iPair * 3; + TIFF_JSAMPLE *in_ptr = line_work_buf + iPair * 2; + + out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4); + out_ptr[1] = + (unsigned char)(((in_ptr[0] & 0xf) << 4) | + ((in_ptr[1] & 0xf00) >> 8)); + out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0)); + } + } + else if (sp->cinfo.d.data_precision == 8) + { + int value_count = + (sp->cinfo.d.output_width * sp->cinfo.d.num_components); + int iValue; + + for (iValue = 0; iValue < value_count; iValue++) + { + ((unsigned char *)buf)[iValue] = + line_work_buf[iValue] & 0xff; + } + } + } + + ++tif->tif_row; + buf += sp->bytesperline; + cc -= sp->bytesperline; + } while (--nrows > 0); - if (line_work_buf != NULL) - _TIFFfree(line_work_buf); - } + if (line_work_buf != NULL) + _TIFFfreeExt(tif, line_work_buf); + } - /* Update information on consumed data */ - tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; - tif->tif_rawcc = sp->src.bytes_in_buffer; + /* Update information on consumed data */ + tif->tif_rawcp = (uint8_t *)sp->src.next_input_byte; + tif->tif_rawcc = sp->src.bytes_in_buffer; - /* Close down the decompressor if we've finished the strip or tile. */ - return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || - TIFFjpeg_finish_decompress(sp); + /* Close down the decompressor if we've finished the strip or tile. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || + TIFFjpeg_finish_decompress(sp); } #endif /* JPEG_LIB_MK1_OR_12BIT */ @@ -1417,15 +1621,16 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) { uint16_t s) { - (void)buf; - (void)cc; - (void)s; - - TIFFErrorExt(tif->tif_clientdata, "TIFFReadScanline", - "scanline oriented access is not supported for downsampled JPEG " - "compressed images, consider enabling TIFF_JPEGCOLORMODE as " - "JPEGCOLORMODE_RGB."); - return 0; + (void)buf; + (void)cc; + (void)s; + + TIFFErrorExtR( + tif, "TIFFReadScanline", + "scanline oriented access is not supported for downsampled JPEG " + "compressed images, consider enabling TIFFTAG_JPEGCOLORMODE as " + "JPEGCOLORMODE_RGB."); + return 0; } /* @@ -1433,218 +1638,252 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) { * Returned data is downsampled per sampling factors. */ /*ARGSUSED*/ static int JPEGDecodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc, - uint16_t s) { - JPEGState *sp = JState(tif); - tmsize_t nrows; - TIFFDirectory *td = &tif->tif_dir; - (void)s; - - nrows = sp->cinfo.d.image_height; - /* For last strip, limit number of rows to its truncated height */ - /* even if the codestream height is larger (which is not compliant, */ - /* but that we tolerate) */ - if ((uint32_t)nrows > td->td_imagelength - tif->tif_row && !isTiled(tif)) - nrows = td->td_imagelength - tif->tif_row; + uint16_t s) +{ + JPEGState *sp = JState(tif); + tmsize_t nrows; + TIFFDirectory *td = &tif->tif_dir; + (void)s; + + nrows = sp->cinfo.d.image_height; + /* For last strip, limit number of rows to its truncated height */ + /* even if the codestream height is larger (which is not compliant, */ + /* but that we tolerate) */ + if ((uint32_t)nrows > td->td_imagelength - tif->tif_row && !isTiled(tif)) + nrows = td->td_imagelength - tif->tif_row; #if defined(JPEG_LIB_MK1_OR_12BIT) - unsigned short *tmpbuf = NULL; + unsigned short *tmpbuf = NULL; #endif - /* data is expected to be read in multiples of a scanline */ - if (nrows != 0) { + /* data is expected to be read in multiples of a scanline */ + if (nrows != 0) + { - /* Cb,Cr both have sampling factors 1, so this is correct */ - JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width; - int samples_per_clump = sp->samplesperclump; + /* Cb,Cr both have sampling factors 1, so this is correct */ + JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width; + int samples_per_clump = sp->samplesperclump; #if defined(JPEG_LIB_MK1_OR_12BIT) - tmpbuf = _TIFFmalloc(sizeof(unsigned short) * sp->cinfo.d.output_width * - sp->cinfo.d.num_components); - if (tmpbuf == NULL) { - TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", "Out of memory"); - return 0; - } + tmpbuf = _TIFFmallocExt(tif, sizeof(unsigned short) * + sp->cinfo.d.output_width * + sp->cinfo.d.num_components); + if (tmpbuf == NULL) + { + TIFFErrorExtR(tif, "JPEGDecodeRaw", "Out of memory"); + return 0; + } #endif - do { - jpeg_component_info *compptr; - int ci, clumpoffset; - - if (cc < sp->bytesperline) { - TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", - "application buffer not large enough for all data."); - goto error; - } - - /* Reload downsampled-data buffer if needed */ - if (sp->scancount >= DCTSIZE) { - int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE; - if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) != n) - goto error; - sp->scancount = 0; - } - /* - * Fastest way to unseparate data is to make one pass - * over the scanline for each row of each component. - */ - clumpoffset = 0; /* first sample in clump */ - for (ci = 0, compptr = sp->cinfo.d.comp_info; - ci < sp->cinfo.d.num_components; ci++, compptr++) { - int hsamp = compptr->h_samp_factor; - int vsamp = compptr->v_samp_factor; - int ypos; - - for (ypos = 0; ypos < vsamp; ypos++) { - JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount * vsamp + ypos]; - JDIMENSION nclump; + do + { + jpeg_component_info *compptr; + int ci, clumpoffset; + + if (cc < sp->bytesperline) + { + TIFFErrorExtR( + tif, "JPEGDecodeRaw", + "application buffer not large enough for all data."); + goto error; + } + + /* Reload downsampled-data buffer if needed */ + if (sp->scancount >= DCTSIZE) + { + int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) != n) + goto error; + sp->scancount = 0; + } + /* + * Fastest way to unseparate data is to make one pass + * over the scanline for each row of each component. + */ + clumpoffset = 0; /* first sample in clump */ + for (ci = 0, compptr = sp->cinfo.d.comp_info; + ci < sp->cinfo.d.num_components; ci++, compptr++) + { + int hsamp = compptr->h_samp_factor; + int vsamp = compptr->v_samp_factor; + int ypos; + + for (ypos = 0; ypos < vsamp; ypos++) + { + TIFF_JSAMPLE *inptr = + sp->ds_buffer[ci][sp->scancount * vsamp + ypos]; + JDIMENSION nclump; #if defined(JPEG_LIB_MK1_OR_12BIT) - JSAMPLE *outptr = (JSAMPLE *)tmpbuf + clumpoffset; + TIFF_JSAMPLE *outptr = (TIFF_JSAMPLE *)tmpbuf + clumpoffset; #else - JSAMPLE *outptr = (JSAMPLE *)buf + clumpoffset; - if (cc < - (tmsize_t)(clumpoffset + - (tmsize_t)samples_per_clump * (clumps_per_line - 1) + - hsamp)) { - TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", - "application buffer not large enough for all data, " - "possible subsampling issue"); - goto error; - } + TIFF_JSAMPLE *outptr = (TIFF_JSAMPLE *)buf + clumpoffset; + if (cc < (tmsize_t)(clumpoffset + + (tmsize_t)samples_per_clump * + (clumps_per_line - 1) + + hsamp)) + { + TIFFErrorExtR( + tif, "JPEGDecodeRaw", + "application buffer not large enough for all data, " + "possible subsampling issue"); + goto error; + } #endif - if (hsamp == 1) { - /* fast path for at least Cb and Cr */ - for (nclump = clumps_per_line; nclump-- > 0;) { - outptr[0] = *inptr++; - outptr += samples_per_clump; + if (hsamp == 1) + { + /* fast path for at least Cb and Cr */ + for (nclump = clumps_per_line; nclump-- > 0;) + { + outptr[0] = *inptr++; + outptr += samples_per_clump; + } + } + else + { + int xpos; + + /* general case */ + for (nclump = clumps_per_line; nclump-- > 0;) + { + for (xpos = 0; xpos < hsamp; xpos++) + outptr[xpos] = *inptr++; + outptr += samples_per_clump; + } + } + clumpoffset += hsamp; + } } - } else { - int xpos; - - /* general case */ - for (nclump = clumps_per_line; nclump-- > 0;) { - for (xpos = 0; xpos < hsamp; xpos++) - outptr[xpos] = *inptr++; - outptr += samples_per_clump; - } - } - clumpoffset += hsamp; - } - } #if defined(JPEG_LIB_MK1_OR_12BIT) - { - if (sp->cinfo.d.data_precision == 8) { - int i = 0; - int len = sp->cinfo.d.output_width * sp->cinfo.d.num_components; - for (i = 0; i < len; i++) { - ((unsigned char *)buf)[i] = tmpbuf[i] & 0xff; - } - } else { /* 12-bit */ - int value_pairs = - (sp->cinfo.d.output_width * sp->cinfo.d.num_components) / 2; - int iPair; - for (iPair = 0; iPair < value_pairs; iPair++) { - unsigned char *out_ptr = ((unsigned char *)buf) + iPair * 3; - JSAMPLE *in_ptr = (JSAMPLE *)(tmpbuf + iPair * 2); - out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4); - out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4) | - ((in_ptr[1] & 0xf00) >> 8)); - out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0)); - } - } - } + { + if (sp->cinfo.d.data_precision == 8) + { + int i = 0; + int len = + sp->cinfo.d.output_width * sp->cinfo.d.num_components; + for (i = 0; i < len; i++) + { + ((unsigned char *)buf)[i] = tmpbuf[i] & 0xff; + } + } + else + { /* 12-bit */ + int value_pairs = (sp->cinfo.d.output_width * + sp->cinfo.d.num_components) / + 2; + int iPair; + for (iPair = 0; iPair < value_pairs; iPair++) + { + unsigned char *out_ptr = + ((unsigned char *)buf) + iPair * 3; + JSAMPLE *in_ptr = (JSAMPLE *)(tmpbuf + iPair * 2); + out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4); + out_ptr[1] = + (unsigned char)(((in_ptr[0] & 0xf) << 4) | + ((in_ptr[1] & 0xf00) >> 8)); + out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0)); + } + } + } #endif - sp->scancount++; - tif->tif_row += sp->v_sampling; + sp->scancount++; + tif->tif_row += sp->v_sampling; - buf += sp->bytesperline; - cc -= sp->bytesperline; + buf += sp->bytesperline; + cc -= sp->bytesperline; - nrows -= sp->v_sampling; - } while (nrows > 0); + nrows -= sp->v_sampling; + } while (nrows > 0); #if defined(JPEG_LIB_MK1_OR_12BIT) - _TIFFfree(tmpbuf); + _TIFFfreeExt(tif, tmpbuf); #endif - } + } - /* Close down the decompressor if done. */ - return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || - TIFFjpeg_finish_decompress(sp); + /* Close down the decompressor if done. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height || + TIFFjpeg_finish_decompress(sp); error: #if defined(JPEG_LIB_MK1_OR_12BIT) - _TIFFfree(tmpbuf); + _TIFFfreeExt(tif, tmpbuf); #endif - return 0; + return 0; } /* * JPEG Encoding. */ -static void unsuppress_quant_table(JPEGState *sp, int tblno) { - JQUANT_TBL *qtbl; +static void unsuppress_quant_table(JPEGState *sp, int tblno) +{ + JQUANT_TBL *qtbl; - if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) - qtbl->sent_table = FALSE; + if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) + qtbl->sent_table = FALSE; } -static void suppress_quant_table(JPEGState *sp, int tblno) { - JQUANT_TBL *qtbl; +static void suppress_quant_table(JPEGState *sp, int tblno) +{ + JQUANT_TBL *qtbl; - if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) - qtbl->sent_table = TRUE; + if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) + qtbl->sent_table = TRUE; } -static void unsuppress_huff_table(JPEGState *sp, int tblno) { - JHUFF_TBL *htbl; +static void unsuppress_huff_table(JPEGState *sp, int tblno) +{ + JHUFF_TBL *htbl; - if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) - htbl->sent_table = FALSE; - if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) - htbl->sent_table = FALSE; + if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = FALSE; + if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = FALSE; } -static void suppress_huff_table(JPEGState *sp, int tblno) { - JHUFF_TBL *htbl; +static void suppress_huff_table(JPEGState *sp, int tblno) +{ + JHUFF_TBL *htbl; - if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) - htbl->sent_table = TRUE; - if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) - htbl->sent_table = TRUE; + if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = TRUE; + if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = TRUE; } -static int prepare_JPEGTables(TIFF *tif) { - JPEGState *sp = JState(tif); +static int prepare_JPEGTables(TIFF *tif) +{ + JPEGState *sp = JState(tif); - /* Initialize quant tables for current quality setting */ - if (!TIFFjpeg_set_quality(sp, sp->otherSettings.jpegquality, FALSE)) - return (0); - /* Mark only the tables we want for output */ - /* NB: chrominance tables are currently used only with YCbCr */ - if (!TIFFjpeg_suppress_tables(sp, TRUE)) - return (0); - if (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_QUANT) { - unsuppress_quant_table(sp, 0); - if (sp->photometric == PHOTOMETRIC_YCBCR) - unsuppress_quant_table(sp, 1); - } - if (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_HUFF) { - unsuppress_huff_table(sp, 0); - if (sp->photometric == PHOTOMETRIC_YCBCR) - unsuppress_huff_table(sp, 1); - } - /* Direct libjpeg output into otherSettings.jpegtables */ - if (!TIFFjpeg_tables_dest(sp, tif)) - return (0); - /* Emit tables-only datastream */ - if (!TIFFjpeg_write_tables(sp)) - return (0); + /* Initialize quant tables for current quality setting */ + if (!TIFFjpeg_set_quality(sp, sp->otherSettings.jpegquality, FALSE)) + return (0); + /* Mark only the tables we want for output */ + /* NB: chrominance tables are currently used only with YCbCr */ + if (!TIFFjpeg_suppress_tables(sp, TRUE)) + return (0); + if (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_QUANT) + { + unsuppress_quant_table(sp, 0); + if (sp->photometric == PHOTOMETRIC_YCBCR) + unsuppress_quant_table(sp, 1); + } + if (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_HUFF) + { + unsuppress_huff_table(sp, 0); + if (sp->photometric == PHOTOMETRIC_YCBCR) + unsuppress_huff_table(sp, 1); + } + /* Direct libjpeg output into otherSettings.jpegtables */ + if (!TIFFjpeg_tables_dest(sp, tif)) + return (0); + /* Emit tables-only datastream */ + if (!TIFFjpeg_write_tables(sp)) + return (0); - return (1); + return (1); } #if defined(JPEG_LIB_VERSION_MAJOR) && \ @@ -1653,703 +1892,809 @@ static int prepare_JPEGTables(TIFF *tif) { /* This is a modified version of std_huff_tables() from jcparam.c * in libjpeg-9d because it no longer initializes default Huffman * tables in jpeg_set_defaults(). */ -static void TIFF_std_huff_tables(j_compress_ptr cinfo) { - - if (cinfo->dc_huff_tbl_ptrs[0] == NULL) { - (void)jpeg_std_huff_table((j_common_ptr)cinfo, TRUE, 0); - } - if (cinfo->ac_huff_tbl_ptrs[0] == NULL) { - (void)jpeg_std_huff_table((j_common_ptr)cinfo, FALSE, 0); - } - if (cinfo->dc_huff_tbl_ptrs[1] == NULL) { - (void)jpeg_std_huff_table((j_common_ptr)cinfo, TRUE, 1); - } - if (cinfo->ac_huff_tbl_ptrs[1] == NULL) { - (void)jpeg_std_huff_table((j_common_ptr)cinfo, FALSE, 1); - } +static void TIFF_std_huff_tables(j_compress_ptr cinfo) +{ + + if (cinfo->dc_huff_tbl_ptrs[0] == NULL) + { + (void)jpeg_std_huff_table((j_common_ptr)cinfo, TRUE, 0); + } + if (cinfo->ac_huff_tbl_ptrs[0] == NULL) + { + (void)jpeg_std_huff_table((j_common_ptr)cinfo, FALSE, 0); + } + if (cinfo->dc_huff_tbl_ptrs[1] == NULL) + { + (void)jpeg_std_huff_table((j_common_ptr)cinfo, TRUE, 1); + } + if (cinfo->ac_huff_tbl_ptrs[1] == NULL) + { + (void)jpeg_std_huff_table((j_common_ptr)cinfo, FALSE, 1); + } } #endif -static int JPEGSetupEncode(TIFF *tif) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; - static const char module[] = "JPEGSetupEncode"; +static int JPEGSetupEncode(TIFF *tif) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGSetupEncode"; #if defined(JPEG_DUAL_MODE_8_12) && !defined(FROM_TIF_JPEG_12) - if (tif->tif_dir.td_bitspersample == 12) { - /* We pass a pointer to a copy of otherSettings, since */ - /* TIFFReInitJPEG_12() will clear sp */ - JPEGOtherSettings savedOtherSettings = sp->otherSettings; - return TIFFReInitJPEG_12(tif, &savedOtherSettings, COMPRESSION_JPEG, 1); - } + if (tif->tif_dir.td_bitspersample == 12) + { + /* We pass a pointer to a copy of otherSettings, since */ + /* TIFFReInitJPEG_12() will clear sp */ + JPEGOtherSettings savedOtherSettings = sp->otherSettings; + return TIFFReInitJPEG_12(tif, &savedOtherSettings, COMPRESSION_JPEG, 1); + } #endif - JPEGInitializeLibJPEG(tif, FALSE); - - assert(sp != NULL); - assert(!sp->cinfo.comm.is_decompressor); - - sp->photometric = td->td_photometric; - - /* - * Initialize all JPEG parameters to default values. - * Note that jpeg_set_defaults needs legal values for - * in_color_space and input_components. - */ - if (td->td_planarconfig == PLANARCONFIG_CONTIG) { - sp->cinfo.c.input_components = td->td_samplesperpixel; - if (sp->photometric == PHOTOMETRIC_YCBCR) { - if (sp->otherSettings.jpegcolormode == JPEGCOLORMODE_RGB) { - sp->cinfo.c.in_color_space = JCS_RGB; - } else { - sp->cinfo.c.in_color_space = JCS_YCbCr; - } - } else { - if ((td->td_photometric == PHOTOMETRIC_MINISWHITE || - td->td_photometric == PHOTOMETRIC_MINISBLACK) && - td->td_samplesperpixel == 1) - sp->cinfo.c.in_color_space = JCS_GRAYSCALE; - else if (td->td_photometric == PHOTOMETRIC_RGB && - td->td_samplesperpixel == 3) - sp->cinfo.c.in_color_space = JCS_RGB; - else if (td->td_photometric == PHOTOMETRIC_SEPARATED && - td->td_samplesperpixel == 4) - sp->cinfo.c.in_color_space = JCS_CMYK; - else + JPEGInitializeLibJPEG(tif, FALSE); + + assert(sp != NULL); + assert(!sp->cinfo.comm.is_decompressor); + + sp->photometric = td->td_photometric; + + /* + * Initialize all JPEG parameters to default values. + * Note that jpeg_set_defaults needs legal values for + * in_color_space and input_components. + */ + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + { + sp->cinfo.c.input_components = td->td_samplesperpixel; + if (sp->photometric == PHOTOMETRIC_YCBCR) + { + if (sp->otherSettings.jpegcolormode == JPEGCOLORMODE_RGB) + { + sp->cinfo.c.in_color_space = JCS_RGB; + } + else + { + sp->cinfo.c.in_color_space = JCS_YCbCr; + } + } + else + { + if ((td->td_photometric == PHOTOMETRIC_MINISWHITE || + td->td_photometric == PHOTOMETRIC_MINISBLACK) && + td->td_samplesperpixel == 1) + sp->cinfo.c.in_color_space = JCS_GRAYSCALE; + else if (td->td_photometric == PHOTOMETRIC_RGB && + td->td_samplesperpixel == 3) + sp->cinfo.c.in_color_space = JCS_RGB; + else if (td->td_photometric == PHOTOMETRIC_SEPARATED && + td->td_samplesperpixel == 4) + sp->cinfo.c.in_color_space = JCS_CMYK; + else + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + } + } + else + { + sp->cinfo.c.input_components = 1; sp->cinfo.c.in_color_space = JCS_UNKNOWN; } - } else { - sp->cinfo.c.input_components = 1; - sp->cinfo.c.in_color_space = JCS_UNKNOWN; - } - if (!TIFFjpeg_set_defaults(sp)) - return (0); - - /* mozjpeg by default enables progressive JPEG, which is illegal in - * JPEG-in-TIFF */ - /* So explicitly disable it. */ - if (sp->cinfo.c.num_scans != 0 && - (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_HUFF) != 0) { - /* it has been found that mozjpeg could create corrupt strips/tiles */ - /* in non optimize_coding mode. */ - TIFFWarningExt(tif->tif_clientdata, module, - "mozjpeg library likely detected. Disable emission of " - "Huffman tables in JpegTables tag, and use optimize_coding " - "to avoid potential issues"); - sp->otherSettings.jpegtablesmode &= ~JPEGTABLESMODE_HUFF; - } - sp->cinfo.c.num_scans = 0; - sp->cinfo.c.scan_info = NULL; - - /* Set per-file parameters */ - switch (sp->photometric) { - case PHOTOMETRIC_YCBCR: - sp->h_sampling = td->td_ycbcrsubsampling[0]; - sp->v_sampling = td->td_ycbcrsubsampling[1]; - if (sp->h_sampling == 0 || sp->v_sampling == 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Invalig horizontal/vertical sampling value"); - return (0); - } - if (td->td_bitspersample > 16) { - TIFFErrorExt(tif->tif_clientdata, module, - "BitsPerSample %" PRIu16 " not allowed for JPEG", - td->td_bitspersample); - return (0); + if (!TIFFjpeg_set_defaults(sp)) + return (0); + + /* mozjpeg by default enables progressive JPEG, which is illegal in + * JPEG-in-TIFF */ + /* So explicitly disable it. */ + if (sp->cinfo.c.num_scans != 0 && + (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_HUFF) != 0) + { + /* it has been found that mozjpeg could create corrupt strips/tiles */ + /* in non optimize_coding mode. */ + TIFFWarningExtR( + tif, module, + "mozjpeg library likely detected. Disable emission of " + "Huffman tables in JpegTables tag, and use optimize_coding " + "to avoid potential issues"); + sp->otherSettings.jpegtablesmode &= ~JPEGTABLESMODE_HUFF; } + sp->cinfo.c.num_scans = 0; + sp->cinfo.c.scan_info = NULL; - /* - * A ReferenceBlackWhite field *must* be present since the - * default value is inappropriate for YCbCr. Fill in the - * proper value if application didn't set it. - */ + /* Set per-file parameters */ + switch (sp->photometric) { - float *ref; - if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, &ref)) { - float refbw[6]; - long top = 1L << td->td_bitspersample; - refbw[0] = 0; - refbw[1] = (float)(top - 1L); - refbw[2] = (float)(top >> 1); - refbw[3] = refbw[1]; - refbw[4] = refbw[2]; - refbw[5] = refbw[1]; - TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, refbw); - } - } - break; - case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */ - case PHOTOMETRIC_MASK: - TIFFErrorExt(tif->tif_clientdata, module, - "PhotometricInterpretation %" PRIu16 " not allowed for JPEG", - sp->photometric); - return (0); - default: - /* TIFF 6.0 forbids subsampling of all other color spaces */ - sp->h_sampling = 1; - sp->v_sampling = 1; - break; - } - - /* Verify miscellaneous parameters */ - - /* - * This would need work if libtiff ever supports different - * depths for different components, or if libjpeg ever supports - * run-time selection of depth. Neither is imminent. - */ + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + if (sp->h_sampling == 0 || sp->v_sampling == 0) + { + TIFFErrorExtR(tif, module, + "Invalig horizontal/vertical sampling value"); + return (0); + } + if (td->td_bitspersample > 16) + { + TIFFErrorExtR(tif, module, + "BitsPerSample %" PRIu16 " not allowed for JPEG", + td->td_bitspersample); + return (0); + } + + /* + * A ReferenceBlackWhite field *must* be present since the + * default value is inappropriate for YCbCr. Fill in the + * proper value if application didn't set it. + */ + { + float *ref; + if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, &ref)) + { + float refbw[6]; + long top = 1L << td->td_bitspersample; + refbw[0] = 0; + refbw[1] = (float)(top - 1L); + refbw[2] = (float)(top >> 1); + refbw[3] = refbw[1]; + refbw[4] = refbw[2]; + refbw[5] = refbw[1]; + TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, refbw); + } + } + break; + case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */ + case PHOTOMETRIC_MASK: + TIFFErrorExtR(tif, module, + "PhotometricInterpretation %" PRIu16 + " not allowed for JPEG", + sp->photometric); + return (0); + default: + /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = 1; + sp->v_sampling = 1; + break; + } + + /* Verify miscellaneous parameters */ + + /* + * This would need work if libtiff ever supports different + * depths for different components, or if libjpeg ever supports + * run-time selection of depth. Neither is imminent. + */ #ifdef JPEG_LIB_MK1 - /* BITS_IN_JSAMPLE now permits 8 and 12 --- dgilbert */ - if (td->td_bitspersample != 8 && td->td_bitspersample != 12) + /* BITS_IN_JSAMPLE now permits 8 and 12 --- dgilbert */ + if (td->td_bitspersample != 8 && td->td_bitspersample != 12) #else - if (td->td_bitspersample != BITS_IN_JSAMPLE) + if (td->td_bitspersample != BITS_IN_JSAMPLE) #endif - { - TIFFErrorExt(tif->tif_clientdata, module, - "BitsPerSample %" PRIu16 " not allowed for JPEG", - td->td_bitspersample); - return (0); - } - sp->cinfo.c.data_precision = td->td_bitspersample; + { + TIFFErrorExtR(tif, module, + "BitsPerSample %" PRIu16 " not allowed for JPEG", + td->td_bitspersample); + return (0); + } + sp->cinfo.c.data_precision = td->td_bitspersample; #ifdef JPEG_LIB_MK1 - sp->cinfo.c.bits_in_jsample = td->td_bitspersample; + sp->cinfo.c.bits_in_jsample = td->td_bitspersample; #endif - if (isTiled(tif)) { - if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "JPEG tile height must be multiple of %" PRIu32, - (uint32_t)(sp->v_sampling * DCTSIZE)); - return (0); - } - if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "JPEG tile width must be multiple of %" PRIu32, - (uint32_t)(sp->h_sampling * DCTSIZE)); - return (0); - } - } else { - if (td->td_rowsperstrip < td->td_imagelength && - (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "RowsPerStrip must be multiple of %" PRIu32 " for JPEG", - (uint32_t)(sp->v_sampling * DCTSIZE)); - return (0); - } - } - - /* Create a JPEGTables field if appropriate */ - if (sp->otherSettings.jpegtablesmode & - (JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF)) { - if (sp->otherSettings.jpegtables == NULL || - memcmp(sp->otherSettings.jpegtables, "\0\0\0\0\0\0\0\0\0", 8) == 0) { + if (isTiled(tif)) + { + if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) + { + TIFFErrorExtR(tif, module, + "JPEG tile height must be multiple of %" PRIu32, + (uint32_t)(sp->v_sampling * DCTSIZE)); + return (0); + } + if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) + { + TIFFErrorExtR(tif, module, + "JPEG tile width must be multiple of %" PRIu32, + (uint32_t)(sp->h_sampling * DCTSIZE)); + return (0); + } + } + else + { + if (td->td_rowsperstrip < td->td_imagelength && + (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) + { + TIFFErrorExtR(tif, module, + "RowsPerStrip must be multiple of %" PRIu32 + " for JPEG", + (uint32_t)(sp->v_sampling * DCTSIZE)); + return (0); + } + } + + /* Create a JPEGTables field if appropriate */ + if (sp->otherSettings.jpegtablesmode & + (JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF)) + { + if (sp->otherSettings.jpegtables == NULL || + memcmp(sp->otherSettings.jpegtables, "\0\0\0\0\0\0\0\0\0", 8) == 0) + { #if defined(JPEG_LIB_VERSION_MAJOR) && \ (JPEG_LIB_VERSION_MAJOR > 9 || \ (JPEG_LIB_VERSION_MAJOR == 9 && JPEG_LIB_VERSION_MINOR >= 4)) - if ((sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_HUFF) != 0 && - (sp->cinfo.c.dc_huff_tbl_ptrs[0] == NULL || - sp->cinfo.c.dc_huff_tbl_ptrs[1] == NULL || - sp->cinfo.c.ac_huff_tbl_ptrs[0] == NULL || - sp->cinfo.c.ac_huff_tbl_ptrs[1] == NULL)) { - /* libjpeg-9d no longer initializes default Huffman tables in */ - /* jpeg_set_defaults() */ - TIFF_std_huff_tables(&sp->cinfo.c); - } + if ((sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_HUFF) != 0 && + (sp->cinfo.c.dc_huff_tbl_ptrs[0] == NULL || + sp->cinfo.c.dc_huff_tbl_ptrs[1] == NULL || + sp->cinfo.c.ac_huff_tbl_ptrs[0] == NULL || + sp->cinfo.c.ac_huff_tbl_ptrs[1] == NULL)) + { + /* libjpeg-9d no longer initializes default Huffman tables in */ + /* jpeg_set_defaults() */ + TIFF_std_huff_tables(&sp->cinfo.c); + } #endif - if (!prepare_JPEGTables(tif)) - return (0); - /* Mark the field present */ - /* Can't use TIFFSetField since BEENWRITING is already set! */ - tif->tif_flags |= TIFF_DIRTYDIRECT; - TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + if (!prepare_JPEGTables(tif)) + return (0); + /* Mark the field present */ + /* Can't use TIFFSetField since BEENWRITING is already set! */ + tif->tif_flags |= TIFF_DIRTYDIRECT; + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + } + } + else + { + /* We do not support application-supplied JPEGTables, */ + /* so mark the field not present */ + TIFFClrFieldBit(tif, FIELD_JPEGTABLES); } - } else { - /* We do not support application-supplied JPEGTables, */ - /* so mark the field not present */ - TIFFClrFieldBit(tif, FIELD_JPEGTABLES); - } - /* Direct libjpeg output to libtiff's output buffer */ - TIFFjpeg_data_dest(sp, tif); + /* Direct libjpeg output to libtiff's output buffer */ + TIFFjpeg_data_dest(sp, tif); - return (1); + return (1); } /* * Set encoding state at the start of a strip or tile. */ -static int JPEGPreEncode(TIFF *tif, uint16_t s) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; - static const char module[] = "JPEGPreEncode"; - uint32_t segment_width, segment_height; - int downsampled_input; - - assert(sp != NULL); - - if (sp->cinfo.comm.is_decompressor == 1) { - tif->tif_setupencode(tif); - } - - assert(!sp->cinfo.comm.is_decompressor); - /* - * Set encoding parameters for this strip/tile. - */ - if (isTiled(tif)) { - segment_width = td->td_tilewidth; - segment_height = td->td_tilelength; - sp->bytesperline = TIFFTileRowSize(tif); - } else { - segment_width = td->td_imagewidth; - segment_height = td->td_imagelength - tif->tif_row; - if (segment_height > td->td_rowsperstrip) - segment_height = td->td_rowsperstrip; - sp->bytesperline = TIFFScanlineSize(tif); - } - if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { - /* for PC 2, scale down the strip/tile size - * to match a downsampled component +static int JPEGPreEncode(TIFF *tif, uint16_t s) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGPreEncode"; + uint32_t segment_width, segment_height; + int downsampled_input; + + assert(sp != NULL); + + if (sp->cinfo.comm.is_decompressor == 1) + { + tif->tif_setupencode(tif); + } + + assert(!sp->cinfo.comm.is_decompressor); + /* + * Set encoding parameters for this strip/tile. */ - segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); - segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); - } - if (segment_width > 65535 || segment_height > 65535) { - TIFFErrorExt(tif->tif_clientdata, module, "Strip/tile too large for JPEG"); - return (0); - } - sp->cinfo.c.image_width = segment_width; - sp->cinfo.c.image_height = segment_height; - downsampled_input = FALSE; - if (td->td_planarconfig == PLANARCONFIG_CONTIG) { - sp->cinfo.c.input_components = td->td_samplesperpixel; - if (sp->photometric == PHOTOMETRIC_YCBCR) { - if (sp->otherSettings.jpegcolormode != JPEGCOLORMODE_RGB) { - if (sp->h_sampling != 1 || sp->v_sampling != 1) - downsampled_input = TRUE; - } - if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr)) + if (isTiled(tif)) + { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + sp->bytesperline = TIFFTileRowSize(tif); + } + else + { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFScanlineSize(tif); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) + { + /* for PC 2, scale down the strip/tile size + * to match a downsampled component + */ + segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); + segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); + } + if (segment_width > 65535 || segment_height > 65535) + { + TIFFErrorExtR(tif, module, "Strip/tile too large for JPEG"); return (0); - /* - * Set Y sampling factors; - * we assume jpeg_set_colorspace() set the rest to 1 - */ - sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; - sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; - } else { - if (!TIFFjpeg_set_colorspace(sp, sp->cinfo.c.in_color_space)) + } + sp->cinfo.c.image_width = segment_width; + sp->cinfo.c.image_height = segment_height; + downsampled_input = FALSE; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + { + sp->cinfo.c.input_components = td->td_samplesperpixel; + if (sp->photometric == PHOTOMETRIC_YCBCR) + { + if (sp->otherSettings.jpegcolormode != JPEGCOLORMODE_RGB) + { + if (sp->h_sampling != 1 || sp->v_sampling != 1) + downsampled_input = TRUE; + } + if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr)) + return (0); + /* + * Set Y sampling factors; + * we assume jpeg_set_colorspace() set the rest to 1 + */ + sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; + sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; + } + else + { + if (!TIFFjpeg_set_colorspace(sp, sp->cinfo.c.in_color_space)) + return (0); + /* jpeg_set_colorspace set all sampling factors to 1 */ + } + } + else + { + if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN)) + return (0); + sp->cinfo.c.comp_info[0].component_id = s; + /* jpeg_set_colorspace() set sampling factors to 1 */ + if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) + { + sp->cinfo.c.comp_info[0].quant_tbl_no = 1; + sp->cinfo.c.comp_info[0].dc_tbl_no = 1; + sp->cinfo.c.comp_info[0].ac_tbl_no = 1; + } + } + /* ensure libjpeg won't write any extraneous markers */ + sp->cinfo.c.write_JFIF_header = FALSE; + sp->cinfo.c.write_Adobe_marker = FALSE; + /* set up table handling correctly */ + /* calling TIFFjpeg_set_quality() causes quantization tables to be flagged + */ + /* as being to be emitted, which we don't want in the JPEGTABLESMODE_QUANT + */ + /* mode, so we must manually suppress them. However TIFFjpeg_set_quality() + */ + /* should really be called when dealing with files with directories with */ + /* mixed qualities. see http://trac.osgeo.org/gdal/ticket/3539 */ + if (!TIFFjpeg_set_quality(sp, sp->otherSettings.jpegquality, FALSE)) return (0); - /* jpeg_set_colorspace set all sampling factors to 1 */ - } - } else { - if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN)) - return (0); - sp->cinfo.c.comp_info[0].component_id = s; - /* jpeg_set_colorspace() set sampling factors to 1 */ - if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) { - sp->cinfo.c.comp_info[0].quant_tbl_no = 1; - sp->cinfo.c.comp_info[0].dc_tbl_no = 1; - sp->cinfo.c.comp_info[0].ac_tbl_no = 1; - } - } - /* ensure libjpeg won't write any extraneous markers */ - sp->cinfo.c.write_JFIF_header = FALSE; - sp->cinfo.c.write_Adobe_marker = FALSE; - /* set up table handling correctly */ - /* calling TIFFjpeg_set_quality() causes quantization tables to be flagged */ - /* as being to be emitted, which we don't want in the JPEGTABLESMODE_QUANT */ - /* mode, so we must manually suppress them. However TIFFjpeg_set_quality() */ - /* should really be called when dealing with files with directories with */ - /* mixed qualities. see http://trac.osgeo.org/gdal/ticket/3539 */ - if (!TIFFjpeg_set_quality(sp, sp->otherSettings.jpegquality, FALSE)) - return (0); - if (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_QUANT) { - suppress_quant_table(sp, 0); - suppress_quant_table(sp, 1); - } else { - unsuppress_quant_table(sp, 0); - unsuppress_quant_table(sp, 1); - } - if (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_HUFF) { - /* Explicit suppression is only needed if we did not go through the */ - /* prepare_JPEGTables() code path, which may be the case if updating */ - /* an existing file */ - suppress_huff_table(sp, 0); - suppress_huff_table(sp, 1); - sp->cinfo.c.optimize_coding = FALSE; - } else - sp->cinfo.c.optimize_coding = TRUE; - if (downsampled_input) { - /* Need to use raw-data interface to libjpeg */ - sp->cinfo.c.raw_data_in = TRUE; - tif->tif_encoderow = JPEGEncodeRaw; - tif->tif_encodestrip = JPEGEncodeRaw; - tif->tif_encodetile = JPEGEncodeRaw; - } else { - /* Use normal interface to libjpeg */ - sp->cinfo.c.raw_data_in = FALSE; - tif->tif_encoderow = JPEGEncode; - tif->tif_encodestrip = JPEGEncode; - tif->tif_encodetile = JPEGEncode; - } - /* Start JPEG compressor */ - if (!TIFFjpeg_start_compress(sp, FALSE)) - return (0); - /* Allocate downsampled-data buffers if needed */ - if (downsampled_input) { - if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info, - sp->cinfo.c.num_components)) - return (0); - } - sp->scancount = 0; + if (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_QUANT) + { + suppress_quant_table(sp, 0); + suppress_quant_table(sp, 1); + } + else + { + unsuppress_quant_table(sp, 0); + unsuppress_quant_table(sp, 1); + } + if (sp->otherSettings.jpegtablesmode & JPEGTABLESMODE_HUFF) + { + /* Explicit suppression is only needed if we did not go through the */ + /* prepare_JPEGTables() code path, which may be the case if updating */ + /* an existing file */ + suppress_huff_table(sp, 0); + suppress_huff_table(sp, 1); + sp->cinfo.c.optimize_coding = FALSE; + } + else + sp->cinfo.c.optimize_coding = TRUE; + if (downsampled_input) + { + /* Need to use raw-data interface to libjpeg */ + sp->cinfo.c.raw_data_in = TRUE; + tif->tif_encoderow = JPEGEncodeRaw; + tif->tif_encodestrip = JPEGEncodeRaw; + tif->tif_encodetile = JPEGEncodeRaw; + } + else + { + /* Use normal interface to libjpeg */ + sp->cinfo.c.raw_data_in = FALSE; + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; + } + /* Start JPEG compressor */ + if (!TIFFjpeg_start_compress(sp, FALSE)) + return (0); + /* Allocate downsampled-data buffers if needed */ + if (downsampled_input) + { + if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info, + sp->cinfo.c.num_components)) + return (0); + } + sp->scancount = 0; - return (1); + return (1); } /* * Encode a chunk of pixels. * "Standard" case: incoming data is not downsampled. */ -static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) { - JPEGState *sp = JState(tif); - tmsize_t nrows; - JSAMPROW bufptr[1]; - short *line16 = NULL; - int line16_count = 0; - - (void)s; - assert(sp != NULL); - /* data is expected to be supplied in multiples of a scanline */ - nrows = cc / sp->bytesperline; - if (cc % sp->bytesperline) - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "fractional scanline discarded"); - - /* The last strip will be limited to image size */ - if (!isTiled(tif) && tif->tif_row + nrows > tif->tif_dir.td_imagelength) - nrows = tif->tif_dir.td_imagelength - tif->tif_row; - - if (sp->cinfo.c.data_precision == 12) { - line16_count = (int)((sp->bytesperline * 2) / 3); - line16 = (short *)_TIFFmalloc(sizeof(short) * line16_count); - if (!line16) { - TIFFErrorExt(tif->tif_clientdata, "JPEGEncode", - "Failed to allocate memory"); +static int JPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) +{ + JPEGState *sp = JState(tif); + tmsize_t nrows; + TIFF_JSAMPROW bufptr[1]; + short *line16 = NULL; + int line16_count = 0; + + (void)s; + assert(sp != NULL); + /* data is expected to be supplied in multiples of a scanline */ + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarningExtR(tif, tif->tif_name, "fractional scanline discarded"); + + /* The last strip will be limited to image size */ + if (!isTiled(tif) && tif->tif_row + nrows > tif->tif_dir.td_imagelength) + nrows = tif->tif_dir.td_imagelength - tif->tif_row; + + if (sp->cinfo.c.data_precision == 12) + { + line16_count = (int)((sp->bytesperline * 2) / 3); + line16 = (short *)_TIFFmallocExt(tif, sizeof(short) * line16_count); + if (!line16) + { + TIFFErrorExtR(tif, "JPEGEncode", "Failed to allocate memory"); - return 0; + return 0; + } } - } - while (nrows-- > 0) { + while (nrows-- > 0) + { - if (sp->cinfo.c.data_precision == 12) { + if (sp->cinfo.c.data_precision == 12) + { - int value_pairs = line16_count / 2; - int iPair; + int value_pairs = line16_count / 2; + int iPair; - bufptr[0] = (JSAMPROW)line16; + bufptr[0] = (TIFF_JSAMPROW)line16; - for (iPair = 0; iPair < value_pairs; iPair++) { - unsigned char *in_ptr = ((unsigned char *)buf) + iPair * 3; - JSAMPLE *out_ptr = (JSAMPLE *)(line16 + iPair * 2); + for (iPair = 0; iPair < value_pairs; iPair++) + { + unsigned char *in_ptr = ((unsigned char *)buf) + iPair * 3; + TIFF_JSAMPLE *out_ptr = (TIFF_JSAMPLE *)(line16 + iPair * 2); - out_ptr[0] = (in_ptr[0] << 4) | ((in_ptr[1] & 0xf0) >> 4); - out_ptr[1] = ((in_ptr[1] & 0x0f) << 8) | in_ptr[2]; - } - } else { - bufptr[0] = (JSAMPROW)buf; + out_ptr[0] = (in_ptr[0] << 4) | ((in_ptr[1] & 0xf0) >> 4); + out_ptr[1] = ((in_ptr[1] & 0x0f) << 8) | in_ptr[2]; + } + } + else + { + bufptr[0] = (TIFF_JSAMPROW)buf; + } + if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1) + return (0); + if (nrows > 0) + tif->tif_row++; + buf += sp->bytesperline; } - if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1) - return (0); - if (nrows > 0) - tif->tif_row++; - buf += sp->bytesperline; - } - if (sp->cinfo.c.data_precision == 12) { - _TIFFfree(line16); - } + if (sp->cinfo.c.data_precision == 12) + { + _TIFFfreeExt(tif, line16); + } - return (1); + return (1); } /* * Encode a chunk of pixels. * Incoming data is expected to be downsampled per sampling factors. */ -static int JPEGEncodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) { - JPEGState *sp = JState(tif); - JSAMPLE *inptr; - JSAMPLE *outptr; - tmsize_t nrows; - JDIMENSION clumps_per_line, nclump; - int clumpoffset, ci, xpos, ypos; - jpeg_component_info *compptr; - int samples_per_clump = sp->samplesperclump; - tmsize_t bytesperclumpline; - - (void)s; - assert(sp != NULL); - /* data is expected to be supplied in multiples of a clumpline */ - /* a clumpline is equivalent to v_sampling desubsampled scanlines */ - /* TODO: the following calculation of bytesperclumpline, should substitute - * calculation of sp->bytesperline, except that it is per v_sampling lines */ - bytesperclumpline = - ((((tmsize_t)sp->cinfo.c.image_width + sp->h_sampling - 1) / - sp->h_sampling) * - ((tmsize_t)sp->h_sampling * sp->v_sampling + 2) * - sp->cinfo.c.data_precision + - 7) / - 8; - - nrows = (cc / bytesperclumpline) * sp->v_sampling; - if (cc % bytesperclumpline) - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "fractional scanline discarded"); - - /* Cb,Cr both have sampling factors 1, so this is correct */ - clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width; - - while (nrows > 0) { - /* - * Fastest way to separate the data is to make one pass - * over the scanline for each row of each component. +static int JPEGEncodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) +{ + JPEGState *sp = JState(tif); + TIFF_JSAMPLE *inptr; + TIFF_JSAMPLE *outptr; + tmsize_t nrows; + JDIMENSION clumps_per_line, nclump; + int clumpoffset, ci, xpos, ypos; + jpeg_component_info *compptr; + int samples_per_clump = sp->samplesperclump; + tmsize_t bytesperclumpline; + + (void)s; + assert(sp != NULL); + /* data is expected to be supplied in multiples of a clumpline */ + /* a clumpline is equivalent to v_sampling desubsampled scanlines */ + /* TODO: the following calculation of bytesperclumpline, should substitute + * calculation of sp->bytesperline, except that it is per v_sampling lines */ - clumpoffset = 0; /* first sample in clump */ - for (ci = 0, compptr = sp->cinfo.c.comp_info; - ci < sp->cinfo.c.num_components; ci++, compptr++) { - int hsamp = compptr->h_samp_factor; - int vsamp = compptr->v_samp_factor; - int padding = - (int)(compptr->width_in_blocks * DCTSIZE - clumps_per_line * hsamp); - for (ypos = 0; ypos < vsamp; ypos++) { - inptr = ((JSAMPLE *)buf) + clumpoffset; - outptr = sp->ds_buffer[ci][sp->scancount * vsamp + ypos]; - if (hsamp == 1) { - /* fast path for at least Cb and Cr */ - for (nclump = clumps_per_line; nclump-- > 0;) { - *outptr++ = inptr[0]; - inptr += samples_per_clump; - } - } else { - /* general case */ - for (nclump = clumps_per_line; nclump-- > 0;) { - for (xpos = 0; xpos < hsamp; xpos++) - *outptr++ = inptr[xpos]; - inptr += samples_per_clump; - } + bytesperclumpline = + ((((tmsize_t)sp->cinfo.c.image_width + sp->h_sampling - 1) / + sp->h_sampling) * + ((tmsize_t)sp->h_sampling * sp->v_sampling + 2) * + sp->cinfo.c.data_precision + + 7) / + 8; + + nrows = (cc / bytesperclumpline) * sp->v_sampling; + if (cc % bytesperclumpline) + TIFFWarningExtR(tif, tif->tif_name, "fractional scanline discarded"); + + /* Cb,Cr both have sampling factors 1, so this is correct */ + clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width; + + while (nrows > 0) + { + /* + * Fastest way to separate the data is to make one pass + * over the scanline for each row of each component. + */ + clumpoffset = 0; /* first sample in clump */ + for (ci = 0, compptr = sp->cinfo.c.comp_info; + ci < sp->cinfo.c.num_components; ci++, compptr++) + { + int hsamp = compptr->h_samp_factor; + int vsamp = compptr->v_samp_factor; + int padding = (int)(compptr->width_in_blocks * DCTSIZE - + clumps_per_line * hsamp); + for (ypos = 0; ypos < vsamp; ypos++) + { + inptr = ((TIFF_JSAMPLE *)buf) + clumpoffset; + outptr = sp->ds_buffer[ci][sp->scancount * vsamp + ypos]; + if (hsamp == 1) + { + /* fast path for at least Cb and Cr */ + for (nclump = clumps_per_line; nclump-- > 0;) + { + *outptr++ = inptr[0]; + inptr += samples_per_clump; + } + } + else + { + /* general case */ + for (nclump = clumps_per_line; nclump-- > 0;) + { + for (xpos = 0; xpos < hsamp; xpos++) + *outptr++ = inptr[xpos]; + inptr += samples_per_clump; + } + } + /* pad each scanline as needed */ + for (xpos = 0; xpos < padding; xpos++) + { + *outptr = outptr[-1]; + outptr++; + } + clumpoffset += hsamp; + } } - /* pad each scanline as needed */ - for (xpos = 0; xpos < padding; xpos++) { - *outptr = outptr[-1]; - outptr++; + sp->scancount++; + if (sp->scancount >= DCTSIZE) + { + int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + sp->scancount = 0; } - clumpoffset += hsamp; - } - } - sp->scancount++; - if (sp->scancount >= DCTSIZE) { - int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; - if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) - return (0); - sp->scancount = 0; + tif->tif_row += sp->v_sampling; + buf += bytesperclumpline; + nrows -= sp->v_sampling; } - tif->tif_row += sp->v_sampling; - buf += bytesperclumpline; - nrows -= sp->v_sampling; - } - return (1); + return (1); } /* * Finish up at the end of a strip or tile. */ -static int JPEGPostEncode(TIFF *tif) { - JPEGState *sp = JState(tif); +static int JPEGPostEncode(TIFF *tif) +{ + JPEGState *sp = JState(tif); + + if (sp->scancount > 0) + { + /* + * Need to emit a partial bufferload of downsampled data. + * Pad the data vertically. + */ + int ci, ypos, n; + jpeg_component_info *compptr; + + for (ci = 0, compptr = sp->cinfo.c.comp_info; + ci < sp->cinfo.c.num_components; ci++, compptr++) + { + int vsamp = compptr->v_samp_factor; + tmsize_t row_width = + compptr->width_in_blocks * DCTSIZE * sizeof(JSAMPLE); + for (ypos = sp->scancount * vsamp; ypos < DCTSIZE * vsamp; ypos++) + { + _TIFFmemcpy((void *)sp->ds_buffer[ci][ypos], + (void *)sp->ds_buffer[ci][ypos - 1], row_width); + } + } + n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + } + + return (TIFFjpeg_finish_compress(JState(tif))); +} + +static void JPEGCleanup(TIFF *tif) +{ + JPEGState *sp = JState(tif); + + assert(sp != 0); + + tif->tif_tagmethods.vgetfield = sp->otherSettings.vgetparent; + tif->tif_tagmethods.vsetfield = sp->otherSettings.vsetparent; + tif->tif_tagmethods.printdir = sp->otherSettings.printdir; + if (sp->cinfo_initialized) + TIFFjpeg_destroy(sp); /* release libjpeg resources */ + if (sp->otherSettings.jpegtables) /* tag value */ + _TIFFfreeExt(tif, sp->otherSettings.jpegtables); + _TIFFfreeExt(tif, tif->tif_data); /* release local state */ + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +static void JPEGResetUpsampled(TIFF *tif) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; - if (sp->scancount > 0) { /* - * Need to emit a partial bufferload of downsampled data. - * Pad the data vertically. + * Mark whether returned data is up-sampled or not so TIFFStripSize + * and TIFFTileSize return values that reflect the true amount of + * data. */ - int ci, ypos, n; - jpeg_component_info *compptr; - - for (ci = 0, compptr = sp->cinfo.c.comp_info; - ci < sp->cinfo.c.num_components; ci++, compptr++) { - int vsamp = compptr->v_samp_factor; - tmsize_t row_width = compptr->width_in_blocks * DCTSIZE * sizeof(JSAMPLE); - for (ypos = sp->scancount * vsamp; ypos < DCTSIZE * vsamp; ypos++) { - _TIFFmemcpy((void *)sp->ds_buffer[ci][ypos], - (void *)sp->ds_buffer[ci][ypos - 1], row_width); - } - } - n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; - if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) - return (0); - } - - return (TIFFjpeg_finish_compress(JState(tif))); -} - -static void JPEGCleanup(TIFF *tif) { - JPEGState *sp = JState(tif); - - assert(sp != 0); - - tif->tif_tagmethods.vgetfield = sp->otherSettings.vgetparent; - tif->tif_tagmethods.vsetfield = sp->otherSettings.vsetparent; - tif->tif_tagmethods.printdir = sp->otherSettings.printdir; - if (sp->cinfo_initialized) - TIFFjpeg_destroy(sp); /* release libjpeg resources */ - if (sp->otherSettings.jpegtables) /* tag value */ - _TIFFfree(sp->otherSettings.jpegtables); - _TIFFfree(tif->tif_data); /* release local state */ - tif->tif_data = NULL; - - _TIFFSetDefaultCompressionState(tif); -} - -static void JPEGResetUpsampled(TIFF *tif) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; - - /* - * Mark whether returned data is up-sampled or not so TIFFStripSize - * and TIFFTileSize return values that reflect the true amount of - * data. - */ - tif->tif_flags &= ~TIFF_UPSAMPLED; - if (td->td_planarconfig == PLANARCONFIG_CONTIG) { - if (td->td_photometric == PHOTOMETRIC_YCBCR && - sp->otherSettings.jpegcolormode == JPEGCOLORMODE_RGB) { - tif->tif_flags |= TIFF_UPSAMPLED; - } else { + tif->tif_flags &= ~TIFF_UPSAMPLED; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + { + if (td->td_photometric == PHOTOMETRIC_YCBCR && + sp->otherSettings.jpegcolormode == JPEGCOLORMODE_RGB) + { + tif->tif_flags |= TIFF_UPSAMPLED; + } + else + { #ifdef notdef - if (td->td_ycbcrsubsampling[0] != 1 || td->td_ycbcrsubsampling[1] != 1) - ; /* XXX what about up-sampling? */ + if (td->td_ycbcrsubsampling[0] != 1 || + td->td_ycbcrsubsampling[1] != 1) + ; /* XXX what about up-sampling? */ #endif + } } - } - - /* - * Must recalculate cached tile size in case sampling state changed. - * Should we really be doing this now if image size isn't set? - */ - if (tif->tif_tilesize > 0) - tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1); - if (tif->tif_scanlinesize > 0) - tif->tif_scanlinesize = TIFFScanlineSize(tif); -} - -static int JPEGVSetField(TIFF *tif, uint32_t tag, va_list ap) { - JPEGState *sp = JState(tif); - const TIFFField *fip; - uint32_t v32; - - assert(sp != NULL); - - switch (tag) { - case TIFFTAG_JPEGTABLES: - v32 = (uint32_t)va_arg(ap, uint32_t); - if (v32 == 0) { - /* XXX */ - return (0); - } - _TIFFsetByteArray(&sp->otherSettings.jpegtables, va_arg(ap, void *), v32); - sp->otherSettings.jpegtables_length = v32; - TIFFSetFieldBit(tif, FIELD_JPEGTABLES); - break; - case TIFFTAG_JPEGQUALITY: - sp->otherSettings.jpegquality = (int)va_arg(ap, int); - return (1); /* pseudo tag */ - case TIFFTAG_JPEGCOLORMODE: - sp->otherSettings.jpegcolormode = (int)va_arg(ap, int); - JPEGResetUpsampled(tif); - return (1); /* pseudo tag */ - case TIFFTAG_PHOTOMETRIC: { - int ret_value = (*sp->otherSettings.vsetparent)(tif, tag, ap); - JPEGResetUpsampled(tif); - return ret_value; - } - case TIFFTAG_JPEGTABLESMODE: - sp->otherSettings.jpegtablesmode = (int)va_arg(ap, int); - return (1); /* pseudo tag */ - case TIFFTAG_YCBCRSUBSAMPLING: - /* mark the fact that we have a real ycbcrsubsampling! */ - sp->otherSettings.ycbcrsampling_fetched = 1; - /* should we be recomputing upsampling info here? */ - return (*sp->otherSettings.vsetparent)(tif, tag, ap); - default: - return (*sp->otherSettings.vsetparent)(tif, tag, ap); - } - - if ((fip = TIFFFieldWithTag(tif, tag)) != NULL) { - TIFFSetFieldBit(tif, fip->field_bit); - } else { - return (0); - } - - tif->tif_flags |= TIFF_DIRTYDIRECT; - return (1); -} - -static int JPEGVGetField(TIFF *tif, uint32_t tag, va_list ap) { - JPEGState *sp = JState(tif); - - assert(sp != NULL); - - switch (tag) { - case TIFFTAG_JPEGTABLES: - *va_arg(ap, uint32_t *) = sp->otherSettings.jpegtables_length; - *va_arg(ap, const void **) = sp->otherSettings.jpegtables; - break; - case TIFFTAG_JPEGQUALITY: - *va_arg(ap, int *) = sp->otherSettings.jpegquality; - break; - case TIFFTAG_JPEGCOLORMODE: - *va_arg(ap, int *) = sp->otherSettings.jpegcolormode; - break; - case TIFFTAG_JPEGTABLESMODE: - *va_arg(ap, int *) = sp->otherSettings.jpegtablesmode; - break; - default: - return (*sp->otherSettings.vgetparent)(tif, tag, ap); - } - return (1); -} - -static void JPEGPrintDir(TIFF *tif, FILE *fd, long flags) { - JPEGState *sp = JState(tif); - - assert(sp != NULL); - (void)flags; - - if (sp != NULL) { - if (TIFFFieldSet(tif, FIELD_JPEGTABLES)) - fprintf(fd, " JPEG Tables: (%" PRIu32 " bytes)\n", - sp->otherSettings.jpegtables_length); - if (sp->otherSettings.printdir) - (*sp->otherSettings.printdir)(tif, fd, flags); - } + + /* + * Must recalculate cached tile size in case sampling state changed. + * Should we really be doing this now if image size isn't set? + */ + if (tif->tif_tilesize > 0) + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1); + if (tif->tif_scanlinesize > 0) + tif->tif_scanlinesize = TIFFScanlineSize(tif); +} + +static int JPEGVSetField(TIFF *tif, uint32_t tag, va_list ap) +{ + JPEGState *sp = JState(tif); + const TIFFField *fip; + uint32_t v32; + + assert(sp != NULL); + + switch (tag) + { + case TIFFTAG_JPEGTABLES: + v32 = (uint32_t)va_arg(ap, uint32_t); + if (v32 == 0) + { + /* XXX */ + return (0); + } + _TIFFsetByteArrayExt(tif, &sp->otherSettings.jpegtables, + va_arg(ap, void *), v32); + sp->otherSettings.jpegtables_length = v32; + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + break; + case TIFFTAG_JPEGQUALITY: + sp->otherSettings.jpegquality = (int)va_arg(ap, int); + return (1); /* pseudo tag */ + case TIFFTAG_JPEGCOLORMODE: + sp->otherSettings.jpegcolormode = (int)va_arg(ap, int); + JPEGResetUpsampled(tif); + return (1); /* pseudo tag */ + case TIFFTAG_PHOTOMETRIC: + { + int ret_value = (*sp->otherSettings.vsetparent)(tif, tag, ap); + JPEGResetUpsampled(tif); + return ret_value; + } + case TIFFTAG_JPEGTABLESMODE: + sp->otherSettings.jpegtablesmode = (int)va_arg(ap, int); + return (1); /* pseudo tag */ + case TIFFTAG_YCBCRSUBSAMPLING: + /* mark the fact that we have a real ycbcrsubsampling! */ + sp->otherSettings.ycbcrsampling_fetched = 1; + /* should we be recomputing upsampling info here? */ + return (*sp->otherSettings.vsetparent)(tif, tag, ap); + default: + return (*sp->otherSettings.vsetparent)(tif, tag, ap); + } + + if ((fip = TIFFFieldWithTag(tif, tag)) != NULL) + { + TIFFSetFieldBit(tif, fip->field_bit); + } + else + { + return (0); + } + + tif->tif_flags |= TIFF_DIRTYDIRECT; + return (1); +} + +static int JPEGVGetField(TIFF *tif, uint32_t tag, va_list ap) +{ + JPEGState *sp = JState(tif); + + assert(sp != NULL); + + switch (tag) + { + case TIFFTAG_JPEGTABLES: + *va_arg(ap, uint32_t *) = sp->otherSettings.jpegtables_length; + *va_arg(ap, const void **) = sp->otherSettings.jpegtables; + break; + case TIFFTAG_JPEGQUALITY: + *va_arg(ap, int *) = sp->otherSettings.jpegquality; + break; + case TIFFTAG_JPEGCOLORMODE: + *va_arg(ap, int *) = sp->otherSettings.jpegcolormode; + break; + case TIFFTAG_JPEGTABLESMODE: + *va_arg(ap, int *) = sp->otherSettings.jpegtablesmode; + break; + default: + return (*sp->otherSettings.vgetparent)(tif, tag, ap); + } + return (1); } -static uint32_t JPEGDefaultStripSize(TIFF *tif, uint32_t s) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; +static void JPEGPrintDir(TIFF *tif, FILE *fd, long flags) +{ + JPEGState *sp = JState(tif); + + assert(sp != NULL); + (void)flags; - s = (*sp->otherSettings.defsparent)(tif, s); - if (s < td->td_imagelength) - s = TIFFroundup_32(s, td->td_ycbcrsubsampling[1] * DCTSIZE); - return (s); + if (sp != NULL) + { + if (TIFFFieldSet(tif, FIELD_JPEGTABLES)) + fprintf(fd, " JPEG Tables: (%" PRIu32 " bytes)\n", + sp->otherSettings.jpegtables_length); + if (sp->otherSettings.printdir) + (*sp->otherSettings.printdir)(tif, fd, flags); + } } -static void JPEGDefaultTileSize(TIFF *tif, uint32_t *tw, uint32_t *th) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; +static uint32_t JPEGDefaultStripSize(TIFF *tif, uint32_t s) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + + s = (*sp->otherSettings.defsparent)(tif, s); + if (s < td->td_imagelength) + s = TIFFroundup_32(s, td->td_ycbcrsubsampling[1] * DCTSIZE); + return (s); +} + +static void JPEGDefaultTileSize(TIFF *tif, uint32_t *tw, uint32_t *th) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; - (*sp->otherSettings.deftparent)(tif, tw, th); - *tw = TIFFroundup_32(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE); - *th = TIFFroundup_32(*th, td->td_ycbcrsubsampling[1] * DCTSIZE); + (*sp->otherSettings.deftparent)(tif, tw, th); + *tw = TIFFroundup_32(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE); + *th = TIFFroundup_32(*th, td->td_ycbcrsubsampling[1] * DCTSIZE); } /* @@ -2374,163 +2719,182 @@ static void JPEGDefaultTileSize(TIFF *tif, uint32_t *tw, uint32_t *th) { * NFW, Feb 3rd, 2003. */ -static int JPEGInitializeLibJPEG(TIFF *tif, int decompress) { - JPEGState *sp = JState(tif); +static int JPEGInitializeLibJPEG(TIFF *tif, int decompress) +{ + JPEGState *sp = JState(tif); - if (sp->cinfo_initialized) { - if (!decompress && sp->cinfo.comm.is_decompressor) - TIFFjpeg_destroy(sp); - else if (decompress && !sp->cinfo.comm.is_decompressor) - TIFFjpeg_destroy(sp); + if (sp->cinfo_initialized) + { + if (!decompress && sp->cinfo.comm.is_decompressor) + TIFFjpeg_destroy(sp); + else if (decompress && !sp->cinfo.comm.is_decompressor) + TIFFjpeg_destroy(sp); + else + return 1; + + sp->cinfo_initialized = 0; + } + + /* + * Initialize libjpeg. + */ + if (decompress) + { + if (!TIFFjpeg_create_decompress(sp)) + return (0); + } else - return 1; - - sp->cinfo_initialized = 0; - } - - /* - * Initialize libjpeg. - */ - if (decompress) { - if (!TIFFjpeg_create_decompress(sp)) - return (0); - } else { - if (!TIFFjpeg_create_compress(sp)) - return (0); + { + if (!TIFFjpeg_create_compress(sp)) + return (0); #ifndef TIFF_JPEG_MAX_MEMORY_TO_USE #define TIFF_JPEG_MAX_MEMORY_TO_USE (10 * 1024 * 1024) #endif - /* libjpeg turbo 1.5.2 honours max_memory_to_use, but has no backing */ - /* store implementation, so better not set max_memory_to_use ourselves. */ - /* See https://github.com/libjpeg-turbo/libjpeg-turbo/issues/162 */ - if (sp->cinfo.c.mem->max_memory_to_use > 0) { - /* This is to address bug related in ticket GDAL #1795. */ - if (getenv("JPEGMEM") == NULL) { - /* Increase the max memory usable. This helps when creating files */ - /* with "big" tile, without using libjpeg temporary files. */ - /* For example a 512x512 tile with 3 bands */ - /* requires 1.5 MB which is above libjpeg 1MB default */ - if (sp->cinfo.c.mem->max_memory_to_use < TIFF_JPEG_MAX_MEMORY_TO_USE) - sp->cinfo.c.mem->max_memory_to_use = TIFF_JPEG_MAX_MEMORY_TO_USE; - } + /* libjpeg turbo 1.5.2 honours max_memory_to_use, but has no backing */ + /* store implementation, so better not set max_memory_to_use ourselves. + */ + /* See https://github.com/libjpeg-turbo/libjpeg-turbo/issues/162 */ + if (sp->cinfo.c.mem->max_memory_to_use > 0) + { + /* This is to address bug related in ticket GDAL #1795. */ + if (getenv("JPEGMEM") == NULL) + { + /* Increase the max memory usable. This helps when creating + * files */ + /* with "big" tile, without using libjpeg temporary files. */ + /* For example a 512x512 tile with 3 bands */ + /* requires 1.5 MB which is above libjpeg 1MB default */ + if (sp->cinfo.c.mem->max_memory_to_use < + TIFF_JPEG_MAX_MEMORY_TO_USE) + sp->cinfo.c.mem->max_memory_to_use = + TIFF_JPEG_MAX_MEMORY_TO_USE; + } + } } - } - sp->cinfo_initialized = TRUE; + sp->cinfo_initialized = TRUE; - return 1; + return 1; } /* Common to tif_jpeg.c and tif_jpeg_12.c */ -static void TIFFInitJPEGCommon(TIFF *tif) { - JPEGState *sp; - - sp = JState(tif); - sp->tif = tif; /* back link */ - - /* Default values for codec-specific fields */ - sp->otherSettings.jpegtables = NULL; - sp->otherSettings.jpegtables_length = 0; - sp->otherSettings.jpegquality = 75; /* Default IJG quality */ - sp->otherSettings.jpegcolormode = JPEGCOLORMODE_RAW; - sp->otherSettings.jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF; - sp->otherSettings.ycbcrsampling_fetched = 0; - - tif->tif_tagmethods.vgetfield = JPEGVGetField; /* hook for codec tags */ - tif->tif_tagmethods.vsetfield = JPEGVSetField; /* hook for codec tags */ - tif->tif_tagmethods.printdir = JPEGPrintDir; /* hook for codec tags */ - - /* - * Install codec methods. - */ - tif->tif_fixuptags = JPEGFixupTags; - tif->tif_setupdecode = JPEGSetupDecode; - tif->tif_predecode = JPEGPreDecode; - tif->tif_decoderow = JPEGDecode; - tif->tif_decodestrip = JPEGDecode; - tif->tif_decodetile = JPEGDecode; - tif->tif_setupencode = JPEGSetupEncode; - tif->tif_preencode = JPEGPreEncode; - tif->tif_postencode = JPEGPostEncode; - tif->tif_encoderow = JPEGEncode; - tif->tif_encodestrip = JPEGEncode; - tif->tif_encodetile = JPEGEncode; - tif->tif_cleanup = JPEGCleanup; - - tif->tif_defstripsize = JPEGDefaultStripSize; - tif->tif_deftilesize = JPEGDefaultTileSize; - tif->tif_flags |= TIFF_NOBITREV; /* no bit reversal, please */ - sp->cinfo_initialized = FALSE; -} - -int TIFFInitJPEG(TIFF *tif, int scheme) { - JPEGState *sp; - - (void)scheme; - assert(scheme == COMPRESSION_JPEG); - - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, jpegFields, TIFFArrayCount(jpegFields))) { - TIFFErrorExt(tif->tif_clientdata, "TIFFInitJPEG", - "Merging JPEG codec-specific tags failed"); - return 0; - } +static void TIFFInitJPEGCommon(TIFF *tif) +{ + JPEGState *sp; - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8_t *)_TIFFmalloc(sizeof(JPEGState)); + sp = JState(tif); + sp->tif = tif; /* back link */ + + /* Default values for codec-specific fields */ + sp->otherSettings.jpegtables = NULL; + sp->otherSettings.jpegtables_length = 0; + sp->otherSettings.jpegquality = 75; /* Default IJG quality */ + sp->otherSettings.jpegcolormode = JPEGCOLORMODE_RAW; + sp->otherSettings.jpegtablesmode = + JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF; + sp->otherSettings.ycbcrsampling_fetched = 0; + + tif->tif_tagmethods.vgetfield = JPEGVGetField; /* hook for codec tags */ + tif->tif_tagmethods.vsetfield = JPEGVSetField; /* hook for codec tags */ + tif->tif_tagmethods.printdir = JPEGPrintDir; /* hook for codec tags */ - if (tif->tif_data == NULL) { - TIFFErrorExt(tif->tif_clientdata, "TIFFInitJPEG", - "No space for JPEG state block"); - return 0; - } - _TIFFmemset(tif->tif_data, 0, sizeof(JPEGState)); - - sp = JState(tif); - /* - * Override parent get/set field methods. - */ - sp->otherSettings.vgetparent = tif->tif_tagmethods.vgetfield; - sp->otherSettings.vsetparent = tif->tif_tagmethods.vsetfield; - sp->otherSettings.printdir = tif->tif_tagmethods.printdir; - - sp->otherSettings.defsparent = tif->tif_defstripsize; - sp->otherSettings.deftparent = tif->tif_deftilesize; - - TIFFInitJPEGCommon(tif); - - /* - ** Create a JPEGTables field if no directory has yet been created. - ** We do this just to ensure that sufficient space is reserved for - ** the JPEGTables field. It will be properly created the right - ** size later. - */ - if (tif->tif_diroff == 0) { -#define SIZE_OF_JPEGTABLES 2000 /* - The following line assumes incorrectly that all JPEG-in-TIFF files will have - a JPEGTABLES tag generated and causes null-filled JPEGTABLES tags to be - written when the JPEG data is placed with TIFFWriteRawStrip. The field bit - should be set, anyway, later when actual JPEGTABLES header is generated, so - removing it here hopefully is harmless. TIFFSetFieldBit(tif, - FIELD_JPEGTABLES); - */ - sp->otherSettings.jpegtables_length = SIZE_OF_JPEGTABLES; - sp->otherSettings.jpegtables = - (void *)_TIFFmalloc(sp->otherSettings.jpegtables_length); - if (sp->otherSettings.jpegtables) { - _TIFFmemset(sp->otherSettings.jpegtables, 0, SIZE_OF_JPEGTABLES); - } else { - TIFFErrorExt(tif->tif_clientdata, "TIFFInitJPEG", - "Failed to allocate memory for JPEG tables"); - return 0; + * Install codec methods. + */ + tif->tif_fixuptags = JPEGFixupTags; + tif->tif_setupdecode = JPEGSetupDecode; + tif->tif_predecode = JPEGPreDecode; + tif->tif_decoderow = JPEGDecode; + tif->tif_decodestrip = JPEGDecode; + tif->tif_decodetile = JPEGDecode; + tif->tif_setupencode = JPEGSetupEncode; + tif->tif_preencode = JPEGPreEncode; + tif->tif_postencode = JPEGPostEncode; + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; + tif->tif_cleanup = JPEGCleanup; + + tif->tif_defstripsize = JPEGDefaultStripSize; + tif->tif_deftilesize = JPEGDefaultTileSize; + tif->tif_flags |= TIFF_NOBITREV; /* no bit reversal, please */ + sp->cinfo_initialized = FALSE; +} + +int TIFFInitJPEG(TIFF *tif, int scheme) +{ + JPEGState *sp; + + (void)scheme; + assert(scheme == COMPRESSION_JPEG); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, jpegFields, TIFFArrayCount(jpegFields))) + { + TIFFErrorExtR(tif, "TIFFInitJPEG", + "Merging JPEG codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(JPEGState)); + + if (tif->tif_data == NULL) + { + TIFFErrorExtR(tif, "TIFFInitJPEG", "No space for JPEG state block"); + return 0; } + _TIFFmemset(tif->tif_data, 0, sizeof(JPEGState)); + + sp = JState(tif); + /* + * Override parent get/set field methods. + */ + sp->otherSettings.vgetparent = tif->tif_tagmethods.vgetfield; + sp->otherSettings.vsetparent = tif->tif_tagmethods.vsetfield; + sp->otherSettings.printdir = tif->tif_tagmethods.printdir; + + sp->otherSettings.defsparent = tif->tif_defstripsize; + sp->otherSettings.deftparent = tif->tif_deftilesize; + + TIFFInitJPEGCommon(tif); + + /* + ** Create a JPEGTables field if no directory has yet been created. + ** We do this just to ensure that sufficient space is reserved for + ** the JPEGTables field. It will be properly created the right + ** size later. + */ + if (tif->tif_diroff == 0) + { +#define SIZE_OF_JPEGTABLES 2000 + /* + The following line assumes incorrectly that all JPEG-in-TIFF files will + have a JPEGTABLES tag generated and causes null-filled JPEGTABLES tags + to be written when the JPEG data is placed with TIFFWriteRawStrip. The + field bit should be set, anyway, later when actual JPEGTABLES header is + generated, so removing it here hopefully is harmless. + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + */ + sp->otherSettings.jpegtables_length = SIZE_OF_JPEGTABLES; + sp->otherSettings.jpegtables = + (void *)_TIFFmallocExt(tif, sp->otherSettings.jpegtables_length); + if (sp->otherSettings.jpegtables) + { + _TIFFmemset(sp->otherSettings.jpegtables, 0, SIZE_OF_JPEGTABLES); + } + else + { + TIFFErrorExtR(tif, "TIFFInitJPEG", + "Failed to allocate memory for JPEG tables"); + return 0; + } #undef SIZE_OF_JPEGTABLES - } - return 1; + } + return 1; } #endif /* JPEG_SUPPORT */ |