135
138
(II, 1, 1, 2, (8,), ()): ("L", "L;R"),
136
139
(II, 1, 1, 1, (16,), ()): ("I;16", "I;16"),
137
140
(II, 1, 2, 1, (16,), ()): ("I;16S", "I;16S"),
141
(II, 1, 1, 1, (32,), ()): ("I", "I;32N"),
138
142
(II, 1, 2, 1, (32,), ()): ("I", "I;32S"),
139
143
(II, 1, 3, 1, (32,), ()): ("F", "F;32F"),
140
144
(II, 2, 1, 1, (8,8,8), ()): ("RGB", "RGB"),
223
#: Tags is an incomplete dictionary of the tags of the image.
224
#: For a complete dictionary, use the as_dict method.
220
226
self.tagdata = {}
221
227
self.tagtype = {} # added 2008-06-05 by Florian Hoech
231
return str(self.as_dict())
234
"""Return a dictionary of the image's tags."""
235
return dict(self.items())
238
"""Returns the complete tag dictionary, with named tags where posible."""
239
from PIL import TiffTags
241
for tag_code, value in self.items():
242
tag_name = TiffTags.TAGS.get(tag_code, tag_code)
243
result[tag_name] = value
226
249
def __len__(self):
606
def _load_libtiff(self):
607
""" Overload method triggered when we detect a g3/g4 tiff
608
Calls out to lib tiff """
610
pixel = Image.Image.load(self)
612
if self.tile is None:
613
raise IOError("cannot load this image")
619
if not len(self.tile) == 1:
620
raise IOError("Not exactly one tile")
622
d, e, o, a = self.tile[0]
623
d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
625
d.setimage(self.im, e)
627
raise IOError("Couldn't set the image")
629
if hasattr(self.fp, "getvalue"):
630
# We've got a stringio like thing passed in. Yay for all in memory.
631
# The decoder needs the entire file in one shot, so there's not
632
# a lot we can do here other than give it the entire file.
633
# unless we could do something like get the address of the underlying
634
# string for stringio.
636
# Rearranging for supporting byteio items, since they have a fileno
637
# that returns an IOError if there's no underlying fp. Easier to deal
638
# with here by reordering.
640
print ("have getvalue. just sending in a string from getvalue")
641
n,e = d.decode(self.fp.getvalue())
642
elif hasattr(self.fp, "fileno"):
643
# we've got a actual file on disk, pass in the fp.
645
print ("have fileno, calling fileno version of the decoder.")
647
n,e = d.decode(b"fpfp") # 4 bytes, otherwise the trace might error out
649
# we have something else.
651
print ("don't have fileno or getvalue. just reading")
652
# UNDONE -- so much for that buffer size thing.
653
n, e = d.decode(self.fp.read())
658
self.fp = None # might be shared
665
return Image.Image.load(self)
573
667
def _setup(self):
574
668
"Setup this image object based on current tags"
646
740
if STRIPOFFSETS in self.tag:
742
offsets = self.tag[STRIPOFFSETS]
648
743
h = getscalar(ROWSPERSTRIP, ysize)
651
for o in self.tag[STRIPOFFSETS]:
653
a = self._decoder(rawmode, l)
745
if self._compression in ["tiff_ccitt", "group3",
746
"group4", "tiff_raw_16"]:
748
## print "Activating g4 compression for whole file"
750
# Decoder expects entire file as one tile.
751
# There's a buffer size limit in load (64k)
752
# so large g4 images will fail if we use that
755
# Setup the one tile for the whole image, then
756
# replace the existing load function with our
757
# _load_libtiff function.
759
self.load = self._load_libtiff
761
# To be nice on memory footprint, if there's a
762
# file descriptor, use that instead of reading
763
# into a string in python.
765
# libtiff closes the file descriptor, so pass in a dup.
767
fp = hasattr(self.fp, "fileno") and os.dup(self.fp.fileno())
769
# io.BytesIO have a fileno, but returns an IOError if
770
# it doesn't use a file descriptor.
773
# Offset in the tile tuple is 0, we go from 0,0 to
774
# w,h, and we only do this once -- eds
775
a = (rawmode, self._compression, fp )
654
776
self.tile.append(
655
777
(self._compression,
656
(0, min(y, ysize), w, min(y+h, ysize)),
659
if y >= self.size[1]:
783
for i in range(len(offsets)):
784
a = self._decoder(rawmode, l, i)
787
(0, min(y, ysize), w, min(y+h, ysize)),
790
print ("tiles: ", self.tile)
792
if y >= self.size[1]:
663
796
elif TILEOFFSETS in self.tag:
741
874
ifd = ImageFileDirectory(prefix)
876
compression = im.info.get('compression','raw')
877
libtiff = compression in ["tiff_ccitt", "group3",
878
"group4", "tiff_raw_16"]
743
880
# -- multi-page -- skip TIFF header on subsequent pages
881
if not libtiff and fp.tell() == 0:
745
882
# tiff header (write via IFD to get everything right)
746
883
# PIL always starts the first IFD at offset 8
747
884
fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
818
955
ifd[ROWSPERSTRIP] = im.size[1]
819
956
ifd[STRIPBYTECOUNTS] = stride * im.size[1]
820
957
ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer
821
ifd[COMPRESSION] = 1 # no compression
823
offset = ifd.save(fp)
825
ImageFile._save(im, fp, [
826
("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
958
ifd[COMPRESSION] = COMPRESSION_INFO_REV.get(compression,1) # no compression by default
962
print ("Saving using libtiff encoder")
965
if hasattr(fp, "fileno"):
967
_fp = os.dup(fp.fileno())
969
blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ROWSPERSTRIP, ICCPROFILE] # ICC Profile crashes.
970
atts = dict([(k,v) for (k,(v,)) in ifd.items() if k not in blocklist])
972
# pull in more bits from the original file, e.g x,y resolution
973
# so that we can save(load('')) == original file.
974
for k,v in im.ifd.items():
975
if k not in atts and k not in blocklist:
976
if type(v[0]) == tuple and len(v) > 1:
977
# A tuple of more than one rational tuples
978
# flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL
979
atts[k] = [float(elt[0])/float(elt[1]) for elt in v]
981
if type(v[0]) == tuple and len(v) == 1:
982
# A tuple of one rational tuples
983
# flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL
984
atts[k] = float(v[0][0])/float(v[0][1])
986
if type(v) == tuple and len(v) == 1:
995
# if we don't have an ifd here, just punt.
999
a = (rawmode, compression, _fp, filename, atts)
1000
e = Image._getencoder(im.mode, compression, a, im.encoderconfig)
1001
e.setimage(im.im, (0,0)+im.size)
1003
l, s, d = e.encode(16*1024) # undone, change to self.decodermaxblock
1009
raise IOError("encoder error %d when writing image file" % s)
1012
offset = ifd.save(fp)
1014
ImageFile._save(im, fp, [
1015
("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
830
1019
# -- helper for multi-page save --