4 from OpenGL.GL import *
6 TOKEN_RE = re.compile("[^" + string.whitespace + "]+")
7 WS_RE = re.compile("[" + string.whitespace + "]+")
10 class TexReaderException(Exception):
16 Return the first power-of-two greater than a given number.
18 Assumes numbers will fit in 32-bit integers; most graphics cards have
19 maximum texture sizes vastly smaller than 2**32, so this should be fine.
26 number |= number >> 16
32 class Texture(object):
34 def __init__(self, width, height, pixels=None):
35 self.textureID = glGenTextures(1)
36 self.imageWidth = width
37 self.imageHeight = height
38 self.textureWidth = next_pot(width)
39 self.textureHeight = next_pot(height)
41 glBindTexture(GL_TEXTURE_2D, self.textureID)
44 GL_TEXTURE_2D, # target
46 GL_RGBA, # internal format
47 self.textureWidth, self.textureHeight,
49 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
55 GL_TEXTURE_2D, # target
57 0, 0, # (xoffset, yoffset)
58 self.imageWidth, self.imageHeight,
59 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
63 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
64 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
67 if self.textureID != None:
68 glDeleteTextures([self.textureID])
70 self.imageWidth = None
71 self.imageHeight = None
72 self.textureWidth = None
73 self.textureHeight = None
81 Parse the PPM data from the given byte string.
84 magic, widthStr, heightStr, sampleMaxStr, pixelData = \
87 raise TexReaderException("Can't parse data: %r..." % (data[:40],))
90 raise TexReaderException("Unrecognised magic %r" % (magic,))
94 height = int(heightStr)
95 sampleMax = int(sampleMaxStr)
97 raise TexReaderException("Can't parse data: %s" % (str(e),))
100 raise TexReaderException("Textures must have 8 bits per channel.")
102 if len(pixelData) != (width * height * 3):
103 raise TexReaderException("Got %d bytes of pixel data, expected %d"
104 % (len(pixelData), width * height * 3))
106 # Now to convert this packed RGB pixel data to RGBA data that OpenGL can
109 for pxOffset in range(0, (width * height * 3), 3):
110 pixels.append(pixelData[pxOffset:pxOffset+3])
111 pixels.append("\xff")
113 return (width, height, "".join(pixels))
116 def textureFromFile(filename):
117 with open(filename, "rb") as handle:
118 width, height, pixels = parse_ppm(handle.read())
120 return Texture(width, height, pixels)
123 if __name__ == "__main__":
125 with open(sys.argv[1]) as handle:
127 print parse_ppm(data)