~ubuntu-branches/debian/stretch/electrum/stretch

« back to all changes in this revision

Viewing changes to gui/kivy/tools/.buildozer/android/platform/python-for-android/dist/kivy/python-install/lib/python2.7/site-packages/PIL/TiffImagePlugin.py

  • Committer: Package Import Robot
  • Author(s): Tristan Seligmann
  • Date: 2016-04-04 03:02:39 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20160404030239-0szgkio8yryjv7c9
Tags: 2.6.3-1
* New upstream release.
  - Drop backported install-wizard-connect.patch.
* Add Suggests: python-zbar and update the installation hint to suggest
  apt-get instead of pip (closes: #819517).
* Bump Standards-Version to 3.9.7 (no changes).
* Update Vcs-* links.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# The Python Imaging Library.
 
3
# $Id$
 
4
#
 
5
# TIFF file handling
 
6
#
 
7
# TIFF is a flexible, if somewhat aged, image file format originally
 
8
# defined by Aldus.  Although TIFF supports a wide variety of pixel
 
9
# layouts and compression methods, the name doesn't really stand for
 
10
# "thousands of incompatible file formats," it just feels that way.
 
11
#
 
12
# To read TIFF data from a stream, the stream must be seekable.  For
 
13
# progressive decoding, make sure to use TIFF files where the tag
 
14
# directory is placed first in the file.
 
15
#
 
16
# History:
 
17
# 1995-09-01 fl   Created
 
18
# 1996-05-04 fl   Handle JPEGTABLES tag
 
19
# 1996-05-18 fl   Fixed COLORMAP support
 
20
# 1997-01-05 fl   Fixed PREDICTOR support
 
21
# 1997-08-27 fl   Added support for rational tags (from Perry Stoll)
 
22
# 1998-01-10 fl   Fixed seek/tell (from Jan Blom)
 
23
# 1998-07-15 fl   Use private names for internal variables
 
24
# 1999-06-13 fl   Rewritten for PIL 1.0 (1.0)
 
25
# 2000-10-11 fl   Additional fixes for Python 2.0 (1.1)
 
26
# 2001-04-17 fl   Fixed rewind support (seek to frame 0) (1.2)
 
27
# 2001-05-12 fl   Added write support for more tags (from Greg Couch) (1.3)
 
28
# 2001-12-18 fl   Added workaround for broken Matrox library
 
29
# 2002-01-18 fl   Don't mess up if photometric tag is missing (D. Alan Stewart)
 
30
# 2003-05-19 fl   Check FILLORDER tag
 
31
# 2003-09-26 fl   Added RGBa support
 
32
# 2004-02-24 fl   Added DPI support; fixed rational write support
 
33
# 2005-02-07 fl   Added workaround for broken Corel Draw 10 files
 
34
# 2006-01-09 fl   Added support for float/double tags (from Russell Nelson)
 
35
#
 
36
# Copyright (c) 1997-2006 by Secret Labs AB.  All rights reserved.
 
37
# Copyright (c) 1995-1997 by Fredrik Lundh
 
38
#
 
39
# See the README file for information on usage and redistribution.
 
40
#
 
41
 
 
42
__version__ = "1.3.5"
 
43
 
 
44
import Image, ImageFile
 
45
import ImagePalette
 
46
 
 
47
import array, string, sys
 
48
 
 
49
II = "II" # little-endian (intel-style)
 
50
MM = "MM" # big-endian (motorola-style)
 
51
 
 
52
try:
 
53
    if sys.byteorder == "little":
 
54
        native_prefix = II
 
55
    else:
 
56
        native_prefix = MM
 
57
except AttributeError:
 
58
    if ord(array.array("i",[1]).tostring()[0]):
 
59
        native_prefix = II
 
60
    else:
 
61
        native_prefix = MM
 
62
 
 
63
#
 
64
# --------------------------------------------------------------------
 
65
# Read TIFF files
 
66
 
 
67
def il16(c,o=0):
 
68
    return ord(c[o]) + (ord(c[o+1])<<8)
 
69
def il32(c,o=0):
 
70
    return ord(c[o]) + (ord(c[o+1])<<8) + (ord(c[o+2])<<16) + (ord(c[o+3])<<24)
 
71
def ol16(i):
 
72
    return chr(i&255) + chr(i>>8&255)
 
73
def ol32(i):
 
74
    return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
 
75
 
 
76
def ib16(c,o=0):
 
77
    return ord(c[o+1]) + (ord(c[o])<<8)
 
78
def ib32(c,o=0):
 
79
    return ord(c[o+3]) + (ord(c[o+2])<<8) + (ord(c[o+1])<<16) + (ord(c[o])<<24)
 
80
def ob16(i):
 
81
    return chr(i>>8&255) + chr(i&255)
 
82
def ob32(i):
 
83
    return chr(i>>24&255) + chr(i>>16&255) + chr(i>>8&255) + chr(i&255)
 
84
 
 
85
# a few tag names, just to make the code below a bit more readable
 
86
IMAGEWIDTH = 256
 
87
IMAGELENGTH = 257
 
88
BITSPERSAMPLE = 258
 
89
COMPRESSION = 259
 
90
PHOTOMETRIC_INTERPRETATION = 262
 
91
FILLORDER = 266
 
92
IMAGEDESCRIPTION = 270
 
93
STRIPOFFSETS = 273
 
94
SAMPLESPERPIXEL = 277
 
95
ROWSPERSTRIP = 278
 
96
STRIPBYTECOUNTS = 279
 
97
X_RESOLUTION = 282
 
98
Y_RESOLUTION = 283
 
99
PLANAR_CONFIGURATION = 284
 
100
RESOLUTION_UNIT = 296
 
101
SOFTWARE = 305
 
102
DATE_TIME = 306
 
103
ARTIST = 315
 
104
PREDICTOR = 317
 
105
COLORMAP = 320
 
106
TILEOFFSETS = 324
 
107
EXTRASAMPLES = 338
 
108
SAMPLEFORMAT = 339
 
109
JPEGTABLES = 347
 
110
COPYRIGHT = 33432
 
111
IPTC_NAA_CHUNK = 33723 # newsphoto properties
 
112
PHOTOSHOP_CHUNK = 34377 # photoshop properties
 
113
ICCPROFILE = 34675
 
114
EXIFIFD = 34665
 
115
XMP = 700
 
116
 
 
117
COMPRESSION_INFO = {
 
118
    # Compression => pil compression name
 
119
    1: "raw",
 
120
    2: "tiff_ccitt",
 
121
    3: "group3",
 
122
    4: "group4",
 
123
    5: "tiff_lzw",
 
124
    6: "tiff_jpeg", # obsolete
 
125
    7: "jpeg",
 
126
    32771: "tiff_raw_16", # 16-bit padding
 
127
    32773: "packbits"
 
128
}
 
129
 
 
130
OPEN_INFO = {
 
131
    # (ByteOrder, PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
 
132
    #  ExtraSamples) => mode, rawmode
 
133
    (II, 0, 1, 1, (1,), ()): ("1", "1;I"),
 
134
    (II, 0, 1, 2, (1,), ()): ("1", "1;IR"),
 
135
    (II, 0, 1, 1, (8,), ()): ("L", "L;I"),
 
136
    (II, 0, 1, 2, (8,), ()): ("L", "L;IR"),
 
137
    (II, 1, 1, 1, (1,), ()): ("1", "1"),
 
138
    (II, 1, 1, 2, (1,), ()): ("1", "1;R"),
 
139
    (II, 1, 1, 1, (8,), ()): ("L", "L"),
 
140
    (II, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
 
141
    (II, 1, 1, 2, (8,), ()): ("L", "L;R"),
 
142
    (II, 1, 1, 1, (16,), ()): ("I;16", "I;16"),
 
143
    (II, 1, 2, 1, (16,), ()): ("I;16S", "I;16S"),
 
144
    (II, 1, 2, 1, (32,), ()): ("I", "I;32S"),
 
145
    (II, 1, 3, 1, (32,), ()): ("F", "F;32F"),
 
146
    (II, 2, 1, 1, (8,8,8), ()): ("RGB", "RGB"),
 
147
    (II, 2, 1, 2, (8,8,8), ()): ("RGB", "RGB;R"),
 
148
    (II, 2, 1, 1, (8,8,8,8), (0,)): ("RGBX", "RGBX"),
 
149
    (II, 2, 1, 1, (8,8,8,8), (1,)): ("RGBA", "RGBa"),
 
150
    (II, 2, 1, 1, (8,8,8,8), (2,)): ("RGBA", "RGBA"),
 
151
    (II, 2, 1, 1, (8,8,8,8), (999,)): ("RGBA", "RGBA"), # corel draw 10
 
152
    (II, 3, 1, 1, (1,), ()): ("P", "P;1"),
 
153
    (II, 3, 1, 2, (1,), ()): ("P", "P;1R"),
 
154
    (II, 3, 1, 1, (2,), ()): ("P", "P;2"),
 
155
    (II, 3, 1, 2, (2,), ()): ("P", "P;2R"),
 
156
    (II, 3, 1, 1, (4,), ()): ("P", "P;4"),
 
157
    (II, 3, 1, 2, (4,), ()): ("P", "P;4R"),
 
158
    (II, 3, 1, 1, (8,), ()): ("P", "P"),
 
159
    (II, 3, 1, 1, (8,8), (2,)): ("PA", "PA"),
 
160
    (II, 3, 1, 2, (8,), ()): ("P", "P;R"),
 
161
    (II, 5, 1, 1, (8,8,8,8), ()): ("CMYK", "CMYK"),
 
162
    (II, 6, 1, 1, (8,8,8), ()): ("YCbCr", "YCbCr"),
 
163
    (II, 8, 1, 1, (8,8,8), ()): ("LAB", "LAB"),
 
164
 
 
165
    (MM, 0, 1, 1, (1,), ()): ("1", "1;I"),
 
166
    (MM, 0, 1, 2, (1,), ()): ("1", "1;IR"),
 
167
    (MM, 0, 1, 1, (8,), ()): ("L", "L;I"),
 
168
    (MM, 0, 1, 2, (8,), ()): ("L", "L;IR"),
 
169
    (MM, 1, 1, 1, (1,), ()): ("1", "1"),
 
170
    (MM, 1, 1, 2, (1,), ()): ("1", "1;R"),
 
171
    (MM, 1, 1, 1, (8,), ()): ("L", "L"),
 
172
    (MM, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
 
173
    (MM, 1, 1, 2, (8,), ()): ("L", "L;R"),
 
174
    (MM, 1, 1, 1, (16,), ()): ("I;16B", "I;16B"),
 
175
    (MM, 1, 2, 1, (16,), ()): ("I;16BS", "I;16BS"),
 
176
    (MM, 1, 2, 1, (32,), ()): ("I;32BS", "I;32BS"),
 
177
    (MM, 1, 3, 1, (32,), ()): ("F;32BF", "F;32BF"),
 
178
    (MM, 2, 1, 1, (8,8,8), ()): ("RGB", "RGB"),
 
179
    (MM, 2, 1, 2, (8,8,8), ()): ("RGB", "RGB;R"),
 
180
    (MM, 2, 1, 1, (8,8,8,8), (0,)): ("RGBX", "RGBX"),
 
181
    (MM, 2, 1, 1, (8,8,8,8), (1,)): ("RGBA", "RGBa"),
 
182
    (MM, 2, 1, 1, (8,8,8,8), (2,)): ("RGBA", "RGBA"),
 
183
    (MM, 2, 1, 1, (8,8,8,8), (999,)): ("RGBA", "RGBA"), # corel draw 10
 
184
    (MM, 3, 1, 1, (1,), ()): ("P", "P;1"),
 
185
    (MM, 3, 1, 2, (1,), ()): ("P", "P;1R"),
 
186
    (MM, 3, 1, 1, (2,), ()): ("P", "P;2"),
 
187
    (MM, 3, 1, 2, (2,), ()): ("P", "P;2R"),
 
188
    (MM, 3, 1, 1, (4,), ()): ("P", "P;4"),
 
189
    (MM, 3, 1, 2, (4,), ()): ("P", "P;4R"),
 
190
    (MM, 3, 1, 1, (8,), ()): ("P", "P"),
 
191
    (MM, 3, 1, 1, (8,8), (2,)): ("PA", "PA"),
 
192
    (MM, 3, 1, 2, (8,), ()): ("P", "P;R"),
 
193
    (MM, 5, 1, 1, (8,8,8,8), ()): ("CMYK", "CMYK"),
 
194
    (MM, 6, 1, 1, (8,8,8), ()): ("YCbCr", "YCbCr"),
 
195
    (MM, 8, 1, 1, (8,8,8), ()): ("LAB", "LAB"),
 
196
 
 
197
}
 
198
 
 
199
PREFIXES = ["MM\000\052", "II\052\000", "II\xBC\000"]
 
200
 
 
201
def _accept(prefix):
 
202
    return prefix[:4] in PREFIXES
 
203
 
 
204
##
 
205
# Wrapper for TIFF IFDs.
 
206
 
 
207
class ImageFileDirectory:
 
208
 
 
209
    # represents a TIFF tag directory.  to speed things up,
 
210
    # we don't decode tags unless they're asked for.
 
211
 
 
212
    def __init__(self, prefix):
 
213
        self.prefix = prefix[:2]
 
214
        if self.prefix == MM:
 
215
            self.i16, self.i32 = ib16, ib32
 
216
            self.o16, self.o32 = ob16, ob32
 
217
        elif self.prefix == II:
 
218
            self.i16, self.i32 = il16, il32
 
219
            self.o16, self.o32 = ol16, ol32
 
220
        else:
 
221
            raise SyntaxError("not a TIFF IFD")
 
222
        self.reset()
 
223
 
 
224
    def reset(self):
 
225
        self.tags = {}
 
226
        self.tagdata = {}
 
227
        self.tagtype = {} # added 2008-06-05 by Florian Hoech
 
228
        self.next = None
 
229
 
 
230
    # dictionary API (sort of)
 
231
 
 
232
    def keys(self):
 
233
        return self.tagdata.keys() + self.tags.keys()
 
234
 
 
235
    def items(self):
 
236
        items = self.tags.items()
 
237
        for tag in self.tagdata.keys():
 
238
            items.append((tag, self[tag]))
 
239
        return items
 
240
 
 
241
    def __len__(self):
 
242
        return len(self.tagdata) + len(self.tags)
 
243
 
 
244
    def __getitem__(self, tag):
 
245
        try:
 
246
            return self.tags[tag]
 
247
        except KeyError:
 
248
            type, data = self.tagdata[tag] # unpack on the fly
 
249
            size, handler = self.load_dispatch[type]
 
250
            self.tags[tag] = data = handler(self, data)
 
251
            del self.tagdata[tag]
 
252
            return data
 
253
 
 
254
    def get(self, tag, default=None):
 
255
        try:
 
256
            return self[tag]
 
257
        except KeyError:
 
258
            return default
 
259
 
 
260
    def getscalar(self, tag, default=None):
 
261
        try:
 
262
            value = self[tag]
 
263
            if len(value) != 1:
 
264
                if tag == SAMPLEFORMAT:
 
265
                    # work around broken (?) matrox library
 
266
                    # (from Ted Wright, via Bob Klimek)
 
267
                    raise KeyError # use default
 
268
                raise ValueError, "not a scalar"
 
269
            return value[0]
 
270
        except KeyError:
 
271
            if default is None:
 
272
                raise
 
273
            return default
 
274
 
 
275
    def has_key(self, tag):
 
276
        return self.tags.has_key(tag) or self.tagdata.has_key(tag)
 
277
 
 
278
    def __setitem__(self, tag, value):
 
279
        if type(value) is not type(()):
 
280
            value = (value,)
 
281
        self.tags[tag] = value
 
282
 
 
283
    # load primitives
 
284
 
 
285
    load_dispatch = {}
 
286
 
 
287
    def load_byte(self, data):
 
288
        l = []
 
289
        for i in range(len(data)):
 
290
            l.append(ord(data[i]))
 
291
        return tuple(l)
 
292
    load_dispatch[1] = (1, load_byte)
 
293
 
 
294
    def load_string(self, data):
 
295
        if data[-1:] == '\0':
 
296
            data = data[:-1]
 
297
        return data
 
298
    load_dispatch[2] = (1, load_string)
 
299
 
 
300
    def load_short(self, data):
 
301
        l = []
 
302
        for i in range(0, len(data), 2):
 
303
            l.append(self.i16(data, i))
 
304
        return tuple(l)
 
305
    load_dispatch[3] = (2, load_short)
 
306
 
 
307
    def load_long(self, data):
 
308
        l = []
 
309
        for i in range(0, len(data), 4):
 
310
            l.append(self.i32(data, i))
 
311
        return tuple(l)
 
312
    load_dispatch[4] = (4, load_long)
 
313
 
 
314
    def load_rational(self, data):
 
315
        l = []
 
316
        for i in range(0, len(data), 8):
 
317
            l.append((self.i32(data, i), self.i32(data, i+4)))
 
318
        return tuple(l)
 
319
    load_dispatch[5] = (8, load_rational)
 
320
 
 
321
    def load_float(self, data):
 
322
        a = array.array("f", data)
 
323
        if self.prefix != native_prefix:
 
324
            a.byteswap()
 
325
        return tuple(a)
 
326
    load_dispatch[11] = (4, load_float)
 
327
 
 
328
    def load_double(self, data):
 
329
        a = array.array("d", data)
 
330
        if self.prefix != native_prefix:
 
331
            a.byteswap()
 
332
        return tuple(a)
 
333
    load_dispatch[12] = (8, load_double)
 
334
 
 
335
    def load_undefined(self, data):
 
336
        # Untyped data
 
337
        return data
 
338
    load_dispatch[7] = (1, load_undefined)
 
339
 
 
340
    def load(self, fp):
 
341
        # load tag dictionary
 
342
 
 
343
        self.reset()
 
344
 
 
345
        i16 = self.i16
 
346
        i32 = self.i32
 
347
 
 
348
        for i in range(i16(fp.read(2))):
 
349
 
 
350
            ifd = fp.read(12)
 
351
 
 
352
            tag, typ = i16(ifd), i16(ifd, 2)
 
353
 
 
354
            if Image.DEBUG:
 
355
                import TiffTags
 
356
                tagname = TiffTags.TAGS.get(tag, "unknown")
 
357
                typname = TiffTags.TYPES.get(typ, "unknown")
 
358
                print "tag: %s (%d)" % (tagname, tag),
 
359
                print "- type: %s (%d)" % (typname, typ),
 
360
 
 
361
            try:
 
362
                dispatch = self.load_dispatch[typ]
 
363
            except KeyError:
 
364
                if Image.DEBUG:
 
365
                    print "- unsupported type", typ
 
366
                continue # ignore unsupported type
 
367
 
 
368
            size, handler = dispatch
 
369
 
 
370
            size = size * i32(ifd, 4)
 
371
 
 
372
            # Get and expand tag value
 
373
            if size > 4:
 
374
                here = fp.tell()
 
375
                fp.seek(i32(ifd, 8))
 
376
                data = ImageFile._safe_read(fp, size)
 
377
                fp.seek(here)
 
378
            else:
 
379
                data = ifd[8:8+size]
 
380
 
 
381
            if len(data) != size:
 
382
                raise IOError, "not enough data"
 
383
 
 
384
            self.tagdata[tag] = typ, data
 
385
            self.tagtype[tag] = typ
 
386
 
 
387
            if Image.DEBUG:
 
388
                if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
 
389
                    print "- value: <table: %d bytes>" % size
 
390
                else:
 
391
                    print "- value:", self[tag]
 
392
 
 
393
        self.next = i32(fp.read(4))
 
394
 
 
395
    # save primitives
 
396
 
 
397
    def save(self, fp):
 
398
 
 
399
        o16 = self.o16
 
400
        o32 = self.o32
 
401
 
 
402
        fp.write(o16(len(self.tags)))
 
403
 
 
404
        # always write in ascending tag order
 
405
        tags = self.tags.items()
 
406
        tags.sort()
 
407
 
 
408
        directory = []
 
409
        append = directory.append
 
410
 
 
411
        offset = fp.tell() + len(self.tags) * 12 + 4
 
412
 
 
413
        stripoffsets = None
 
414
 
 
415
        # pass 1: convert tags to binary format
 
416
        for tag, value in tags:
 
417
 
 
418
            typ = None
 
419
 
 
420
            if self.tagtype.has_key(tag):
 
421
                typ = self.tagtype[tag]
 
422
 
 
423
            if typ == 1:
 
424
                # byte data
 
425
                data = value = string.join(map(chr, value), "")
 
426
            elif typ == 7:
 
427
                # untyped data
 
428
                data = value = string.join(value, "")
 
429
            elif type(value[0]) is type(""):
 
430
                # string data
 
431
                typ = 2
 
432
                data = value = string.join(value, "\0") + "\0"
 
433
            else:
 
434
                # integer data
 
435
                if tag == STRIPOFFSETS:
 
436
                    stripoffsets = len(directory)
 
437
                    typ = 4 # to avoid catch-22
 
438
                elif tag in (X_RESOLUTION, Y_RESOLUTION):
 
439
                    # identify rational data fields
 
440
                    typ = 5
 
441
                elif not typ:
 
442
                    typ = 3
 
443
                    for v in value:
 
444
                        if v >= 65536:
 
445
                            typ = 4
 
446
                if typ == 3:
 
447
                    data = string.join(map(o16, value), "")
 
448
                else:
 
449
                    data = string.join(map(o32, value), "")
 
450
 
 
451
            if Image.DEBUG:
 
452
                import TiffTags
 
453
                tagname = TiffTags.TAGS.get(tag, "unknown")
 
454
                typname = TiffTags.TYPES.get(typ, "unknown")
 
455
                print "save: %s (%d)" % (tagname, tag),
 
456
                print "- type: %s (%d)" % (typname, typ),
 
457
                if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
 
458
                    size = len(data)
 
459
                    print "- value: <table: %d bytes>" % size
 
460
                else:
 
461
                    print "- value:", value
 
462
 
 
463
            # figure out if data fits into the directory
 
464
            if len(data) == 4:
 
465
                append((tag, typ, len(value), data, ""))
 
466
            elif len(data) < 4:
 
467
                append((tag, typ, len(value), data + (4-len(data))*"\0", ""))
 
468
            else:
 
469
                count = len(value)
 
470
                if typ == 5:
 
471
                    count = count / 2        # adjust for rational data field
 
472
                append((tag, typ, count, o32(offset), data))
 
473
                offset = offset + len(data)
 
474
                if offset & 1:
 
475
                    offset = offset + 1 # word padding
 
476
 
 
477
        # update strip offset data to point beyond auxiliary data
 
478
        if stripoffsets is not None:
 
479
            tag, typ, count, value, data = directory[stripoffsets]
 
480
            assert not data, "multistrip support not yet implemented"
 
481
            value = o32(self.i32(value) + offset)
 
482
            directory[stripoffsets] = tag, typ, count, value, data
 
483
 
 
484
        # pass 2: write directory to file
 
485
        for tag, typ, count, value, data in directory:
 
486
            if Image.DEBUG > 1:
 
487
                print tag, typ, count, repr(value), repr(data)
 
488
            fp.write(o16(tag) + o16(typ) + o32(count) + value)
 
489
 
 
490
        # -- overwrite here for multi-page --
 
491
        fp.write("\0\0\0\0") # end of directory
 
492
 
 
493
        # pass 3: write auxiliary data to file
 
494
        for tag, typ, count, value, data in directory:
 
495
            fp.write(data)
 
496
            if len(data) & 1:
 
497
                fp.write("\0")
 
498
 
 
499
        return offset
 
500
 
 
501
##
 
502
# Image plugin for TIFF files.
 
503
 
 
504
class TiffImageFile(ImageFile.ImageFile):
 
505
 
 
506
    format = "TIFF"
 
507
    format_description = "Adobe TIFF"
 
508
 
 
509
    def _open(self):
 
510
        "Open the first image in a TIFF file"
 
511
 
 
512
        # Header
 
513
        ifh = self.fp.read(8)
 
514
 
 
515
        if ifh[:4] not in PREFIXES:
 
516
            raise SyntaxError, "not a TIFF file"
 
517
 
 
518
        # image file directory (tag dictionary)
 
519
        self.tag = self.ifd = ImageFileDirectory(ifh[:2])
 
520
 
 
521
        # setup frame pointers
 
522
        self.__first = self.__next = self.ifd.i32(ifh, 4)
 
523
        self.__frame = -1
 
524
        self.__fp = self.fp
 
525
 
 
526
        # and load the first frame
 
527
        self._seek(0)
 
528
 
 
529
    def seek(self, frame):
 
530
        "Select a given frame as current image"
 
531
 
 
532
        if frame < 0:
 
533
            frame = 0
 
534
        self._seek(frame)
 
535
 
 
536
    def tell(self):
 
537
        "Return the current frame number"
 
538
 
 
539
        return self._tell()
 
540
 
 
541
    def _seek(self, frame):
 
542
 
 
543
        self.fp = self.__fp
 
544
        if frame < self.__frame:
 
545
            # rewind file
 
546
            self.__frame = -1
 
547
            self.__next = self.__first
 
548
        while self.__frame < frame:
 
549
            if not self.__next:
 
550
                raise EOFError, "no more images in TIFF file"
 
551
            self.fp.seek(self.__next)
 
552
            self.tag.load(self.fp)
 
553
            self.__next = self.tag.next
 
554
            self.__frame = self.__frame + 1
 
555
        self._setup()
 
556
 
 
557
    def _tell(self):
 
558
 
 
559
        return self.__frame
 
560
 
 
561
    def _decoder(self, rawmode, layer):
 
562
        "Setup decoder contexts"
 
563
 
 
564
        args = None
 
565
        if rawmode == "RGB" and self._planar_configuration == 2:
 
566
            rawmode = rawmode[layer]
 
567
        compression = self._compression
 
568
        if compression == "raw":
 
569
            args = (rawmode, 0, 1)
 
570
        elif compression == "jpeg":
 
571
            args = rawmode, ""
 
572
            if self.tag.has_key(JPEGTABLES):
 
573
                # Hack to handle abbreviated JPEG headers
 
574
                self.tile_prefix = self.tag[JPEGTABLES]
 
575
        elif compression == "packbits":
 
576
            args = rawmode
 
577
        elif compression == "tiff_lzw":
 
578
            args = rawmode
 
579
            if self.tag.has_key(317):
 
580
                # Section 14: Differencing Predictor
 
581
                self.decoderconfig = (self.tag[PREDICTOR][0],)
 
582
 
 
583
        if self.tag.has_key(ICCPROFILE):
 
584
            self.info['icc_profile'] = self.tag[ICCPROFILE]
 
585
 
 
586
        return args
 
587
 
 
588
    def _setup(self):
 
589
        "Setup this image object based on current tags"
 
590
 
 
591
        if self.tag.has_key(0xBC01):
 
592
            raise IOError, "Windows Media Photo files not yet supported"
 
593
 
 
594
        getscalar = self.tag.getscalar
 
595
 
 
596
        # extract relevant tags
 
597
        self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)]
 
598
        self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1)
 
