summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-05-29 20:11:43 +0000
committerEven Rouault <even.rouault@spatialys.com>2019-05-29 20:11:43 +0000
commit9cf3a97beaa3ffa8303e3ea9d7f34c6ee91dcf26 (patch)
tree9736009e4a0fc594069432abd72bcb2b7182f376
parentf273e83262c9996fd18dd889e9ab8dda2f7a5c34 (diff)
parent4e74734ded94f14afb0c2e871d026237515e0837 (diff)
downloadlibtiff-git-9cf3a97beaa3ffa8303e3ea9d7f34c6ee91dcf26.tar.gz
Merge branch 'TIFFReadFromUserBuffer' into 'master'
Add TIFFReadFromUserBuffer() See merge request libtiff/libtiff!81
-rw-r--r--libtiff/libtiff.def1
-rw-r--r--libtiff/tif_read.c87
-rw-r--r--libtiff/tiffio.h3
-rw-r--r--test/defer_strile_loading.c74
4 files changed, 155 insertions, 10 deletions
diff --git a/libtiff/libtiff.def b/libtiff/libtiff.def
index 413276b8..472299a7 100644
--- a/libtiff/libtiff.def
+++ b/libtiff/libtiff.def
@@ -86,6 +86,7 @@ EXPORTS TIFFAccessTagMethods
TIFFReadEXIFDirectory
TIFFReadEncodedStrip
TIFFReadEncodedTile
+ TIFFReadFromUserBuffer
TIFFReadRGBAImage
TIFFReadRGBAImageOriented
TIFFReadRGBAStrip
diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c
index f8dec446..1f5362a7 100644
--- a/libtiff/tif_read.c
+++ b/libtiff/tif_read.c
@@ -1506,6 +1506,93 @@ TIFFCheckRead(TIFF* tif, int tiles)
return (1);
}
+/* Use the provided input buffer (inbuf, insize) and decompress it into
+ * (outbuf, outsize).
+ * This function replaces the use of TIFFReadEncodedStrip()/TIFFReadEncodedTile()
+ * when the user can provide the buffer for the input data, for example when
+ * he wants to avoid libtiff to read the strile offset/count values from the
+ * [Strip|Tile][Offsets/ByteCounts] array.
+ * inbuf content must be writable (if bit reversal is needed)
+ * Returns 1 in case of success, 0 otherwise.
+ */
+int TIFFReadFromUserBuffer(TIFF* tif, uint32 strile,
+ void* inbuf, tmsize_t insize,
+ void* outbuf, tmsize_t outsize)
+{
+ static const char module[] = "TIFFReadFromUserBuffer";
+ TIFFDirectory *td = &tif->tif_dir;
+ int ret = 1;
+ uint32 old_tif_flags = tif->tif_flags;
+ tmsize_t old_rawdatasize = tif->tif_rawdatasize;
+ void* old_rawdata = tif->tif_rawdata;
+
+ if (tif->tif_mode == O_WRONLY) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "File not open for reading");
+ return 0;
+ }
+ if (tif->tif_flags&TIFF_NOREADRAW)
+ {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Compression scheme does not support access to raw uncompressed data");
+ return 0;
+ }
+
+ tif->tif_flags &= ~TIFF_MYBUFFER;
+ tif->tif_flags |= TIFF_BUFFERMMAP;
+ tif->tif_rawdatasize = insize;
+ tif->tif_rawdata = inbuf;
+ tif->tif_rawdataoff = 0;
+ tif->tif_rawdataloaded = insize;
+
+ if (!isFillOrder(tif, td->td_fillorder) &&
+ (tif->tif_flags & TIFF_NOBITREV) == 0)
+ {
+ TIFFReverseBits(inbuf, insize);
+ }
+
+ if( TIFFIsTiled(tif) )
+ {
+ if( !TIFFStartTile(tif, strile) ||
+ !(*tif->tif_decodetile)(tif, (uint8*) outbuf, outsize,
+ (uint16)(strile/td->td_stripsperimage)) )
+ {
+ ret = 0;
+ }
+ }
+ else
+ {
+ uint32 rowsperstrip=td->td_rowsperstrip;
+ uint32 stripsperplane;
+ if (rowsperstrip>td->td_imagelength)
+ rowsperstrip=td->td_imagelength;
+ stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
+ if( !TIFFStartStrip(tif, strile) ||
+ !(*tif->tif_decodestrip)(tif, (uint8*) outbuf, outsize,
+ (uint16)(strile/stripsperplane)) )
+ {
+ ret = 0;
+ }
+ }
+ if( ret )
+ {
+ (*tif->tif_postdecode)(tif, (uint8*) outbuf, outsize);
+ }
+
+ if (!isFillOrder(tif, td->td_fillorder) &&
+ (tif->tif_flags & TIFF_NOBITREV) == 0)
+ {
+ TIFFReverseBits(inbuf, insize);
+ }
+
+ tif->tif_flags = old_tif_flags;
+ tif->tif_rawdatasize = old_rawdatasize;
+ tif->tif_rawdata = old_rawdata;
+ tif->tif_rawdataoff = 0;
+ tif->tif_rawdataloaded = 0;
+
+ return ret;
+}
+
void
_TIFFNoPostDecode(TIFF* tif, uint8* buf, tmsize_t cc)
{
diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h
index 7193fbcf..5e42d522 100644
--- a/libtiff/tiffio.h
+++ b/libtiff/tiffio.h
@@ -468,6 +468,9 @@ extern tmsize_t TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_
extern tmsize_t TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size);
extern tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size);
extern tmsize_t TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size);
+extern int TIFFReadFromUserBuffer(TIFF* tif, uint32 strile,
+ void* inbuf, tmsize_t insize,
+ void* outbuf, tmsize_t outsize);
extern tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc);
extern tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc);
extern tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc);
diff --git a/test/defer_strile_loading.c b/test/defer_strile_loading.c
index 6f70d538..b444c01f 100644
--- a/test/defer_strile_loading.c
+++ b/test/defer_strile_loading.c
@@ -46,6 +46,8 @@ int test(int classictif, int height, int tiled)
TIFF* tif;
int i;
int ret = 0;
+ FILE* f;
+
(void)ret;
tif = TIFFOpen(filename, classictif ? "wDO" : "w8DO"); /* O should be ignored in write mode */
@@ -97,12 +99,17 @@ int test(int classictif, int height, int tiled)
}
TIFFClose(tif);
+ f = fopen(filename, "rb");
+ if( !f )
+ return 1;
+
for( i = 0; i < 2; i++ )
{
tif = TIFFOpen(filename, i == 0 ? "rD" : "rO");
if(!tif)
{
fprintf(stderr, "cannot open %s\n", filename);
+ fclose(f);
return 1;
}
if( tiled )
@@ -111,10 +118,11 @@ int test(int classictif, int height, int tiled)
for( j = 0; j < (height+15) / 16; j++ )
{
int retry;
+ unsigned char expected_c = (unsigned char)j;
+
for( retry = 0; retry < 2; retry++ )
{
unsigned char tilebuffer[256];
- unsigned char expected_c = (unsigned char)j;
memset(tilebuffer,0, 256);
ret = TIFFReadEncodedTile( tif, j, tilebuffer, 256 );
assert(ret == 256);
@@ -124,19 +132,42 @@ int test(int classictif, int height, int tiled)
fprintf(stderr, "unexpected value at tile %d: %d %d\n",
j, tilebuffer[0], tilebuffer[255]);
TIFFClose(tif);
+ fclose(f);
return 1;
}
}
{
int err = 0;
- ret = TIFFGetStrileOffsetWithErr(tif, j, &err);
- assert(ret != 0);
+ int offset, size;
+ unsigned char inputbuffer[256];
+ unsigned char tilebuffer[256];
+
+ offset = TIFFGetStrileOffsetWithErr(tif, j, &err);
+ assert(offset != 0);
assert(err == 0);
- ret = TIFFGetStrileByteCountWithErr(tif, j, &err);
- assert(ret == 256);
+ size = TIFFGetStrileByteCountWithErr(tif, j, &err);
+ assert(size == 256);
assert(err == 0);
+
+ fseek(f, offset, SEEK_SET);
+ fread(inputbuffer, 256, 1, f);
+
+ memset(tilebuffer,0, 256);
+ ret = TIFFReadFromUserBuffer(tif, j,
+ inputbuffer, 256,
+ tilebuffer, 256 );
+ assert(ret == 1);
+ if( tilebuffer[0] != expected_c ||
+ tilebuffer[255] != expected_c )
+ {
+ fprintf(stderr, "unexpected value at tile %d: %d %d\n",
+ j, tilebuffer[0], tilebuffer[255]);
+ TIFFClose(tif);
+ fclose(f);
+ return 1;
+ }
}
}
}
@@ -146,10 +177,10 @@ int test(int classictif, int height, int tiled)
for( j = 0; j < height; j++ )
{
int retry;
+ unsigned char expected_c = (unsigned char)j;
for( retry = 0; retry < 2; retry++ )
{
unsigned char c = 0;
- unsigned char expected_c = (unsigned char)j;
ret = TIFFReadEncodedStrip( tif, j, &c, 1 );
assert(ret == 1);
if( c != expected_c )
@@ -157,19 +188,41 @@ int test(int classictif, int height, int tiled)
fprintf(stderr, "unexpected value at line %d: %d\n",
j, c);
TIFFClose(tif);
+ fclose(f);
return 1;
}
}
{
int err = 0;
- ret = TIFFGetStrileOffsetWithErr(tif, j, &err);
- assert(ret != 0);
+ int offset, size;
+ unsigned char inputbuffer[1];
+ unsigned char tilebuffer[1];
+
+ offset = TIFFGetStrileOffsetWithErr(tif, j, &err);
+ assert(offset != 0);
assert(err == 0);
- ret = TIFFGetStrileByteCountWithErr(tif, j, &err);
- assert(ret == 1);
+ size = TIFFGetStrileByteCountWithErr(tif, j, &err);
+ assert(size == 1);
assert(err == 0);
+
+ fseek(f, offset, SEEK_SET);
+ fread(inputbuffer, 1, 1, f);
+
+ memset(tilebuffer,0, 1);
+ ret = TIFFReadFromUserBuffer(tif, j,
+ inputbuffer, 1,
+ tilebuffer, 1 );
+ assert(ret == 1);
+ if( tilebuffer[0] != expected_c )
+ {
+ fprintf(stderr, "unexpected value at line %d: %d\n",
+ j, tilebuffer[0]);
+ TIFFClose(tif);
+ fclose(f);
+ return 1;
+ }
}
if( j == 1 && height > 100000 )
@@ -231,6 +284,7 @@ int test(int classictif, int height, int tiled)
TIFFClose(tif);
}
+ fclose(f);
unlink(filename);
return 0;