4 from OpenGL.GL import *
6 TOKEN_RE = re.compile("[^" + string.whitespace + "]+")
7 WS_RE = re.compile("[" + string.whitespace + "]+")
10 class TexReaderException(Exception):
14 class Texture(object):
16 def __init__(self, width, height, pixels=None):
17 self.textureID = glGenTextures(1)
21 glBindTexture(GL_TEXTURE_2D, self.textureID)
23 # We assume the GL implementation can handle non-power-of-two textures,
24 # so we use the image dimensions directly as texture dimensions.
25 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
26 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels)
28 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
29 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
32 if self.textureID != None:
33 glDeleteTextures([self.textureID])
44 Parse the PPM data from the given byte string.
47 magic, widthStr, heightStr, sampleMaxStr, pixelData = \
50 raise TexReaderException("Can't parse data: %r..." % (data[:40],))
53 raise TexReaderException("Unrecognised magic %r" % (magic,))
57 height = int(heightStr)
58 sampleMax = int(sampleMaxStr)
60 raise TexReaderException("Can't parse data: %s" % (str(e),))
63 raise TexReaderException("Textures must have 8 bits per channel.")
65 if len(pixelData) != (width * height * 3):
66 raise TexReaderException("Got %d bytes of pixel data, expected %d"
67 % (len(pixelData), width * height * 3))
69 # Now to convert this packed RGB pixel data to RGBA data that OpenGL can
72 for pxOffset in range(0, (width * height * 3), 3):
73 pixels.append(pixelData[pxOffset:pxOffset+3])
76 return (width, height, "".join(pixels))
79 def textureFromFile(filename):
80 with open(filename, "rb") as handle:
81 width, height, pixels = parse_ppm(handle.read())
83 return Texture(width, height, pixels)
86 if __name__ == "__main__":
88 with open(sys.argv[1]) as handle: