~ubuntu-branches/ubuntu/saucy/python-imaging/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/git-updates.diff/PIL/PsdImagePlugin.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:
1
 
#
2
 
# The Python Imaging Library
3
 
# $Id$
4
 
#
5
 
# Adobe PSD 2.5/3.0 file handling
6
 
#
7
 
# History:
8
 
# 1995-09-01 fl   Created
9
 
# 1997-01-03 fl   Read most PSD images
10
 
# 1997-01-18 fl   Fixed P and CMYK support
11
 
# 2001-10-21 fl   Added seek/tell support (for layers)
12
 
#
13
 
# Copyright (c) 1997-2001 by Secret Labs AB.
14
 
# Copyright (c) 1995-2001 by Fredrik Lundh
15
 
#
16
 
# See the README file for information on usage and redistribution.
17
 
#
18
 
 
19
 
__version__ = "0.4"
20
 
 
21
 
import Image, ImageFile, ImagePalette
22
 
 
23
 
MODES = {
24
 
    # (photoshop mode, bits) -> (pil mode, required channels)
25
 
    (0, 1): ("1", 1),
26
 
    (0, 8): ("L", 1),
27
 
    (1, 8): ("L", 1),
28
 
    (2, 8): ("P", 1),
29
 
    (3, 8): ("RGB", 3),
30
 
    (4, 8): ("CMYK", 4),
31
 
    (7, 8): ("L", 1), # FIXME: multilayer
32
 
    (8, 8): ("L", 1), # duotone
33
 
    (9, 8): ("LAB", 3)
34
 
}
35
 
 
36
 
#
37
 
# helpers
38
 
 
39
 
def i16(c):
40
 
    return ord(c[1]) + (ord(c[0])<<8)
41
 
 
42
 
def i32(c):
43
 
    return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
44
 
 
45
 
# --------------------------------------------------------------------.
46
 
# read PSD images
47
 
 
48
 
def _accept(prefix):
49
 
    return prefix[:4] == "8BPS"
50
 
 
51
 
##
52
 
# Image plugin for Photoshop images.
53
 
 
54
 
class PsdImageFile(ImageFile.ImageFile):
55
 
 
56
 
    format = "PSD"
57
 
    format_description = "Adobe Photoshop"
58
 
 
59
 
    def _open(self):
60
 
        
61
 
        read = self.fp.read
62
 
 
63
 
        #
64
 
        # header
65
 
 
66
 
        s = read(26)
67
 
        if s[:4] != "8BPS" or i16(s[4:]) != 1:
68
 
            raise SyntaxError, "not a PSD file"
69
 
 
70
 
        psd_bits = i16(s[22:])
71
 
        psd_channels = i16(s[12:])
72
 
        psd_mode = i16(s[24:])
73
 
 
74
 
        mode, channels = MODES[(psd_mode, psd_bits)]
75
 
 
76
 
        if channels > psd_channels:
77
 
            raise IOError, "not enough channels"
78
 
 
79
 
        self.mode = mode
80
 
        self.size = i32(s[18:]), i32(s[14:])
81
 
 
82
 
        #
83
 
        # color mode data
84
 
 
85
 
        size = i32(read(4))
86
 
        if size:
87
 
            data = read(size)
88
 
            if mode == "P" and size == 768:
89
 
                self.palette = ImagePalette.raw("RGB;L", data)
90
 
 
91
 
        #
92
 
        # image resources
93
 
 
94
 
        self.resources = []
95
 
 
96
 
        size = i32(read(4))
97
 
        if size:
98
 
            # load resources
99
 
            end = self.fp.tell() + size
100
 
            while self.fp.tell() < end:
101
 
                signature = read(4)
102
 
                id = i16(read(2))
103
 
                name = read(ord(read(1)))
104
 
                if not (len(name) & 1):
105
 
                    read(1) # padding
106
 
                data = read(i32(read(4)))
107
 
                if (len(data) & 1):
108
 
                    read(1) # padding
109
 
                self.resources.append((id, name, data))
110
 
                if id == 1039: # ICC profile
111
 
                    self.info["icc_profile"] = data
112
 
 
113
 
        #
114
 
        # layer and mask information
115
 
 
116
 
        self.layers = []
117
 
 
118
 
        size = i32(read(4))
119
 
        if size:
120
 
            end = self.fp.tell() + size
121
 
            size = i32(read(4))
122
 
            if size:
123
 
                self.layers = _layerinfo(self.fp)
124
 
            self.fp.seek(end)
125
 
 
126
 
        #
127
 
        # image descriptor
128
 
 
129
 
        self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels)
130
 
 
131
 
        # keep the file open
132
 
        self._fp = self.fp
133
 
        self.frame = 0
134
 
 
135
 
    def seek(self, layer):
136
 
        # seek to given layer (1..max)
137
 
        if layer == self.frame:
138
 
            return
139
 
        try:
140
 
            if layer <= 0:
141
 
                raise IndexError
142
 
            name, mode, bbox, tile = self.layers[layer-1]
143
 
            self.mode = mode
144
 
            self.tile = tile
145
 
            self.frame = layer
