| Home | Trees | Indices | Help |
|
|---|
|
|
1 """
2 :mod:`pyffi.formats.dds` --- DirectDraw Surface (.dds)
3 ======================================================
4
5 Implementation
6 --------------
7
8 .. autoclass:: DdsFormat
9 :show-inheritance:
10 :members:
11
12 Regression tests
13 ----------------
14
15 Read a DDS file
16 ^^^^^^^^^^^^^^^
17
18 >>> # check and read dds file
19 >>> stream = open('tests/dds/test.dds', 'rb')
20 >>> data = DdsFormat.Data()
21 >>> data.inspect(stream)
22 >>> data.header.pixel_format.size
23 32
24 >>> data.header.height
25 20
26 >>> data.read(stream)
27 >>> len(data.pixeldata.get_value())
28 888
29
30 Parse all DDS files in a directory tree
31 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32
33 >>> for stream, data in DdsFormat.walkData('tests/dds'):
34 ... print(stream.name)
35 tests/dds/test.dds
36
37 Create a DDS file from scratch and write to file
38 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39
40 >>> data = DdsFormat.Data()
41 >>> from tempfile import TemporaryFile
42 >>> stream = TemporaryFile()
43 >>> data.write(stream)
44
45 Get list of versions
46 ^^^^^^^^^^^^^^^^^^^^
47
48 >>> for vnum in sorted(DdsFormat.versions.values()):
49 ... print('0x%08X' % vnum)
50 0x09000000
51 0x0A000000
52 """
53
54 # ***** BEGIN LICENSE BLOCK *****
55 #
56 # Copyright (c) 2007-2011, Python File Format Interface
57 # All rights reserved.
58 #
59 # Redistribution and use in source and binary forms, with or without
60 # modification, are permitted provided that the following conditions
61 # are met:
62 #
63 # * Redistributions of source code must retain the above copyright
64 # notice, this list of conditions and the following disclaimer.
65 #
66 # * Redistributions in binary form must reproduce the above
67 # copyright notice, this list of conditions and the following
68 # disclaimer in the documentation and/or other materials provided
69 # with the distribution.
70 #
71 # * Neither the name of the Python File Format Interface
72 # project nor the names of its contributors may be used to endorse
73 # or promote products derived from this software without specific
74 # prior written permission.
75 #
76 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
77 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
78 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
79 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
80 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
81 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
82 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
83 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
84 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
86 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
87 # POSSIBILITY OF SUCH DAMAGE.
88 #
89 # ***** END LICENSE BLOCK *****
90
91 import struct
92 import os
93 import re
94
95 import pyffi.object_models.xml
96 import pyffi.object_models.common
97 from pyffi.object_models.xml.basic import BasicBase
98 import pyffi.object_models
99 from pyffi.utils.graph import EdgeFilter
102 """This class implements the DDS format."""
103 xml_file_name = 'dds.xml'
104 # where to look for dds.xml and in what order:
105 # DDSXMLPATH env var, or DdsFormat module directory
106 xml_file_path = [os.getenv('DDSXMLPATH'), os.path.dirname(__file__)]
107 # file name regular expression match
108 RE_FILENAME = re.compile(r'^.*\.dds$', re.IGNORECASE)
109 # used for comparing floats
110 _EPSILON = 0.0001
111
112 # basic types
113 int = pyffi.object_models.common.Int
114 uint = pyffi.object_models.common.UInt
115 byte = pyffi.object_models.common.Byte
116 ubyte = pyffi.object_models.common.UByte
117 char = pyffi.object_models.common.Char
118 short = pyffi.object_models.common.Short
119 ushort = pyffi.object_models.common.UShort
120 float = pyffi.object_models.common.Float
121 PixelData = pyffi.object_models.common.UndecodedData
122
123 # implementation of dds-specific basic types
124
126 """Basic type which implements the header of a DDS file."""
129
132
134 return self.__str__()
135
137 """Return a hash value for this value.
138
139 :return: An immutable object that can be used as a hash.
140 """
141 return None
142
144 """Read header string from stream and check it.
145
146 :param stream: The stream to read from.
147 :type stream: file
148 """
149 hdrstr = stream.read(4)
150 # check if the string is correct
151 if hdrstr != "DDS ".encode("ascii"):
152 raise ValueError(
153 "invalid DDS header: expected 'DDS ' but got '%s'" % hdrstr)
154
156 """Write the header string to stream.
157
158 :param stream: The stream to write to.
159 :type stream: file
160 """
161 stream.write("DDS ".encode("ascii"))
162
169
170 @staticmethod
172 """Converts version string into an integer.
173
174 :param version_str: The version string.
175 :type version_str: str
176 :return: A version integer.
177
178 >>> hex(DdsFormat.version_number('DX10'))
179 '0xa000000'
180 """
181 return {'DX9': 0x09000000, 'DX10': 0x0A000000}[version_str]
182
184 """A class to contain the actual dds data."""
186 self.version = version
187 self.header = DdsFormat.Header()
188 self.pixeldata = DdsFormat.PixelData()
189
190 # TODO refactor xml model so we can get rid of these
191 self.user_version = 0
192 self.user_version2 = 0
193
195 """Quickly checks if stream contains DDS data, and gets the
196 version, by looking at the first 8 bytes.
197
198 :param stream: The stream to inspect.
199 :type stream: file
200 """
201 pos = stream.tell()
202 try:
203 hdrstr = stream.read(4)
204 if hdrstr != "DDS ".encode("ascii"):
205 raise ValueError("Not a DDS file.")
206 size = struct.unpack("<I", stream.read(4))
207 if size == 124:
208 self.version = 0x09000000 # DX9
209 elif size == 144:
210 self.version = 0x0A000000 # DX10
211 finally:
212 stream.seek(pos)
213
214 # overriding pyffi.object_models.FileFormat.Data methods
215
217 """Quickly checks if stream contains DDS data, and reads the
218 header.
219
220 :param stream: The stream to inspect.
221 :type stream: file
222 """
223 pos = stream.tell()
224 try:
225 self.inspect_quick(stream)
226 self.header.read(stream, data=self)
227 finally:
228 stream.seek(pos)
229
230
232 """Read a dds file.
233
234 :param stream: The stream from which to read.
235 :type stream: ``file``
236 :param verbose: The level of verbosity.
237 :type verbose: ``int``
238 """
239 # read the file
240 self.inspect_quick(stream)
241 self.header.read(stream, data=self)
242 self.pixeldata.read(stream, data=self)
243
244 # check if we are at the end of the file
245 if stream.read(1):
246 raise ValueError(
247 'end of file not reached: corrupt dds file?')
248
250 """Write a dds file.
251
252 :param stream: The stream to which to write.
253 :type stream: ``file``
254 :param verbose: The level of verbosity.
255 :type verbose: ``int``
256 """
257 # TODO: make sure pixel data has correct length
258
259 # write the file
260 # first header
261 self.header.write(stream, data=self)
262 # next the pixel data
263 self.pixeldata.write(stream, data=self)
264
265 # DetailNode
266
269
272
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Oct 10 19:04:07 2011 | http://epydoc.sourceforge.net |