[Image-SIG] BMP color palette bug fix
Su, Yuan-Liang
zsu@iii.org.tw
Thu, 4 Jun 1998 09:30:19 +0800
This is a multi-part message in MIME format.
------=_NextPart_000_0027_01BD8F9B.63CC05E0
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_0028_01BD8F9B.63CC05E0"
------=_NextPart_001_0028_01BD8F9B.63CC05E0
Content-Type: text/plain;
charset="big5"
Content-Transfer-Encoding: quoted-printable
There is a bug in BmpImagePlugin.py module which is caused
by ignoring the palette size field in BMP header.
I mark the changed parts with #!+ for addition and #!* for
modification.
Su, Yuan-Liang
Institute for Infomation Industry
------=_NextPart_001_0028_01BD8F9B.63CC05E0
Content-Type: text/html;
charset="big5"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML//EN">
<HTML>
<HEAD>
<META content=3Dtext/html;charset=3Dbig5 http-equiv=3DContent-Type>
<META content=3D'"MSHTML 4.72.2106.11"' name=3DGENERATOR>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3D=B7s=B2=D3=A9=FA=C5=E9 size=3D2>There is a bug in =
BmpImagePlugin.py module which is=20
caused</FONT></DIV>
<DIV><FONT face=3D=B7s=B2=D3=A9=FA=C5=E9 size=3D2>by ignoring the =
palette size field in BMP=20
header.</FONT></DIV>
<DIV><FONT face=3D=B7s=B2=D3=A9=FA=C5=E9 size=3D2></FONT> </DIV>
<DIV><FONT face=3D=B7s=B2=D3=A9=FA=C5=E9 size=3D2>I mark the changed =
parts with #!+ for addition and=20
#!* for</FONT></DIV>
<DIV><FONT face=3D=B7s=B2=D3=A9=FA=C5=E9 =
size=3D2>modification.</FONT></DIV>
<DIV><FONT face=3D=B7s=B2=D3=A9=FA=C5=E9 size=3D2></FONT> </DIV>
<DIV><FONT face=3D=B7s=B2=D3=A9=FA=C5=E9 size=3D2>Su, =
Yuan-Liang</FONT></DIV>
<DIV><FONT face=3D=B7s=B2=D3=A9=FA=C5=E9 size=3D2>Institute for =
Infomation=20
Industry</FONT></DIV></BODY></HTML>
------=_NextPart_001_0028_01BD8F9B.63CC05E0--
------=_NextPart_000_0027_01BD8F9B.63CC05E0
Content-Type: application/octet-stream;
name="BmpImagePlugin.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="BmpImagePlugin.py"
#
# The Python Imaging Library.
# $Id: BmpImagePlugin.py,v 1.5 1996/11/10 17:52:14 fredrik Exp $
#
# BMP file handler
#
# Windows (and OS/2) native bitmap storage format.
#
# History:
# 95-09-01 fl Created
# 96-04-30 fl Added save
#
# Copyright (c) Fredrik Lundh 1995-96. All rights reserved.
#
# See the README file for information on usage and redistribution.
#
__version__ =3D "0.1"
import array
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 =3D {
1: ("1", "1"),
4: ("P", "P;4"),
8: ("P", "P"),
24: ("RGB", "BGR")
}
def _accept(prefix):
return prefix[:2] =3D=3D "BM"
class BmpImageFile(ImageFile.ImageFile):
format =3D "BMP"
format_description =3D "Windows Bitmap"
def _bitmap(self, header =3D 0, offset =3D 0):
if header:
self.fp.seek(header)
# CORE/INFO
s =3D self.fp.read(4)
s =3D s + self.fp.read(i32(s)-4)
colors =3D 0
if len(s) =3D=3D 12:
# OS/2 1.0 CORE
bits =3D i16(s[10:])
self.size =3D i16(s[4:]), i16(s[6:])
lutsize =3D 3
elif len(s) in [40, 64]:
# WIN 3.1 or OS/2 2.0 INFO
bits =3D i16(s[14:])
self.size =3D i32(s[4:]), i32(s[8:])
self.info["compression"] =3D i32(s[16:])
#!+ Su, Yuan-Liang
colors =3D i32(s[32:])
#!!
lutsize =3D 4
else:
raise IOError, "Unknown BMP header type"
# MODE
try:
self.mode, rawmode =3D BIT2MODE[bits]
except KeyError:
raise IOError, "Unsupported BMP pixel depth"
# LUT
if self.mode !=3D "RGB":
#!* Su, Yuan-Liang
if colors =3D=3D 0:
colors =3D 1<<bits
#!!
if lutsize =3D=3D 3:
self.palette =3D ImagePalette.raw("BGR", self.fp.read(colors*3))
else:
self.palette =3D ImagePalette.raw("BGRX", self.fp.read(colors*4))
if self.mode =3D=3D "L":
self.mode =3D "P"
if offset =3D=3D 0:
offset =3D self.fp.tell()
=09
self.tile =3D [("raw",
(0, 0) + self.size,
offset,
(rawmode, ((self.size[0]*bits+31)>>3)&(-4), -1))]
def _open(self):
# HEAD
s =3D self.fp.read(14)
if s[:2] !=3D "BM":
raise SyntaxError, "Not a BMP file"
offset =3D i32(s[10:])
#!* Su, Yuan-Liang
self._bitmap(0, offset)
#!!
#
# --------------------------------------------------------------------
# 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)
def _save(im, fp, filename):
if im.mode =3D=3D "1":
rawmode, bits, colors =3D "1I", 1, 2
elif im.mode in ["L", "P"]:
rawmode, bits, colors =3D "L", 8, 256
elif im.mode =3D=3D "RGB":
rawmode, bits, colors =3D "BGR", 24, 0
else:
raise IOError, "cannot write mode %s as BMP" % im.mode
stride =3D ((im.size[0]*bits+7)/8+3)&-4
header =3D 40 # or 64 for OS/2 version 2
offset =3D 14 + header + colors * 4
image =3D 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=3Duncompressed)
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 =3D=3D "1":
for i in (0, 255):
fp.write(chr(i) * 4)
elif im.mode =3D=3D "L":
for i in range(256):
fp.write(chr(i) * 4)
elif im.mode =3D=3D "P":
fp.write(im.im.getpalette("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")
------=_NextPart_000_0027_01BD8F9B.63CC05E0--