146
 
            self.fp = self._fp
147
 
            return name, bbox
148
 
        except IndexError:
149
 
            raise EOFError, "no such layer"
150
 
 
151
 
    def tell(self):
152
 
        # return layer number (0=image, 1..max=layers)
153
 
        return self.frame
154
 
 
155
 
    def load_prepare(self):
156
 
        # create image memory if necessary
157
 
        if not self.im or\
158
 
           self.im.mode != self.mode or self.im.size != self.size:
159
 
            self.im = Image.core.fill(self.mode, self.size, 0)
160
 
        # create palette (optional)
161
 
        if self.mode == "P":
162
 
            Image.Image.load(self)
163
 
 
164
 
def _layerinfo(file):
165
 
    # read layerinfo block
166
 
    layers = []
167
 
    read = file.read
168
 
    for i in range(abs(i16(read(2)))):
169
 
 
170
 
        # bounding box
171
 
        y0 = i32(read(4)); x0 = i32(read(4))
172
 
        y1 = i32(read(4)); x1 = i32(read(4))
173
 
 
174
 
        # image info
175
 
        info = []
176
 
        mode = []
177
 
        types = range(i16(read(2)))
178
 
        if len(types) > 4:
179
 
            continue
180
 
 
181
 
        for i in types:
182
 
            type = i16(read(2))
183
 
 
184
 
            if type == 65535:
185
 
                m = "A"
186
 
            else:
187
 
                m = "RGBA"[type]
188
 
 
189
 
            mode.append(m)
190
 
            size = i32(read(4))
191
 
            info.append((m, size))
192
 
 
193
 
        # figure out the image mode
194
 
        mode.sort()
195
 
        if mode == ["R"]:
196
 
            mode = "L"
197
 
        elif mode == ["B", "G", "R"]:
198
 
            mode = "RGB"
199
 
        elif mode == ["A", "B", "G", "R"]:
200
 
            mode = "RGBA"
201
 
        else:
202
 
            mode = None # unknown
203
 
 
204
 
        # skip over blend flags and extra information
205
 
        filler = read(12)
206
 
        name = ""
207
 
        size = i32(read(4))
208
 
        combined = 0
209
 
        if size:
210
 
            length = i32(read(4))
211
 
            if length:
212
 
                mask_y = i32(read(4)); mask_x = i32(read(4))
213
 
                mask_h = i32(read(4)) - mask_y; mask_w = i32(read(4)) - mask_x
214
 
                file.seek(length - 16, 1)
215
 
            combined += length + 4
216
 
 
217
 
            length = i32(read(4))
218
 
            if length:
219
 
                file.seek(length, 1)
220
 
            combined += length + 4
221
 
 
222
 
            length = ord(read(1))
223
 
            if length:
224
 
                name = read(length)
225
 
            combined += length + 1
226
 
 
227
 
        file.seek(size - combined, 1)
228
 
        layers.append((name, mode, (x0, y0, x1, y1)))
229
 
 
230
 
    # get tiles
231
 
    i = 0
232
 
    for name, mode, bbox in layers:
233
 
        tile = []
234
 
        for m in mode:
235
 
            t = _maketile(file, m, bbox, 1)
236
 
            if t:
237
 
                tile.extend(t)
238
 
        layers[i] = name, mode, bbox, tile
239
 
        i = i + 1
240
 
 
241
 
    return layers
242
 
 
243
 
def _maketile(file, mode, bbox, channels):
244
 
 
245
 
    tile = None
246
 
    read = file.read
247
 
 
248
 
    compression = i16(read(2))
249
 
 
250
 
    xsize = bbox[2] - bbox[0]
251
 
    ysize = bbox[3] - bbox[1]
252
 
 
253
 
    offset = file.tell()
254
 
 
255
 
    if compression == 0:
256
 
        #
257
 
        # raw compression
258
 
        tile = []
259
 
        for channel in range(channels):
260
 
            layer = mode[channel]
261
 
            if mode == "CMYK":
262
 
                layer = layer + ";I"
263
 
            tile.append(("raw", bbox, offset, layer))
264
 
            offset = offset + xsize*ysize
265
 
 
266
 
    elif compression == 1:
267
 
        #
268
 
        # packbits compression
269
 
        i = 0
270
 
        tile = []
271
 
        bytecount = read(channels * ysize * 2)
272
 
        offset = file.tell()
273
 
        for channel in range(channels):
274
 
            layer = mode[channel]
275
 
            if mode == "CMYK":
276
 
                layer = layer + ";I"
277
 
            tile.append(
278
 
                ("packbits", bbox, offset, layer)
279
 
                )
280
 
            for y in range(ysize):
281
 
                offset = offset + i16(bytecount[i:i+2])
282
 
                i = i + 2
283
 
 
284
 
    file.seek(offset)
285
 
 
286
 
    if offset & 1:
287
 
        read(1) # padding
288
 
 
289
 
    return tile
290
 
 
291
 
# --------------------------------------------------------------------
292
 
# registry
293
 
 
294
 
Image.register_open("PSD", PsdImageFile, _accept)
295
 
 
296
 
Image.register_extension("PSD", ".psd")