diff options
author | Keshav Sharma <keshav7890@gmail.com> | 2011-07-03 11:22:14 (GMT) |
---|---|---|
committer | Keshav Sharma <keshav7890@gmail.com> | 2011-07-03 11:22:14 (GMT) |
commit | ca10d560496dc9f6edde8b422fe591c96c175a6d (patch) | |
tree | 5efdf45be57028217d8f742651301ec234824401 /PIL/BmpImagePlugin.py |
added activity folder
Diffstat (limited to 'PIL/BmpImagePlugin.py')
-rw-r--r-- | PIL/BmpImagePlugin.py | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/PIL/BmpImagePlugin.py b/PIL/BmpImagePlugin.py new file mode 100644 index 0000000..a939d9b --- /dev/null +++ b/PIL/BmpImagePlugin.py @@ -0,0 +1,245 @@ +# +# The Python Imaging Library. +# $Id: BmpImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $ +# +# BMP file handler +# +# Windows (and OS/2) native bitmap storage format. +# +# history: +# 1995-09-01 fl Created +# 1996-04-30 fl Added save +# 1997-08-27 fl Fixed save of 1-bit images +# 1998-03-06 fl Load P images as L where possible +# 1998-07-03 fl Load P images as 1 where possible +# 1998-12-29 fl Handle small palettes +# 2002-12-30 fl Fixed load of 1-bit palette images +# 2003-04-21 fl Fixed load of 1-bit monochrome images +# 2003-04-23 fl Added limited support for BI_BITFIELDS compression +# +# Copyright (c) 1997-2003 by Secret Labs AB +# Copyright (c) 1995-2003 by Fredrik Lundh +# +# See the README file for information on usage and redistribution. +# + + +__version__ = "0.7" + + +import string +import Image, ImageFile, ImagePalette + + +# +# -------------------------------------------------------------------- +# Read BMP file + +def i16(c): + return ord(c[0]) + (ord(c[1])<<8) + +def i32(c): + return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24) + + +BIT2MODE = { + # bits => mode, rawmode + 1: ("P", "P;1"), + 4: ("P", "P;4"), + 8: ("P", "P"), + 16: ("RGB", "BGR;16"), + 24: ("RGB", "BGR"), + 32: ("RGB", "BGRX") +} + +def _accept(prefix): + return prefix[:2] == "BM" + +## +# Image plugin for the Windows BMP format. + +class BmpImageFile(ImageFile.ImageFile): + + format = "BMP" + format_description = "Windows Bitmap" + + def _bitmap(self, header = 0, offset = 0): + + if header: + self.fp.seek(header) + + read = self.fp.read + + # CORE/INFO + s = read(4) + s = s + ImageFile._safe_read(self.fp, i32(s)-4) + + if len(s) == 12: + + # OS/2 1.0 CORE + bits = i16(s[10:]) + self.size = i16(s[4:]), i16(s[6:]) + compression = 0 + lutsize = 3 + colors = 0 + + elif len(s) in [40, 64]: + + # WIN 3.1 or OS/2 2.0 INFO + bits = i16(s[14:]) + self.size = i32(s[4:]), i32(s[8:]) + compression = i32(s[16:]) + lutsize = 4 + colors = i32(s[32:]) + + else: + raise IOError("Unsupported BMP header type (%d)" % len(s)) + + if not colors: + colors = 1 << bits + + # MODE + try: + self.mode, rawmode = BIT2MODE[bits] + except KeyError: + raise IOError("Unsupported BMP pixel depth (%d)" % bits) + + if compression == 3: + # BI_BITFIELDS compression + mask = i32(read(4)), i32(read(4)), i32(read(4)) + if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff): + rawmode = "BGRX" + elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f): + rawmode = "BGR;16" + elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f): + rawmode = "BGR;15" + else: + # print bits, map(hex, mask) + raise IOError("Unsupported BMP bitfields layout") + elif compression != 0: + raise IOError("Unsupported BMP compression (%d)" % compression) + + # LUT + if self.mode == "P": + palette = [] + greyscale = 1 + if colors == 2: + indices = (0, 255) + else: + indices = range(colors) + for i in indices: + rgb = read(lutsize)[:3] + if rgb != chr(i)*3: + greyscale = 0 + palette.append(rgb) + if greyscale: + if colors == 2: + self.mode = rawmode = "1" + else: + self.mode = rawmode = "L" + else: + self.mode = "P" + self.palette = ImagePalette.raw( + "BGR", string.join(palette, "") + ) + + if not offset: + offset = self.fp.tell() + + self.tile = [("raw", + (0, 0) + self.size, + offset, + (rawmode, ((self.size[0]*bits+31)>>3)&(~3), -1))] + + self.info["compression"] = compression + + def _open(self): + + # HEAD + s = self.fp.read(14) + if s[:2] != "BM": + raise SyntaxError("Not a BMP file") + offset = i32(s[10:]) + + self._bitmap(offset=offset) + + +class DibImageFile(BmpImageFile): + + format = "DIB" + format_description = "Windows Bitmap" + + def _open(self): + self._bitmap() + +# +# -------------------------------------------------------------------- +# Write BMP file + +def o16(i): + return chr(i&255) + chr(i>>8&255) + +def o32(i): + return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255) + +SAVE = { + "1": ("1", 1, 2), + "L": ("L", 8, 256), + "P": ("P", 8, 256), + "RGB": ("BGR", 24, 0), +} + +def _save(im, fp, filename, check=0): + + try: + rawmode, bits, colors = SAVE[im.mode] + except KeyError: + raise IOError("cannot write mode %s as BMP" % im.mode) + + if check: + return check + + stride = ((im.size[0]*bits+7)/8+3)&(~3) + header = 40 # or 64 for OS/2 version 2 + offset = 14 + header + colors * 4 + image = stride * im.size[1] + + # bitmap header + fp.write("BM" + # file type (magic) + o32(offset+image) + # file size + o32(0) + # reserved + o32(offset)) # image data offset + + # bitmap info header + fp.write(o32(header) + # info header size + o32(im.size[0]) + # width + o32(im.size[1]) + # height + o16(1) + # planes + o16(bits) + # depth + o32(0) + # compression (0=uncompressed) + o32(image) + # size of bitmap + o32(1) + o32(1) + # resolution + o32(colors) + # colors used + o32(colors)) # colors important + + fp.write("\000" * (header - 40)) # padding (for OS/2 format) + + if im.mode == "1": + for i in (0, 255): + fp.write(chr(i) * 4) + elif im.mode == "L": + for i in range(256): + fp.write(chr(i) * 4) + elif im.mode == "P": + fp.write(im.im.getpalette("RGB", "BGRX")) + + ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))]) + +# +# -------------------------------------------------------------------- +# Registry + +Image.register_open(BmpImageFile.format, BmpImageFile, _accept) +Image.register_save(BmpImageFile.format, _save) + +Image.register_extension(BmpImageFile.format, ".bmp") |