[Image-SIG] Re: WAL file format

Fredrik Lundh fredrik@pythonware.com
Wed, 23 Apr 2003 07:09:58 +0200


Derek Simkowiak wrote:

> I need the ability to load Id Software "WAL" files.  WAL images are the
> file format used by Id Software for Quake2 texture maps.  They are an
> indexed image format (like GIF) and do not have any compression, and the
> file format includes several copies of the image for use as a "mipmap".
>
> Looking in the appendix, that format does not appear to be supported.
>
> I currently have some C code that will load WAL files.  I have been
> using it successfully for some time.  It is basic, and only loads the
> "master" copy of the image (it does not look at the mipmaps, because all
> modern video cards generate their own mipmaps through OpenGL or DirectX).
>
> I am re-architecting my 3D game engine to use PIL, so that I can
> support all the other image types as textures.  But since PIL does not
> support WAL files, I'm in a bad spot.

reading uncompressed formats with PIL is usually trivial.  this
document tells you how to write a "real" image plugin:

http://www.pythonware.com/library/pil/handbook/writing-your-own-file-decoder.htm


here's a 5-minute hack (a single function, not an ImagePlugin) that
might work.  if it doesn't, feel free to tweak as necessary:

# WAL reader (untested), based on specification available from:
# http://www.flipcode.com/tutorials/tut_q2levels.shtml

import Image

def i32(c, o=0):
    return ord(c[o])+(ord(c[o+1])<<8)+(ord(c[o+2])<<16)+(ord(c[o+3])<<24)

##
# Load first texture from a WAL file.
#
# @param filename WAL file name.
# @param palette Palette to use for this file.  The palette is
#     a list of 768 colour values, given as [R, G, B, R, G, B, ...]
# @return An image instance.

def load(filename, palette):

    fp = open(filename, "rb")

    # read header fields
    header = fp.read(32+24+32+12)
    name = header[:32]
    size = i32(header, 32), i32(header, 36)
    offset = i32(header, 40)

    # load pixel data
    fp.seek(offset)
    # or maybe fp.seek(offset, 1) ?

    im = Image.fromstring("P", size, fp.read(size[0] * size[1]))
    im.putpalette(palette)

    return im

</F>