diff options
author | Even Rouault <even.rouault@spatialys.com> | 2019-05-29 20:11:43 +0000 |
---|---|---|
committer | Even Rouault <even.rouault@spatialys.com> | 2019-05-29 20:11:43 +0000 |
commit | 9cf3a97beaa3ffa8303e3ea9d7f34c6ee91dcf26 (patch) | |
tree | 9736009e4a0fc594069432abd72bcb2b7182f376 | |
parent | f273e83262c9996fd18dd889e9ab8dda2f7a5c34 (diff) | |
parent | 4e74734ded94f14afb0c2e871d026237515e0837 (diff) | |
download | libtiff-git-9cf3a97beaa3ffa8303e3ea9d7f34c6ee91dcf26.tar.gz |
Merge branch 'TIFFReadFromUserBuffer' into 'master'
Add TIFFReadFromUserBuffer()
See merge request libtiff/libtiff!81
-rw-r--r-- | libtiff/libtiff.def | 1 | ||||
-rw-r--r-- | libtiff/tif_read.c | 87 | ||||
-rw-r--r-- | libtiff/tiffio.h | 3 | ||||
-rw-r--r-- | test/defer_strile_loading.c | 74 |
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; |