599
 
 
600
        # photometric is a required tag, but not everyone is reading
 
601
        # the specification
 
602
        photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0)
 
603
 
 
604
        fillorder = getscalar(FILLORDER, 1)
 
605
 
 
606
        if Image.DEBUG:
 
607
            print "*** Summary ***"
 
608
            print "- compression:", self._compression
 
609
            print "- photometric_interpretation:", photo
 
610
            print "- planar_configuration:", self._planar_configuration
 
611
            print "- fill_order:", fillorder
 
612
 
 
613
        # size
 
614
        xsize = getscalar(IMAGEWIDTH)
 
615
        ysize = getscalar(IMAGELENGTH)
 
616
        self.size = xsize, ysize
 
617
 
 
618
        if Image.DEBUG:
 
619
            print "- size:", self.size
 
620
 
 
621
        format = getscalar(SAMPLEFORMAT, 1)
 
622
 
 
623
        # mode: check photometric interpretation and bits per pixel
 
624
        key = (
 
625
            self.tag.prefix, photo, format, fillorder,
 
626
            self.tag.get(BITSPERSAMPLE, (1,)),
 
627
            self.tag.get(EXTRASAMPLES, ())
 
628
            )
 
629
        if Image.DEBUG:
 
630
            print "format key:", key
 
