Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/PIL/ImImagePlugin.py
diff options
context:
space:
mode:
Diffstat (limited to 'PIL/ImImagePlugin.py')
-rw-r--r--PIL/ImImagePlugin.py335
1 files changed, 335 insertions, 0 deletions
diff --git a/PIL/ImImagePlugin.py b/PIL/ImImagePlugin.py
new file mode 100644
index 0000000..17b8c0e
--- /dev/null
+++ b/PIL/ImImagePlugin.py
@@ -0,0 +1,335 @@
+#
+# The Python Imaging Library.
+# $Id: ImImagePlugin.py 2285 2005-02-07 23:52:14Z fredrik $
+#
+# IFUNC IM file handling for PIL
+#
+# history:
+# 1995-09-01 fl Created.
+# 1997-01-03 fl Save palette images
+# 1997-01-08 fl Added sequence support
+# 1997-01-23 fl Added P and RGB save support
+# 1997-05-31 fl Read floating point images
+# 1997-06-22 fl Save floating point images
+# 1997-08-27 fl Read and save 1-bit images
+# 1998-06-25 fl Added support for RGB+LUT images
+# 1998-07-02 fl Added support for YCC images
+# 1998-07-15 fl Renamed offset attribute to avoid name clash
+# 1998-12-29 fl Added I;16 support
+# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.7)
+# 2003-09-26 fl Added LA/PA support
+#
+# Copyright (c) 1997-2003 by Secret Labs AB.
+# Copyright (c) 1995-2001 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+
+__version__ = "0.7"
+
+import re, string
+import Image, ImageFile, ImagePalette
+
+
+# --------------------------------------------------------------------
+# Standard tags
+
+COMMENT = "Comment"
+DATE = "Date"
+EQUIPMENT = "Digitalization equipment"
+FRAMES = "File size (no of images)"
+LUT = "Lut"
+NAME = "Name"
+SCALE = "Scale (x,y)"
+SIZE = "Image size (x*y)"
+MODE = "Image type"
+
+TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0,
+ SCALE:0, SIZE:0, MODE:0 }
+
+OPEN = {
+ # ifunc93/p3cfunc formats
+ "0 1 image": ("1", "1"),
+ "L 1 image": ("1", "1"),
+ "Greyscale image": ("L", "L"),
+ "Grayscale image": ("L", "L"),
+ "RGB image": ("RGB", "RGB;L"),
+ "RLB image": ("RGB", "RLB"),
+ "RYB image": ("RGB", "RLB"),
+ "B1 image": ("1", "1"),
+ "B2 image": ("P", "P;2"),
+ "B4 image": ("P", "P;4"),
+ "X 24 image": ("RGB", "RGB"),
+ "L 32 S image": ("I", "I;32"),
+ "L 32 F image": ("F", "F;32"),
+ # old p3cfunc formats
+ "RGB3 image": ("RGB", "RGB;T"),
+ "RYB3 image": ("RGB", "RYB;T"),
+ # extensions
+ "LA image": ("LA", "LA;L"),
+ "RGBA image": ("RGBA", "RGBA;L"),
+ "RGBX image": ("RGBX", "RGBX;L"),
+ "CMYK image": ("CMYK", "CMYK;L"),
+ "YCC image": ("YCbCr", "YCbCr;L"),
+}
+
+# ifunc95 extensions
+for i in ["8", "8S", "16", "16S", "32", "32F"]:
+ OPEN["L %s image" % i] = ("F", "F;%s" % i)
+ OPEN["L*%s image" % i] = ("F", "F;%s" % i)
+for i in ["16", "16B"]:
+ OPEN["L %s image" % i] = ("I;%s" % i, "I;%s" % i)
+ OPEN["L*%s image" % i] = ("I;%s" % i, "I;%s" % i)
+for i in ["32S"]:
+ OPEN["L %s image" % i] = ("I", "I;%s" % i)
+ OPEN["L*%s image" % i] = ("I", "I;%s" % i)
+for i in range(2, 33):
+ OPEN["L*%s image" % i] = ("F", "F;%s" % i)
+
+
+# --------------------------------------------------------------------
+# Read IM directory
+
+split = re.compile(r"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
+
+def number(s):
+ try:
+ return int(s)
+ except ValueError:
+ return float(s)
+
+##
+# Image plugin for the IFUNC IM file format.
+
+class ImImageFile(ImageFile.ImageFile):
+
+ format = "IM"
+ format_description = "IFUNC Image Memory"
+
+ def _open(self):
+
+ # Quick rejection: if there's not an LF among the first
+ # 100 bytes, this is (probably) not a text header.
+
+ if not "\n" in self.fp.read(100):
+ raise SyntaxError, "not an IM file"
+ self.fp.seek(0)
+
+ n = 0
+
+ # Default values
+ self.info[MODE] = "L"
+ self.info[SIZE] = (512, 512)
+ self.info[FRAMES] = 1
+
+ self.rawmode = "L"
+
+ while 1:
+
+ s = self.fp.read(1)
+
+ # Some versions of IFUNC uses \n\r instead of \r\n...
+ if s == "\r":
+ continue
+
+ if not s or s[0] == chr(0) or s[0] == chr(26):
+ break
+
+ # FIXME: this may read whole file if not a text file
+ s = s + self.fp.readline()
+
+ if len(s) > 100:
+ raise SyntaxError, "not an IM file"
+
+ if s[-2:] == '\r\n':
+ s = s[:-2]
+ elif s[-1:] == '\n':
+ s = s[:-1]
+
+ try:
+ m = split.match(s)
+ except re.error, v:
+ raise SyntaxError, "not an IM file"
+
+ if m:
+
+ k, v = m.group(1,2)
+
+ # Convert value as appropriate
+ if k in [FRAMES, SCALE, SIZE]:
+ v = string.replace(v, "*", ",")
+ v = tuple(map(number, string.split(v, ",")))
+ if len(v) == 1:
+ v = v[0]
+ elif k == MODE and OPEN.has_key(v):
+ v, self.rawmode = OPEN[v]
+
+ # Add to dictionary. Note that COMMENT tags are
+ # combined into a list of strings.
+ if k == COMMENT:
+ if self.info.has_key(k):
+ self.info[k].append(v)
+ else:
+ self.info[k] = [v]
+ else:
+ self.info[k] = v
+
+ if TAGS.has_key(k):
+ n = n + 1
+
+ else:
+
+ raise SyntaxError, "Syntax error in IM header: " + s
+
+ if not n:
+ raise SyntaxError, "Not an IM file"
+
+ # Basic attributes
+ self.size = self.info[SIZE]
+ self.mode = self.info[MODE]
+
+ # Skip forward to start of image data
+ while s and s[0] != chr(26):
+ s = self.fp.read(1)
+ if not s:
+ raise SyntaxError, "File truncated"
+
+ if self.info.has_key(LUT):
+ # convert lookup table to palette or lut attribute
+ palette = self.fp.read(768)
+ greyscale = 1 # greyscale palette
+ linear = 1 # linear greyscale palette
+ for i in range(256):
+ if palette[i] == palette[i+256] == palette[i+512]:
+ if palette[i] != chr(i):
+ linear = 0
+ else:
+ greyscale = 0
+ if self.mode == "L" or self.mode == "LA":
+ if greyscale:
+ if not linear:
+ self.lut = map(ord, palette[:256])
+ else:
+ if self.mode == "L":
+ self.mode = self.rawmode = "P"
+ elif self.mode == "LA":
+ self.mode = self.rawmode = "PA"
+ self.palette = ImagePalette.raw("RGB;L", palette)
+ elif self.mode == "RGB":
+ if not greyscale or not linear:
+ self.lut = map(ord, palette)
+
+ self.frame = 0
+
+ self.__offset = offs = self.fp.tell()
+
+ self.__fp = self.fp # FIXME: hack
+
+ if self.rawmode[:2] == "F;":
+
+ # ifunc95 formats
+ try:
+ # use bit decoder (if necessary)
+ bits = int(self.rawmode[2:])
+ if bits not in [8, 16, 32]:
+ self.tile = [("bit", (0,0)+self.size, offs,
+ (bits, 8, 3, 0, -1))]
+ return
+ except ValueError:
+ pass
+
+ if self.rawmode in ["RGB;T", "RYB;T"]:
+ # Old LabEye/3PC files. Would be very surprised if anyone
+ # ever stumbled upon such a file ;-)
+ size = self.size[0] * self.size[1]
+ self.tile = [("raw", (0,0)+self.size, offs, ("G", 0, -1)),
+ ("raw", (0,0)+self.size, offs+size, ("R", 0, -1)),
+ ("raw", (0,0)+self.size, offs+2*size, ("B", 0, -1))]
+ else:
+ # LabEye/IFUNC files
+ self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
+
+ def seek(self, frame):
+
+ if frame < 0 or frame >= self.info[FRAMES]:
+ raise EOFError, "seek outside sequence"
+
+ if self.frame == frame:
+ return
+
+ self.frame = frame
+
+ if self.mode == "1":
+ bits = 1
+ else:
+ bits = 8 * len(self.mode)
+
+ size = ((self.size[0] * bits + 7) / 8) * self.size[1]
+ offs = self.__offset + frame * size
+
+ self.fp = self.__fp
+
+ self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
+
+ def tell(self):
+
+ return self.frame
+
+#
+# --------------------------------------------------------------------
+# Save IM files
+
+SAVE = {
+ # mode: (im type, raw mode)
+ "1": ("0 1", "1"),
+ "L": ("Greyscale", "L"),
+ "LA": ("LA", "LA;L"),
+ "P": ("Greyscale", "P"),
+ "PA": ("LA", "PA;L"),
+ "I": ("L 32S", "I;32S"),
+ "I;16": ("L 16", "I;16"),
+ "I;16B": ("L 16B", "I;16B"),
+ "F": ("L 32F", "F;32F"),
+ "RGB": ("RGB", "RGB;L"),
+ "RGBA": ("RGBA", "RGBA;L"),
+ "RGBX": ("RGBX", "RGBX;L"),
+ "CMYK": ("CMYK", "CMYK;L"),
+ "YCbCr": ("YCC", "YCbCr;L")
+}
+
+def _save(im, fp, filename, check=0):
+
+ try:
+ type, rawmode = SAVE[im.mode]
+ except KeyError:
+ raise ValueError, "Cannot save %s images as IM" % im.mode
+
+ try:
+ frames = im.encoderinfo["frames"]
+ except KeyError:
+ frames = 1
+
+ if check:
+ return check
+
+ fp.write("Image type: %s image\r\n" % type)
+ if filename:
+ fp.write("Name: %s\r\n" % filename)
+ fp.write("Image size (x*y): %d*%d\r\n" % im.size)
+ fp.write("File size (no of images): %d\r\n" % frames)
+ if im.mode == "P":
+ fp.write("Lut: 1\r\n")
+ fp.write("\000" * (511-fp.tell()) + "\032")
+ if im.mode == "P":
+ fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes
+ ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, -1))])
+
+#
+# --------------------------------------------------------------------
+# Registry
+
+Image.register_open("IM", ImImageFile)
+Image.register_save("IM", _save)
+
+Image.register_extension("IM", ".im")