~ubuntu-branches/ubuntu/trusty/python-imaging/trusty

« back to all changes in this revision

Viewing changes to PIL/TiffImagePlugin.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-03-20 16:44:01 UTC
  • mfrom: (2.1.13 experimental)
  • Revision ID: package-import@ubuntu.com-20130320164401-ptf6m0ttg4zw72az
Tags: 1.1.7+2.0.0-1
Pillow 2.0.0 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
 
44
44
__version__ = "1.3.5"
45
45
 
46
 
from . import Image, ImageFile
47
 
from . import ImagePalette
48
 
from . import _binary
 
46
from PIL import Image, ImageFile
 
47
from PIL import ImagePalette
 
48
from PIL import _binary
49
49
 
50
50
import array, sys
51
51
import collections
52
52
import itertools
 
53
import os
53
54
 
54
55
II = b"II" # little-endian (intel-style)
55
56
MM = b"MM" # big-endian (motorola-style)
121
122
    32773: "packbits"
122
123
}
123
124
 
 
125
COMPRESSION_INFO_REV = dict([(v,k) for (k,v) in COMPRESSION_INFO.items()])
 
126
 
124
127
OPEN_INFO = {
125
128
    # (ByteOrder, PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
126
129
    #  ExtraSamples) => mode, rawmode
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"),
216
220
        self.reset()
217
221
 
218
222
    def reset(self):
 
223
        #: Tags is an incomplete dictionary of the tags of the image.
 
224
        #: For a complete dictionary, use the as_dict method.
219
225
        self.tags = {}
220
226
        self.tagdata = {}
221
227
        self.tagtype = {} # added 2008-06-05 by Florian Hoech
222
228
        self.next = None
223
229
 
 
230
    def __str__(self):
 
231
        return str(self.as_dict())
 
232
 
 
233
    def as_dict(self):
 
234
        """Return a dictionary of the image's tags."""
 
235
        return dict(self.items())
 
236
 
 
237
    def named(self):
 
238
        """Returns the complete tag dictionary, with named tags where posible."""
 
239
        from PIL import TiffTags
 
240
        result = {}
 
241
        for tag_code, value in self.items():
 
242
            tag_name = TiffTags.TAGS.get(tag_code, tag_code)
 
243
            result[tag_name] = value
 
244
        return result
 
245
 
 
246
 
224
247
    # dictionary API
225
248
 
226
249
    def __len__(self):
269
292
    def __iter__(self):
270
293
        return itertools.chain(self.tags.__iter__(), self.tagdata.__iter__())
271
294
 
 
295
    def items(self):
 
296
        keys = list(self.__iter__())
 
297
        values = [self[key] for key in keys]
 
298
        return zip(keys, values)
 
299
 
272
300
    # load primitives
273
301
 
274
302
    load_dispatch = {}
338
366
            tag, typ = i16(ifd), i16(ifd, 2)
339
367
 
340
368
            if Image.DEBUG:
341
 
                from . import TiffTags
 
369
                from PIL import TiffTags
342
370
                tagname = TiffTags.TAGS.get(tag, "unknown")
343
371
                typname = TiffTags.TYPES.get(typ, "unknown")
344
372
                print("tag: %s (%d)" % (tagname, tag), end=' ')
434
462
                    data = b"".join(map(o32, value))
435
463
 
436
464
            if Image.DEBUG:
437
 
                from . import TiffTags
 
465
                from PIL import TiffTags
438
466
                tagname = TiffTags.TAGS.get(tag, "unknown")
439
467
                typname = TiffTags.TYPES.get(typ, "unknown")
440
468
                print("save: %s (%d)" % (tagname, tag), end=' ')
508
536
        self.__frame = -1
509
537
        self.__fp = self.fp
510
538
 
511
 
        # and load the first frame
 
539
        if Image.DEBUG:
 
540
            print ("*** TiffImageFile._open ***")
 
541
            print ("- __first:", self.__first)
 
542
            print ("- ifh: ", ifh)
 
543
 
 
544
       # and load the first frame
512
545
        self._seek(0)
513
546
 
514
547
    def seek(self, frame):
543
576
 
544
577
        return self.__frame
545
578
 
546
 
    def _decoder(self, rawmode, layer):
 
579
    def _decoder(self, rawmode, layer, tile=None):
547
580
        "Setup decoder contexts"
548
581
 
549
582
        args = None
570
603
 
571
604
        return args
572
605
 
 
606
    def _load_libtiff(self):
 
607
        """ Overload method triggered when we detect a g3/g4 tiff
 
608
            Calls out to lib tiff """
 
609
 
 
610
        pixel = Image.Image.load(self)
 
611
 
 
612
        if self.tile is None:
 
613
            raise IOError("cannot load this image")
 
614
        if not self.tile:
 
615
            return pixel
 
616
 
 
617
        self.load_prepare()
 
618
        
 
619
        if not len(self.tile) == 1:
 
620
            raise IOError("Not exactly one tile")
 
621
 
 
622
        d, e, o, a = self.tile[0]
 
623
        d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
 
624
        try:
 
625
            d.setimage(self.im, e)
 
626
        except ValueError:
 
627
            raise IOError("Couldn't set the image")
 
628
 
 
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.
 
635
            #
 
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. 
 
639
            if Image.DEBUG:
 
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.
 
644
            if Image.DEBUG:
 
645
                print ("have fileno, calling fileno version of the decoder.")
 
646
            self.fp.seek(0)
 
647
            n,e = d.decode(b"fpfp") # 4 bytes, otherwise the trace might error out
 
648
        else:
 
649
            # we have something else.
 
650
            if Image.DEBUG:
 
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())
 