631
        try:
 
632
            self.mode, rawmode = OPEN_INFO[key]
 
633
        except KeyError:
 
634
            if Image.DEBUG:
 
635
                print "- unsupported format"
 
636
            raise SyntaxError, "unknown pixel mode"
 
637
 
 
638
        if Image.DEBUG:
 
639
            print "- raw mode:", rawmode
 
640
            print "- pil mode:", self.mode
 
641
 
 
642
        self.info["compression"] = self._compression
 
643
 
 
644
        xres = getscalar(X_RESOLUTION, (1, 1))
 
645
        yres = getscalar(Y_RESOLUTION, (1, 1))
 
646
 
 
647
        if xres and yres:
 
648
            xres = xres[0] / (xres[1] or 1)
 
649
            yres = yres[0] / (yres[1] or 1)
 
650
            resunit = getscalar(RESOLUTION_UNIT, 1)
 
651
            if resunit == 2: # dots per inch
 
652
                self.info["dpi"] = xres, yres
 
653
            elif resunit == 3: # dots per centimeter. convert to dpi
 
654
                self.info["dpi"] = xres * 2.54, yres * 2.54
 
655
            else: # No absolute unit of measurement
 
656
                self.info["resolution"] = xres, yres
 
657
 
 
658
        # build tile descriptors
 
