summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerouault <erouault>2017-06-29 07:37:12 +0000
committererouault <erouault>2017-06-29 07:37:12 +0000
commitcf096692e43eaf02c67098e91f1e68b505c172b8 (patch)
treef71b3d034362eb397b66feb32026cf025346397d
parent95290821b4b170309ce104f866bcd9adff24ab0a (diff)
downloadlibtiff-cf096692e43eaf02c67098e91f1e68b505c172b8.tar.gz
* libtiff/tiffiop.h, libtiff/tif_jpeg.c, libtiff/tif_jpeg_12.c,
libtiff/tif_read.c: make TIFFReadScanline() works in CHUNKY_STRIP_READ_SUPPORT mode with JPEG stream with multiple scans. Also make configurable through a LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER environment variable the maximum number of scans allowed. Defaults to 100.
-rw-r--r--ChangeLog9
-rw-r--r--libtiff/tif_jpeg.c65
-rw-r--r--libtiff/tif_jpeg_12.c1
-rw-r--r--libtiff/tif_read.c25
-rw-r--r--libtiff/tiffiop.h3
5 files changed, 88 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index ab792220..c4ef9a7c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2017-06-29 Even Rouault <even.rouault at spatialys.com>
+
+ * libtiff/tiffiop.h, libtiff/tif_jpeg.c, libtiff/tif_jpeg_12.c,
+ libtiff/tif_read.c: make TIFFReadScanline() works in
+ CHUNKY_STRIP_READ_SUPPORT mode with JPEG stream with multiple scans.
+ Also make configurable through a LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER
+ environment variable the maximum number of scans allowed. Defaults to
+ 100.
+
2017-06-27 Even Rouault <even.rouault at spatialys.com>
* libtiff/tif_dirread.c: in TIFFReadDirEntryFloat(), check that a
diff --git a/libtiff/tif_jpeg.c b/libtiff/tif_jpeg.c
index e28fd667..833ca63f 100644
--- a/libtiff/tif_jpeg.c
+++ b/libtiff/tif_jpeg.c
@@ -1,4 +1,4 @@
-/* $Id: tif_jpeg.c,v 1.130 2017-06-24 15:33:28 erouault Exp $ */
+/* $Id: tif_jpeg.c,v 1.131 2017-06-29 07:37:12 erouault Exp $ */
/*
* Copyright (c) 1994-1997 Sam Leffler
@@ -49,6 +49,7 @@
int TIFFFillStrip(TIFF* tif, uint32 strip);
int TIFFFillTile(TIFF* tif, uint32 tile);
int TIFFReInitJPEG_12( TIFF *tif, int scheme, int is_encode );
+int TIFFJPEGIsFullStripRequired_12(TIFF* tif);
/* We undefine FAR to avoid conflict with JPEG definition */
@@ -179,6 +180,7 @@ typedef struct {
int jpegtablesmode; /* What to put in JPEGTables */
int ycbcrsampling_fetched;
+ int max_allowed_scan_number;
} JPEGState;
#define JState(tif) ((JPEGState*)(tif)->tif_data)
@@ -250,13 +252,14 @@ TIFFjpeg_progress_monitor(j_common_ptr cinfo)
{
const int scan_no =
((j_decompress_ptr)cinfo)->input_scan_number;
- const int MAX_SCANS = 100;
- if (scan_no >= MAX_SCANS)
+ if (scan_no >= sp->max_allowed_scan_number)
{
TIFFErrorExt(((JPEGState *) cinfo)->tif->tif_clientdata,
"TIFFjpeg_progress_monitor",
- "Scan number %d exceeds maximum scans (%d)",
- scan_no, MAX_SCANS);
+ "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->max_allowed_scan_number);
jpeg_abort(cinfo); /* clean up libjpeg state */
LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */
@@ -375,9 +378,14 @@ TIFFjpeg_has_multiple_scans(JPEGState* sp)
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->max_allowed_scan_number = 100;
+ sz_max_allowed_scan_number = getenv("LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER");
+ if( sz_max_allowed_scan_number )
+ sp->max_allowed_scan_number = atoi(sz_max_allowed_scan_number);
return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d));
}
@@ -629,9 +637,8 @@ std_term_source(j_decompress_ptr cinfo)
}
static void
-TIFFjpeg_data_src(JPEGState* sp, TIFF* tif)
+TIFFjpeg_data_src(JPEGState* sp)
{
- (void) tif;
sp->cinfo.d.src = &sp->src;
sp->src.init_source = std_init_source;
sp->src.fill_input_buffer = std_fill_input_buffer;
@@ -657,9 +664,9 @@ tables_init_source(j_decompress_ptr cinfo)
}
static void
-TIFFjpeg_tables_src(JPEGState* sp, TIFF* tif)
+TIFFjpeg_tables_src(JPEGState* sp)
{
- TIFFjpeg_data_src(sp, tif);
+ TIFFjpeg_data_src(sp);
sp->src.init_source = tables_init_source;
}
@@ -1016,7 +1023,7 @@ JPEGSetupDecode(TIFF* tif)
/* Read JPEGTables if it is present */
if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) {
- TIFFjpeg_tables_src(sp, tif);
+ TIFFjpeg_tables_src(sp);
if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) {
TIFFErrorExt(tif->tif_clientdata, "JPEGSetupDecode", "Bogus JPEGTables field");
return (0);
@@ -1038,11 +1045,47 @@ JPEGSetupDecode(TIFF* tif)
}
/* Set up for reading normal data */
- TIFFjpeg_data_src(sp, tif);
+ 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 */
+/* scanline decoding. This happens when the JPEG stream uses multiple scans. */
+/* Currently only called in CHUNKY_STRIP_READ_SUPPORT mode through */
+/* scanline interface. */
+/* 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;
+
+#if defined(JPEG_DUAL_MODE_8_12) && !defined(TIFFJPEGIsFullStripRequired)
+ if( tif->tif_dir.td_bitspersample == 12 )
+ return TIFFJPEGIsFullStripRequired_12( tif );
+#endif
+
+ memset(&state, 0, sizeof(JPEGState));
+ state.tif = tif;
+
+ TIFFjpeg_create_decompress(&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);
+
+ TIFFjpeg_destroy(&state);
+
+ return ret;
+}
+
/*
* Set up for decoding a strip or tile.
*/
diff --git a/libtiff/tif_jpeg_12.c b/libtiff/tif_jpeg_12.c
index 8499e649..b458c258 100644
--- a/libtiff/tif_jpeg_12.c
+++ b/libtiff/tif_jpeg_12.c
@@ -4,6 +4,7 @@
#if defined(JPEG_DUAL_MODE_8_12)
# define TIFFInitJPEG TIFFInitJPEG_12
+# define TIFFJPEGIsFullStripRequired TIFFJPEGIsFullStripRequired_12
int
TIFFInitJPEG_12(TIFF* tif, int scheme);
diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c
index cc4f5d2f..4f85fa93 100644
--- a/libtiff/tif_read.c
+++ b/libtiff/tif_read.c
@@ -1,4 +1,4 @@
-/* $Id: tif_read.c,v 1.59 2017-05-13 15:34:06 erouault Exp $ */
+/* $Id: tif_read.c,v 1.60 2017-06-29 07:37:12 erouault Exp $ */
/*
* Copyright (c) 1988-1997 Sam Leffler
@@ -262,6 +262,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ;
tif->tif_rawdataloaded = unused_data + to_read;
+ tif->tif_rawcc = tif->tif_rawdataloaded;
tif->tif_rawcp = tif->tif_rawdata;
if (!isFillOrder(tif, td->td_fillorder) &&
@@ -275,10 +276,28 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
** restart the decoder.
*/
if( restart )
- return TIFFStartStrip(tif, strip);
+ {
+
+#ifdef JPEG_SUPPORT
+ /* A bit messy since breaks the codec abstraction. Ultimately */
+ /* there should be a function pointer for that, but it seems */
+ /* only JPEG is affected. */
+ /* For JPEG, if there are multiple scans (can generally be known */
+ /* with the read_ahead used), we need to read the whole strip */
+ if( tif->tif_dir.td_compression==COMPRESSION_JPEG &&
+ (uint64)tif->tif_rawcc < td->td_stripbytecount[strip] )
+ {
+ if( TIFFJPEGIsFullStripRequired(tif) )
+ {
+ return TIFFFillStrip(tif, strip);
+ }
+ }
+#endif
+
+ return TIFFStartStrip(tif, strip);
+ }
else
{
- tif->tif_rawcc = tif->tif_rawdataloaded;
return 1;
}
}
diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h
index 73591340..2f992ef5 100644
--- a/libtiff/tiffiop.h
+++ b/libtiff/tiffiop.h
@@ -1,4 +1,4 @@
-/* $Id: tiffiop.h,v 1.91 2017-06-18 10:31:50 erouault Exp $ */
+/* $Id: tiffiop.h,v 1.92 2017-06-29 07:37:12 erouault Exp $ */
/*
* Copyright (c) 1988-1997 Sam Leffler
@@ -394,6 +394,7 @@ extern int TIFFInitOJPEG(TIFF*, int);
#endif
#ifdef JPEG_SUPPORT
extern int TIFFInitJPEG(TIFF*, int);
+extern int TIFFJPEGIsFullStripRequired(TIFF*);
#endif
#ifdef JBIG_SUPPORT
extern int TIFFInitJBIG(TIFF*, int);