Manually delete textures at shutdown.
[bsnes:xml-shaders.git] / reference / texreader.py
1 #!/usr/bin/python
2 import re
3 import string
4 from OpenGL.GL import *
5
6 TOKEN_RE = re.compile("[^" + string.whitespace + "]+")
7 WS_RE = re.compile("[" + string.whitespace + "]+")
8
9
10 class TexReaderException(Exception):
11         pass
12
13
14 class Texture(object):
15
16         def __init__(self, width, height, pixels=None):
17                 self.textureID = glGenTextures(1)
18                 self.width = width
19                 self.height = height
20
21                 glBindTexture(GL_TEXTURE_2D, self.textureID)
22
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)
27
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)
30
31         def destroy(self):
32                 if self.textureID != None:
33                         glDeleteTextures([self.textureID])
34                         self.textureID = None
35                         self.width = None
36                         self.height = None
37
38         def __del__(self):
39                 self.destroy()
40
41
42 def parse_ppm(data):
43         """
44         Parse the PPM data from the given byte string.
45         """
46         try:
47                 magic, widthStr, heightStr, sampleMaxStr, pixelData = \
48                                 data.split(None, 4)
49         except ValueError:
50                 raise TexReaderException("Can't parse data: %r..." % (data[:40],))
51
52         if magic != "P6":
53                 raise TexReaderException("Unrecognised magic %r" % (magic,))
54
55         try:
56                 width = int(widthStr)
57                 height = int(heightStr)
58                 sampleMax = int(sampleMaxStr)
59         except ValueError, e:
60                 raise TexReaderException("Can't parse data: %s" % (str(e),))
61
62         if sampleMax != 255:
63                 raise TexReaderException("Textures must have 8 bits per channel.")
64
65         if len(pixelData) != (width * height * 3):
66                 raise TexReaderException("Got %d bytes of pixel data, expected %d"
67                                 % (len(pixelData), width * height * 3))
68
69         # Now to convert this packed RGB pixel data to RGBA data that OpenGL can
70         # understand.
71         pixels = []
72         for pxOffset in range(0, (width * height * 3), 3):
73                 pixels.append(pixelData[pxOffset:pxOffset+3])
74                 pixels.append("\xff")
75
76         return (width, height, "".join(pixels))
77
78
79 def textureFromFile(filename):
80         with open(filename, "rb") as handle:
81                 width, height, pixels = parse_ppm(handle.read())
82
83         return Texture(width, height, pixels)
84
85
86 if __name__ == "__main__":
87         import sys
88         with open(sys.argv[1]) as handle:
89                 data = handle.read()
90                 print parse_ppm(data)