659
        x = y = l = 0
 
660
        self.tile = []
 
661
        if self.tag.has_key(STRIPOFFSETS):
 
662
            # striped image
 
663
            h = getscalar(ROWSPERSTRIP, ysize)
 
664
            w = self.size[0]
 
665
            a = None
 
666
            for o in self.tag[STRIPOFFSETS]:
 
667
                if not a:
 
668
                    a = self._decoder(rawmode, l)
 
669
                self.tile.append(
 
670
                    (self._compression,
 
671
                    (0, min(y, ysize), w, min(y+h, ysize)),
 
672
                    o, a))
 
673
                y = y + h
 
674
                if y >= self.size[1]:
 
675
                    x = y = 0
 
676
                    l = l + 1
 
677
                    a = None
 
678
        elif self.tag.has_key(TILEOFFSETS):
 
679
            # tiled image
 
680
            w = getscalar(322)
 
681
            h = getscalar(323)
 
682
            a = None
 
683
            for o in self.tag[TILEOFFSETS]:
 
684
                if not a:
 
685
                    a = self._decoder(rawmode, l)
 
686
                # FIXME: this doesn't work if the image size
 
687
                # is not a multiple of the tile size...
 
688
                self.tile.append(
 
689
                    (self._compression,
 
690
                    (x, y, x+w, y+h),
 
691
                    o, a))
 