654
 
 
655
        
 
656
        self.tile = []
 
657
        self.readonly = 0
 
658
        self.fp = None # might be shared
 
659
 
 
660
        if e < 0:
 
661
            raise IOError(e)
 
662
 
 
663
        self.load_end()
 
664
 
 
665
        return Image.Image.load(self)
 
666
 
573
667
    def _setup(self):
574
668
        "Setup this image object based on current tags"
575
669
 
645
739
        self.tile = []
646
740
        if STRIPOFFSETS in self.tag:
647
741
            # striped image
 
742
            offsets = self.tag[STRIPOFFSETS]
648
743
            h = getscalar(ROWSPERSTRIP, ysize)
649
744
            w = self.size[0]
650
 
            a = None
651
 
            for o in self.tag[STRIPOFFSETS]:
652
 
                if not a:
653
 
                    a = self._decoder(rawmode, l)
 
745
            if self._compression in ["tiff_ccitt", "group3",
 
746
                                     "group4", "tiff_raw_16"]:
 
747
                ## if Image.DEBUG:
 
748
                ##     print "Activating g4 compression for whole file"
 
749
 
 
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
 
753
                # function. 
 
754
                #
 
755
                # Setup the one tile for the whole image, then
 
756
                # replace the existing load function with our
 
757
                # _load_libtiff function.
 
758
                
 
759
                self.load = self._load_libtiff
 
760
                
 
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.
 
764
 
 
765
                # libtiff closes the file descriptor, so pass in a dup. 
 
766
                try:
 
767
                    fp = hasattr(self.fp, "fileno") and os.dup(self.fp.fileno())
 
768
                except IOError:
 
769
                    # io.BytesIO have a fileno, but returns an IOError if
 
770
                    # it doesn't use a file descriptor.
 
771
                    fp = False
 
772
 
 
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)),
657
 
                    o, a))
658
 
                y = y + h
659
 
                if y >= self.size[1]:
660
 
                    x = y = 0
661
 
                    l = l + 1
 
778
                     (0, 0, w, ysize),
 
779
                     0, a))
 
780
                a = None
 
781
 
 
782
            else:
 
783
                for i in range(len(offsets)):
 
784
                    a = self._decoder(rawmode, l, i)
 
785
                    self.tile.append(
 
786
                        (self._compression,
 
787
                        (0, min(y, ysize), w, min(y+h, ysize)),
 
788
                        offsets[i], a))
 
789
                    if Image.DEBUG:
 
790
                        print ("tiles: ", self.tile)
 
791
                    y = y + h
 
792
                    if y >= self.size[1]:
 
793
                        x = y = 0
 
794
                        l = l + 1
662
795
                    a = None
663
796
        elif TILEOFFSETS in self.tag:
664
797
            # tiled image
740
873
 
741
874
    ifd = ImageFileDirectory(prefix)
742
875
 
 
876
    compression = im.info.get('compression','raw')
 
877
    libtiff = compression in ["tiff_ccitt", "group3",
 
878
                              "group4", "tiff_raw_16"]
 
879
 
743
880
    # -- multi-page -- skip TIFF header on subsequent pages
744
 
    if fp.tell() == 0:
 
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
822
 
 
823
 
    offset = ifd.save(fp)
824
 
 
825
 
    ImageFile._save(im, fp, [
826
 
        ("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
827
 
        ])
 
958
    ifd[COMPRESSION] = COMPRESSION_INFO_REV.get(compression,1) # no compression by default
 
959
 
 
960
    if libtiff:
 
961
        if Image.DEBUG:
 
962
            print ("Saving using libtiff encoder")
 
963
            print (ifd.items())
 
964
        _fp = 0
 
965
        if hasattr(fp, "fileno"):
 
966
            fp.seek(0)
 
967
            _fp = os.dup(fp.fileno())
 
968
 
 
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])
 
971
        try:
 
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]
 
980
                        continue
 
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])
 
985
                        continue
 
986
                    if type(v) == tuple and len(v) == 1:
 
987
                        # int or similar
 
988
                        atts[k] = v[0]
 
989
                        continue
 
990
                    if type(v) == str:
 
991
                        atts[k] = v
 
992
                        continue
 
993
                    
 
994
        except:
 
995
            # if we don't have an ifd here, just punt.
 
996
            pass
 
997
        if Image.DEBUG:
 
998
            print (atts)
 
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)
 
1002
        while 1:
 
1003
            l, s, d = e.encode(16*1024) # undone, change to self.decodermaxblock
 
1004
            if not _fp:
 
1005
                fp.write(d)
 
1006
            if s:
 
1007
                break
 
1008
        if s < 0:
 
1009
            raise IOError("encoder error %d when writing image file" % s)
 
1010
        
 
1011
    else:
 
1012
        offset = ifd.save(fp)
 
1013
 
 
1014
        ImageFile._save(im, fp, [
 
1015
            ("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
 
1016
            ])
828
1017
 
829
1018
 
830
1019
    # -- helper for multi-page save --