[Image-SIG] [PATCH] Fix ordering of color layer for PSD file format
Xavier Trochu
xavier.trochu at wanadoo.fr
Fri Oct 3 10:32:28 EDT 2003
The attached patch correct an issue with some photoshop files.
The issue occur when the order of the layer in the file in not one that
PIL understands (i.e. ARGB was wrongly read as RGBA), the patch fix
this by keeping the order consistent when building the tile array.
This patch also add support for reading the name of the layers.
Greetings,
Xavier
-------------- next part --------------
--- PsdImagePlugin.py.ori Fri Oct 03 14:10:04 2003
+++ PsdImagePlugin.py Fri Oct 03 14:05:16 2003
@@ -18,7 +18,7 @@
__version__ = "0.4"
-import string
+import string, struct
import Image, ImageFile, ImagePalette
MODES = {
@@ -38,10 +38,16 @@
# helpers
def i16(c):
- return ord(c[1]) + (ord(c[0])<<8)
+ return struct.unpack('>h', c)[0]
def i32(c):
- return ord(c[3]) + (ord(c[2])<<8) + (ord(c[1])<<16) + (ord(c[0])<<24)
+ return struct.unpack('>i', c)[0]
+
+def u16(c):
+ return struct.unpack('>H', c)[0]
+
+def u32(c):
+ return struct.unpack('>I', c)[0]
# --------------------------------------------------------------------.
# read PSD images
@@ -64,21 +70,34 @@
#
# header
- s = read(26)
- if s[:4] != "8BPS" or i16(s[4:]) != 1:
+ (psd_signature,
+ psd_version,
+ psd_channels,
+ psd_rows,
+ psd_columns,
+ psd_depth,
+ psd_mode) = struct.unpack('>4sh6xhiihh', read(26))
+
+ if Image.DEBUG > 2:
+ print "psd_signature is", psd_signature
+ print "psd_version is", psd_version
+ print "psd_channels is", psd_channels
+ print "psd_rows is", psd_rows
+ print "psd_columns is", psd_columns
+ print "psd_depth is", psd_depth
+ print "psd_mode is", psd_mode
+
+ if psd_signature != "8BPS" or psd_version != 1:
raise SyntaxError, "not a PSD file"
- psd_bits = i16(s[22:])
- psd_channels = i16(s[12:])
- psd_mode = i16(s[24:])
- mode, channels = MODES[(psd_mode, psd_bits)]
+ mode, channels = MODES[(psd_mode, psd_depth)]
if channels > psd_channels:
raise IOError, "not enough channels"
self.mode = mode
- self.size = i32(s[18:]), i32(s[14:])
+ self.size = psd_columns, psd_rows
#
# color mode data
@@ -107,7 +126,7 @@
data = read(i32(read(4)))
if (len(data) & 1):
read(1) # padding
- self.resources.append((id, name, data))
+ self.resources.append((signature, id, name, data))
#
# layer and mask information
@@ -164,8 +183,8 @@
# read layerinfo block
layers = []
read = file.read
-
- for i in range(abs(i16(read(2)))):
+ srange = i16(read(2))
+ for i in range(abs(srange)):
# bounding box
y0 = i32(read(4)); x0 = i32(read(4))
@@ -174,9 +193,10 @@
# image info
info = []
mode = []
- for i in range(i16(read(2))):
+ len = i16(read(2))
+ for i in range(len):
type = i16(read(2))
- if type == 65535:
+ if type == -1:
m = "A"
else:
m = "RGB"[type]
@@ -185,6 +205,7 @@
info.append((m, size))
# figure out the image mode
+ modecopy = mode[:]
mode.sort()
if mode == ["R"]:
mode = "L"
@@ -197,16 +218,20 @@
# skip over blend flags and extra information
filler = read(12)
- name = None # FIXME
- file.seek(i32(read(4)), 1)
+ end = u32(read(4)) + file.tell()
+ file.seek(i32(read(4)), 1) # skip over layer mask/adj data
+ file.seek(i32(read(4)), 1) # skip over blending range
+ len = ord(read(1))
+ name = read(len)
+ file.seek(end, 0) # skip to the end of the layer info
- layers.append((name, mode, (x0, y0, x1, y1)))
+ layers.append((name, mode, modecopy, (x0, y0, x1, y1)))
# get tiles
i = 0
- for name, mode, bbox in layers:
+ for name, mode, rmode, bbox in layers:
tile = []
- for m in mode:
+ for m in rmode:
t = _maketile(file, m, bbox, 1)
if t:
tile.extend(t)
More information about the Image-SIG
mailing list