692
                x = x + w
 
693
                if x >= self.size[0]:
 
694
                    x, y = 0, y + h
 
695
                    if y >= self.size[1]:
 
696
                        x = y = 0
 
697
                        l = l + 1
 
698
                        a = None
 
699
        else:
 
700
            if Image.DEBUG:
 
701
                print "- unsupported data organization"
 
702
            raise SyntaxError("unknown data organization")
 
703
 
 
704
        # fixup palette descriptor
 
705
 
 
706
        if self.mode == "P":
 
707
            palette = map(lambda a: chr(a / 256), self.tag[COLORMAP])
 
708
            self.palette = ImagePalette.raw("RGB;L", string.join(palette, ""))
 
709
#
 
710
# --------------------------------------------------------------------
 
711
# Write TIFF files
 
712
 
 
713
# little endian is default except for image modes with explict big endian byte-order
 
714
 
 
715
SAVE_INFO = {
 
716
    # mode => rawmode, byteorder, photometrics, sampleformat, bitspersample, extra
 
717
    "1": ("1", II, 1, 1, (1,), None),
 
718
    "L": ("L", II, 1, 1, (8,), None),
 
719
    "LA": ("LA", II, 1, 1, (8,8), 2),
 
720
    "P": ("P", II, 3, 1, (8,), None),
 
721
    "PA": ("PA", II, 3, 1, (8,8), 2),
 
722
    "I": ("I;32S", II, 1, 2, (32,), None),
 
723
    "I;16": ("I;16", II, 1, 1, (16,), None),
 
724
    "I;16S": ("I;16S", II, 1, 2, (16,), None),
 
725
    "F": ("F;32F", II, 1, 3, (32,), None),
 
726
    "RGB": ("RGB", II, 2, 1, (8,8,8), None),
 
727
    "RGBX": ("RGBX", II, 2, 1, (8,8,8,8), 0),
 
728
    "RGBA": ("RGBA", II, 2, 1, (8,8,8,8), 2),
 
729
    "CMYK": ("CMYK", II, 5, 1, (8,8,8,8), None),
 
730
    "YCbCr": ("YCbCr", II, 6, 1, (8,8,8), None),
 
731
    "LAB": ("LAB", II, 8, 1, (8,8,8), None),
 
732
 
 
733
    "I;32BS": ("I;32BS", MM, 1, 2, (32,), None),
 
734
    "I;16B": ("I;16B", MM, 1, 1, (16,), None),
 
735
    "I;16BS": ("I;16BS", MM, 1, 2, (16,), None),
 
736
    "F;32BF": ("F;32BF", MM, 1, 3, (32,), None),
 
737
}
 
