From b701edd28e97ac082e5e480898286bd434991fea Mon Sep 17 00:00:00 2001 From: Kenny Ostrom Date: Fri, 29 Aug 2014 17:19:24 -0500 Subject: [PATCH] merged wiredfool tiff-seek --- PIL/Image.py | 2 +- PIL/TiffImagePlugin.py | 17 +++++++++++---- Tests/images/multipage-lastframe.tif | Bin 0 -> 296 bytes Tests/images/multipage.tiff | Bin 0 -> 816 bytes Tests/test_file_libtiff.py | 31 +++++++++++++++++++++++++++ Tests/test_file_tiff.py | 27 ++++++++++++++++++++++- Tests/test_imagesequence.py | 25 ++++++++++++++++++++- decode.c | 5 +++-- libImaging/TiffDecode.c | 15 +++++++++++-- libImaging/TiffDecode.h | 3 ++- 10 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 Tests/images/multipage-lastframe.tif create mode 100644 Tests/images/multipage.tiff diff --git a/PIL/Image.py b/PIL/Image.py index 480410eff..ce94a583c 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -408,7 +408,7 @@ def _getdecoder(mode, decoder_name, args, extra=()): try: # get decoder decoder = getattr(core, decoder_name + "_decoder") - # print(decoder, mode, args + extra) + print(decoder, mode, args + extra) return decoder(mode, *args + extra) except AttributeError: raise IOError("decoder %s not available" % decoder_name) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index 9bef30ebe..0790d6532 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -281,6 +281,7 @@ class ImageFileDirectory(collections.MutableMapping): self.tagdata = {} self.tagtype = {} # added 2008-06-05 by Florian Hoech self.next = None + self.offset = None def __str__(self): return str(self.as_dict()) @@ -415,6 +416,7 @@ class ImageFileDirectory(collections.MutableMapping): # load tag dictionary self.reset() + self.offset = fp.tell() i16 = self.i16 i32 = self.i32 @@ -634,14 +636,17 @@ class TiffImageFile(ImageFile.ImageFile): if frame < 0: frame = 0 self._seek(frame) + # Create a new core image object on second and + # subsequent frames in the image. Image may be + # different size/mode. + Image._decompression_bomb_check(self.size) + self.im = Image.core.new(self.mode, self.size) def tell(self): "Return the current frame number" - return self._tell() def _seek(self, frame): - self.fp = self.__fp if frame < self.__frame: # rewind file @@ -650,6 +655,9 @@ class TiffImageFile(ImageFile.ImageFile): while self.__frame < frame: if not self.__next: raise EOFError("no more images in TIFF file") + # reset python3 buffered io handle in case fp + # was passed to libtiff, invalidating the buffer + self.fp.tell() self.fp.seek(self.__next) self.tag.load(self.fp) self.__next = self.tag.next @@ -657,7 +665,6 @@ class TiffImageFile(ImageFile.ImageFile): self._setup() def _tell(self): - return self.__frame def _decoder(self, rawmode, layer, tile=None): @@ -706,6 +713,7 @@ class TiffImageFile(ImageFile.ImageFile): # (self._compression, (extents tuple), # 0, (rawmode, self._compression, fp)) ignored, extents, ignored_2, args = self.tile[0] + args = args + (self.ifd.offset,) decoder = Image._getdecoder(self.mode, 'libtiff', args, self.decoderconfig) try: @@ -744,7 +752,8 @@ class TiffImageFile(ImageFile.ImageFile): self.readonly = 0 # libtiff closed the fp in a, we need to close self.fp, if possible if hasattr(self.fp, 'close'): - self.fp.close() + if not self.__next: + self.fp.close() self.fp = None # might be shared if err < 0: diff --git a/Tests/images/multipage-lastframe.tif b/Tests/images/multipage-lastframe.tif new file mode 100644 index 0000000000000000000000000000000000000000..aeba534e25a9f0527c5fe1674461d4b484b67159 GIT binary patch literal 296 zcmebD)M9X9pbQ8wFfcMRFaiw`0b)iZHWQQ$l4C|OIx6vmM|p=otifD41~6Nc#Ke&sE#b zUVz7fufRnxI|bIL;bt^f+TQVowJOT{O_Dk7&r0>?)puqGmPkbvcUJ9Pf{4p e>68J-bkbzJPC0sstate, fp)) { + if (! ImagingLibTiffInit(&decoder->state, fp, ifdoffset)) { Py_DECREF(decoder); PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed"); return NULL; diff --git a/libImaging/TiffDecode.c b/libImaging/TiffDecode.c index 787cd4506..a9fd504bd 100644 --- a/libImaging/TiffDecode.c +++ b/libImaging/TiffDecode.c @@ -22,7 +22,7 @@ void dump_state(const TIFFSTATE *state){ TRACE(("State: Location %u size %d eof %d data: %p \n", (uint)state->loc, - (int)state->size, (uint)state->eof, state->data)); + (int)state->size, (uint)state->eof, state->data, state->ifd)); } /* @@ -142,7 +142,7 @@ void _tiffUnmapProc(thandle_t hdata, tdata_t base, toff_t size) { (void) hdata; (void) base; (void) size; } -int ImagingLibTiffInit(ImagingCodecState state, int fp) { +int ImagingLibTiffInit(ImagingCodecState state, int fp, int offset) { TIFFSTATE *clientstate = (TIFFSTATE *)state->context; TRACE(("initing libtiff\n")); @@ -158,6 +158,7 @@ int ImagingLibTiffInit(ImagingCodecState state, int fp) { clientstate->size = 0; clientstate->data = 0; clientstate->fp = fp; + clientstate->ifd = offset; clientstate->eof = 0; return 1; @@ -220,6 +221,16 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int return -1; } + if (clientstate->ifd){ + unsigned int ifdoffset = clientstate->ifd; + TRACE(("reading tiff ifd %d\n", ifdoffset)); + int rv = TIFFSetSubDirectory(tiff, ifdoffset); + if (!rv){ + TRACE(("error in TIFFSetSubDirectory")); + return -1; + } + } + size = TIFFScanlineSize(tiff); TRACE(("ScanlineSize: %d \n", size)); if (size > state->bytes) { diff --git a/libImaging/TiffDecode.h b/libImaging/TiffDecode.h index 46c940d1b..4a182089c 100644 --- a/libImaging/TiffDecode.h +++ b/libImaging/TiffDecode.h @@ -26,6 +26,7 @@ typedef struct { toff_t loc; /* toff_t == uint32 */ tsize_t size; /* tsize_t == int32 */ int fp; + int ifd; /* offset of the ifd, used for multipage */ TIFF *tiff; /* Used in write */ toff_t eof; int flrealloc; /* may we realloc */ @@ -33,7 +34,7 @@ typedef struct { -extern int ImagingLibTiffInit(ImagingCodecState state, int fp); +extern int ImagingLibTiffInit(ImagingCodecState state, int fp, int offset); extern int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp); extern int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);