2
# The Python Imaging Library.
5
# IFUNC IM file handling for PIL
8
# 1995-09-01 fl Created.
9
# 1997-01-03 fl Save palette images
10
# 1997-01-08 fl Added sequence support
11
# 1997-01-23 fl Added P and RGB save support
12
# 1997-05-31 fl Read floating point images
13
# 1997-06-22 fl Save floating point images
14
# 1997-08-27 fl Read and save 1-bit images
15
# 1998-06-25 fl Added support for RGB+LUT images
16
# 1998-07-02 fl Added support for YCC images
17
# 1998-07-15 fl Renamed offset attribute to avoid name clash
18
# 1998-12-29 fl Added I;16 support
19
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.7)
20
# 2003-09-26 fl Added LA/PA support
22
# Copyright (c) 1997-2003 by Secret Labs AB.
23
# Copyright (c) 1995-2001 by Fredrik Lundh.
25
# See the README file for information on usage and redistribution.
32
import Image, ImageFile, ImagePalette
35
# --------------------------------------------------------------------
40
EQUIPMENT = "Digitalization equipment"
41
FRAMES = "File size (no of images)"
45
SIZE = "Image size (x*y)"
48
TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0,
49
SCALE:0, SIZE:0, MODE:0 }
52
# ifunc93/p3cfunc formats
53
"0 1 image": ("1", "1"),
54
"L 1 image": ("1", "1"),
55
"Greyscale image": ("L", "L"),
56
"Grayscale image": ("L", "L"),
57
"RGB image": ("RGB", "RGB;L"),
58
"RLB image": ("RGB", "RLB"),
59
"RYB image": ("RGB", "RLB"),
60
"B1 image": ("1", "1"),
61
"B2 image": ("P", "P;2"),
62
"B4 image": ("P", "P;4"),
63
"X 24 image": ("RGB", "RGB"),
64
"L 32 S image": ("I", "I;32"),
65
"L 32 F image": ("F", "F;32"),
67
"RGB3 image": ("RGB", "RGB;T"),
68
"RYB3 image": ("RGB", "RYB;T"),
70
"LA image": ("LA", "LA;L"),
71
"RGBA image": ("RGBA", "RGBA;L"),
72
"RGBX image": ("RGBX", "RGBX;L"),
73
"CMYK image": ("CMYK", "CMYK;L"),
74
"YCC image": ("YCbCr", "YCbCr;L"),
78
for i in ["8", "8S", "16", "16S", "32", "32F"]:
79
OPEN["L %s image" % i] = ("F", "F;%s" % i)
80
OPEN["L*%s image" % i] = ("F", "F;%s" % i)
81
for i in ["16", "16L", "16B"]:
82
OPEN["L %s image" % i] = ("I;%s" % i, "I;%s" % i)
83
OPEN["L*%s image" % i] = ("I;%s" % i, "I;%s" % i)
85
OPEN["L %s image" % i] = ("I", "I;%s" % i)
86
OPEN["L*%s image" % i] = ("I", "I;%s" % i)
87
for i in range(2, 33):
88
OPEN["L*%s image" % i] = ("F", "F;%s" % i)
91
# --------------------------------------------------------------------
94
split = re.compile(r"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
103
# Image plugin for the IFUNC IM file format.
105
class ImImageFile(ImageFile.ImageFile):
108
format_description = "IFUNC Image Memory"
112
# Quick rejection: if there's not an LF among the first
113
# 100 bytes, this is (probably) not a text header.
115
if not "\n" in self.fp.read(100):
116
raise SyntaxError, "not an IM file"
122
self.info[MODE] = "L"
123
self.info[SIZE] = (512, 512)
124
self.info[FRAMES] = 1
132
# Some versions of IFUNC uses \n\r instead of \r\n...
136
if not s or s[0] == chr(0) or s[0] == chr(26):
139
# FIXME: this may read whole file if not a text file
140
s = s + self.fp.readline()
143
raise SyntaxError, "not an IM file"
153
raise SyntaxError, "not an IM file"
159
# Convert value as appropriate
160
if k in [FRAMES, SCALE, SIZE]:
161
v = string.replace(v, "*", ",")
162
v = tuple(map(number, string.split(v, ",")))
165
elif k == MODE and OPEN.has_key(v):
166
v, self.rawmode = OPEN[v]
168
# Add to dictionary. Note that COMMENT tags are
169
# combined into a list of strings.
171
if self.info.has_key(k):
172
self.info[k].append(v)
183
raise SyntaxError, "Syntax error in IM header: " + s
186
raise SyntaxError, "Not an IM file"
189
self.size = self.info[SIZE]
190
self.mode = self.info[MODE]
192
# Skip forward to start of image data
193
while s and s[0] != chr(26):
196
raise SyntaxError, "File truncated"
198
if self.info.has_key(LUT):
199
# convert lookup table to palette or lut attribute
200
palette = self.fp.read(768)
201
greyscale = 1 # greyscale palette
202
linear = 1 # linear greyscale palette
204
if palette[i] == palette[i+256] == palette[i+512]:
205
if palette[i] != chr(i):
209
if self.mode == "L" or self.mode == "LA":
212
self.lut = map(ord, palette[:256])
215
self.mode = self.rawmode = "P"
216
elif self.mode == "LA":
217
self.mode = self.rawmode = "PA"
218
self.palette = ImagePalette.raw("RGB;L", palette)
219
elif self.mode == "RGB":
220
if not greyscale or not linear:
221
self.lut = map(ord, palette)
225
self.__offset = offs = self.fp.tell()
227
self.__fp = self.fp # FIXME: hack
229
if self.rawmode[:2] == "F;":
233
# use bit decoder (if necessary)
234
bits = int(self.rawmode[2:])
235
if bits not in [8, 16, 32]:
236
self.tile = [("bit", (0,0)+self.size, offs,
237
(bits, 8, 3, 0, -1))]
242
if self.rawmode in ["RGB;T", "RYB;T"]:
243
# Old LabEye/3PC files. Would be very surprised if anyone
244
# ever stumbled upon such a file ;-)
245
size = self.size[0] * self.size[1]
246
self.tile = [("raw", (0,0)+self.size, offs, ("G", 0, -1)),
247
("raw", (0,0)+self.size, offs+size, ("R", 0, -1)),
248
("raw", (0,0)+self.size, offs+2*size, ("B", 0, -1))]
251
self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
253
def seek(self, frame):
255
if frame < 0 or frame >= self.info[FRAMES]:
256
raise EOFError, "seek outside sequence"
258
if self.frame == frame:
266
bits = 8 * len(self.mode)
268
size = ((self.size[0] * bits + 7) / 8) * self.size[1]
269
offs = self.__offset + frame * size
273
self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
280
# --------------------------------------------------------------------
284
# mode: (im type, raw mode)
286
"L": ("Greyscale", "L"),
287
"LA": ("LA", "LA;L"),
288
"P": ("Greyscale", "P"),
289
"PA": ("LA", "PA;L"),
290
"I": ("L 32S", "I;32S"),
291
"I;16": ("L 16", "I;16"),
292
"I;16L": ("L 16L", "I;16L"),
293
"I;16B": ("L 16B", "I;16B"),
294
"F": ("L 32F", "F;32F"),
295
"RGB": ("RGB", "RGB;L"),
296
"RGBA": ("RGBA", "RGBA;L"),
297
"RGBX": ("RGBX", "RGBX;L"),
298
"CMYK": ("CMYK", "CMYK;L"),
299
"YCbCr": ("YCC", "YCbCr;L")
302
def _save(im, fp, filename, check=0):
305
type, rawmode = SAVE[im.mode]
307
raise ValueError, "Cannot save %s images as IM" % im.mode
310
frames = im.encoderinfo["frames"]
317
fp.write("Image type: %s image\r\n" % type)
319
fp.write("Name: %s\r\n" % filename)
320
fp.write("Image size (x*y): %d*%d\r\n" % im.size)
321
fp.write("File size (no of images): %d\r\n" % frames)
323
fp.write("Lut: 1\r\n")
324
fp.write("\000" * (511-fp.tell()) + "\032")
326
fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes
327
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, -1))])
330
# --------------------------------------------------------------------
333
Image.register_open("IM", ImImageFile)
334
Image.register_save("IM", _save)
336
Image.register_extension("IM", ".im")