738
 
 
739
def _cvt_res(value):
 
740
    # convert value to TIFF rational number -- (numerator, denominator)
 
741
    if type(value) in (type([]), type(())):
 
742
        assert(len(value) % 2 == 0)
 
743
        return value
 
744
    if type(value) == type(1):
 
745
        return (value, 1)
 
746
    value = float(value)
 
747
    return (int(value * 65536), 65536)
 
748
 
 
749
def _save(im, fp, filename):
 
750
 
 
751
    try:
 
752
        rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
 
753
    except KeyError:
 
754
        raise IOError, "cannot write mode %s as TIFF" % im.mode
 
755
 
 
756
    ifd = ImageFileDirectory(prefix)
 
757
 
 
758
    # -- multi-page -- skip TIFF header on subsequent pages
 
759
    if fp.tell() == 0:
 
760
        # tiff header (write via IFD to get everything right)
 
761
        # PIL always starts the first IFD at offset 8
 
762
        fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
 
763
 
 
764
    ifd[IMAGEWIDTH] = im.size[0]
 
765
    ifd[IMAGELENGTH] = im.size[1]
 
766
 
 
767
    # additions written by Greg Couch, gregc@cgl.ucsf.edu
 
768
    # inspired by image-sig posting from Kevin Cazabon, kcazabon@home.com
 
