mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-08-08 06:14:45 +03:00
Merge e6ad472c3b
into c2835350a8
This commit is contained in:
commit
291bbedfce
|
@ -59,9 +59,11 @@ try:
|
|||
# them. Note that other modules should not refer to _imaging
|
||||
# directly; import Image and use the Image.core variable instead.
|
||||
from PIL import _imaging as core
|
||||
if PILLOW_VERSION != getattr(core, 'PILLOW_VERSION', None):
|
||||
pillow_version_imported = getattr(core, 'PILLOW_VERSION', None)
|
||||
if PILLOW_VERSION != pillow_version_imported:
|
||||
raise ImportError("The _imaging extension was built for another "
|
||||
" version of Pillow or PIL")
|
||||
" version of Pillow or PIL - "
|
||||
" expected %s actual %s" % (PILLOW_VERSION, pillow_version_imported))
|
||||
|
||||
except ImportError as v:
|
||||
core = _imaging_not_installed()
|
||||
|
|
|
@ -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
|
||||
|
@ -706,6 +708,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:
|
||||
|
@ -743,9 +746,9 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
self.tile = []
|
||||
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()
|
||||
self.fp = None # might be shared
|
||||
#if hasattr(self.fp, 'close'):
|
||||
# self.fp.close()
|
||||
#self.fp = None # might be shared
|
||||
|
||||
if err < 0:
|
||||
raise IOError(err)
|
||||
|
@ -1119,14 +1122,16 @@ def _save(im, fp, filename):
|
|||
# save(load('')) == original file.
|
||||
for k, v in itertools.chain(ifd.items(),
|
||||
getattr(im, 'ifd', {}).items()):
|
||||
if k not in atts and k not in blocklist:
|
||||
if type(v[0]) == tuple and len(v) > 1:
|
||||
# all adobe defined tags are < 1024
|
||||
if k not in atts and k not in blocklist and k < 1024:
|
||||
# check len(v) before accessing elements
|
||||
if len(v) > 1 and type(v[0]) == tuple:
|
||||
# A tuple of more than one rational tuples
|
||||
# flatten to floats,
|
||||
# following tiffcp.c->cpTag->TIFF_RATIONAL
|
||||
atts[k] = [float(elt[0])/float(elt[1]) for elt in v]
|
||||
continue
|
||||
if type(v[0]) == tuple and len(v) == 1:
|
||||
if len(v) == 1 and type(v[0]) == tuple:
|
||||
# A tuple of one rational tuples
|
||||
# flatten to floats,
|
||||
# following tiffcp.c->cpTag->TIFF_RATIONAL
|
||||
|
|
BIN
Tests/images/multi.tif
Normal file
BIN
Tests/images/multi.tif
Normal file
Binary file not shown.
30
Tests/test_sequence_tiff.py
Normal file
30
Tests/test_sequence_tiff.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from helper import unittest, PillowTestCase
|
||||
|
||||
from PIL import Image, ImageSequence, TiffImagePlugin
|
||||
|
||||
TiffImagePlugin.READ_LIBTIFF = True
|
||||
|
||||
class TestFileTiff(PillowTestCase):
|
||||
|
||||
def setUp(self):
|
||||
codecs = dir(Image.core)
|
||||
|
||||
if "libtiff_encoder" not in codecs or "libtiff_decoder" not in codecs:
|
||||
self.skipTest("tiff support not available")
|
||||
|
||||
def testSequence(self):
|
||||
try:
|
||||
im = Image.open('Tests/images/multi.tif')
|
||||
index = 0
|
||||
for frame in ImageSequence.Iterator(im):
|
||||
frame.load()
|
||||
self.assertEqual(index, im.tell())
|
||||
index = index+1
|
||||
except Exception as e:
|
||||
self.assertTrue(False, str(e))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
# End of file
|
||||
|
5
decode.c
5
decode.c
|
@ -442,8 +442,9 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
|
|||
char* rawmode;
|
||||
char* compname;
|
||||
int fp;
|
||||
int ifdoffset;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "sssi", &mode, &rawmode, &compname, &fp))
|
||||
if (! PyArg_ParseTuple(args, "sssii", &mode, &rawmode, &compname, &fp, &ifdoffset))
|
||||
return NULL;
|
||||
|
||||
TRACE(("new tiff decoder %s\n", compname));
|
||||
|
@ -455,7 +456,7 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
|
|||
if (get_unpacker(decoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
|
||||
if (! ImagingLibTiffInit(&decoder->state, fp)) {
|
||||
if (! ImagingLibTiffInit(&decoder->state, fp, ifdoffset)) {
|
||||
Py_DECREF(decoder);
|
||||
PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
|
||||
return NULL;
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include "TiffDecode.h"
|
||||
|
||||
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));
|
||||
TRACE(("State: Location %u size %d eof %d data: %p ifd: %d\n", (uint)state->loc,
|
||||
(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;
|
||||
|
@ -195,7 +196,6 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int
|
|||
clientstate->loc = 0;
|
||||
clientstate->data = (tdata_t)buffer;
|
||||
clientstate->flrealloc = 0;
|
||||
|
||||
dump_state(clientstate);
|
||||
|
||||
TIFFSetWarningHandler(NULL);
|
||||
|
@ -220,6 +220,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) {
|
||||
|
|
|
@ -26,6 +26,7 @@ typedef struct {
|
|||
toff_t loc; /* toff_t == uint32 */
|
||||
tsize_t size; /* tsize_t == int32 */
|
||||
int fp;
|
||||
int ifd;
|
||||
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, ...);
|
||||
|
||||
|
@ -50,5 +51,4 @@ extern int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);
|
|||
|
||||
#define TRACE(args)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user