769
    if hasattr(im, 'tag'):
 
770
        # preserve tags from original TIFF image file
 
771
        for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
 
772
            if im.tag.tagdata.has_key(key):
 
773
                ifd[key] = im.tag.tagdata.get(key)
 
774
        # preserve some more tags from original TIFF image file
 
775
        # -- 2008-06-06 Florian Hoech
 
776
        ifd.tagtype = im.tag.tagtype
 
777
        for key in (IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP):
 
778
            if im.tag.has_key(key):
 
779
                ifd[key] = im.tag[key]
 
780
        # preserve ICC profile (should also work when saving other formats
 
781
        # which support profiles as TIFF) -- 2008-06-06 Florian Hoech
 
782
        if im.info.has_key("icc_profile"):
 
783
            ifd[ICCPROFILE] = im.info["icc_profile"]
 
784
    if im.encoderinfo.has_key("description"):
 
785
        ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
 
786
    if im.encoderinfo.has_key("resolution"):
 
787
        ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \
 
788
                                = _cvt_res(im.encoderinfo["resolution"])
 
789
    if im.encoderinfo.has_key("x resolution"):
 
790
        ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"])
 
791
    if im.encoderinfo.has_key("y resolution"):
 
792
        ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"])
 
793
    if im.encoderinfo.has_key("resolution unit"):
 
794
        unit = im.encoderinfo["resolution unit"]
 
795
        if unit == "inch":
 
796
            ifd[RESOLUTION_UNIT] = 2
 
797
        elif unit == "cm" or unit == "centimeter":
 
798
            ifd[RESOLUTION_UNIT] = 3
 
799
        else:
 
800
            ifd[RESOLUTION_UNIT] = 1
 
801
    if im.encoderinfo.has_key("software"):
 
802
        ifd[SOFTWARE] = im.encoderinfo["software"]
 
803
    if im.encoderinfo.has_key("date time"):
 
804
        ifd[DATE_TIME] = im.encoderinfo["date time"]
 
805
    if im.encoderinfo.has_key("artist"):
 
806
        ifd[ARTIST] = im.encoderinfo["artist"]
 
807
    if im.encoderinfo.has_key("copyright"):
 
808
        ifd[COPYRIGHT] = im.encoderinfo["copyright"]
 
809
 
 
810
    dpi = im.encoderinfo.get("dpi")
 
811
    if dpi:
 
812
        ifd[RESOLUTION_UNIT] = 2
 
813
        ifd[X_RESOLUTION] = _cvt_res(dpi[0])
 
814
        ifd[Y_RESOLUTION] = _cvt_res(dpi[1])
 
815
 
 
816
    if bits != (1,):
 
817
        ifd[BITSPERSAMPLE] = bits
 
818
        if len(bits) != 1:
 
819
            ifd[SAMPLESPERPIXEL] = len(bits)
 
820
    if extra is not None:
 
821
        ifd[EXTRASAMPLES] = extra
 
822
    if format != 1:
 
823
        ifd[SAMPLEFORMAT] = format
 
824
 
 
825
    ifd[PHOTOMETRIC_INTERPRETATION] = photo
 
826
 
 
827
    if im.mode == "P":
 
828
        lut = im.im.getpalette("RGB", "RGB;L")
 
829
        ifd[COLORMAP] = tuple(map(lambda v: ord(v) * 256, lut))
 
830
 
 
831
    # data orientation
 
832
    stride = len(bits) * ((im.size[0]*bits[0]+7)/8)
 
833
    ifd[ROWSPERSTRIP] = im.size[1]
 
834
    ifd[STRIPBYTECOUNTS] = stride * im.size[1]
 
835
    ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer
 
836
    ifd[COMPRESSION] = 1 # no compression
 
837
 
 
838
    offset = ifd.save(fp)
 
839
 
 
840
    ImageFile._save(im, fp, [
 
841
        ("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
 
842
        ])
 
843
 
 
844
 
 
845
    # -- helper for multi-page save --
 
846
    if im.encoderinfo.has_key("_debug_multipage"):
 
847
        #just to access o32 and o16 (using correct byte order)
 
848
        im._debug_multipage = ifd
 
849
 
 
850
#
 
851
# --------------------------------------------------------------------
 
852
# Register
 
853
 
 
854
Image.register_open("TIFF", TiffImageFile, _accept)
 
855
Image.register_save("TIFF", _save)
 
856
 
 
857
Image.register_extension("TIFF", ".tif")
 
858
Image.register_extension("TIFF", ".tiff")
 
859
 
 
860
Image.register_mime("TIFF", "image/tiff")