Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tex_codec.h
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * support routines and interface for texture codecs.
25  */
26 
27 #ifndef INCLUDED_TEX_CODEC
28 #define INCLUDED_TEX_CODEC
29 
30 #include "tex.h"
31 #include "tex_internal.h" // for codec's convenience
32 
33 /**
34  * virtual method table for TexCodecs.
35  * rationale: this works in C and also allows storing name and next in vtbl.
36  * 'template method'-style interface to increase code reuse and
37  * simplify writing new codecs.
38  **/
40 {
41  /**
42  * decode the file into a Tex structure.
43  *
44  * @param data input data array (non-const, because the texture
45  * may have to be flipped in-place - see "texture orientation").
46  * @param size [bytes] of data, always >= 4
47  * (this is usually enough to compare the header's "magic" field,
48  * and no legitimate file will be smaller)
49  * @param t output texture object
50  * @return Status
51  **/
52  Status (*decode)(u8* data, size_t size, Tex* RESTRICT t);
53 
54  /**
55  * encode the texture data into the codec's file format (in memory).
56  *
57  * @param t input texture object. note: non-const because encoding may
58  * require a tex_transform.
59  * @param da output data array, allocated by codec.
60  * rationale: some codecs cannot calculate the output size beforehand
61  * (e.g. PNG output via libpng), so the output memory cannot be allocated
62  * by the caller.
63  * @return Status
64  **/
66 
67  /**
68  * transform the texture's pixel format.
69  *
70  * @param t texture object
71  * @param transforms: OR-ed combination of TEX_* flags that are to
72  * be changed. note: the codec needs only handle situations specific
73  * to its format; generic pixel format transforms are handled by
74  * the caller.
75  **/
76  Status (*transform)(Tex* t, size_t transforms);
77 
78  /**
79  * indicate if the data appears to be an instance of this codec's header,
80  * i.e. can this codec decode it?
81  *
82  * @param file input data; only guaranteed to be 4 bytes!
83  * (this should be enough to examine the header's 'magic' field)
84  * @return bool
85  **/
86  bool (*is_hdr)(const u8* file);
87 
88  /**
89  * is the extension that of a file format supported by this codec?
90  *
91  * rationale: cannot just return the extension string and have
92  * caller compare it (-> smaller code) because a codec's file format
93  * may have several valid extensions (e.g. jpg and jpeg).
94  *
95  * @param extension (including '.')
96  * @return bool
97  **/
98  bool (*is_ext)(const OsPath& extension);
99 
100  /**
101  * return size of the file header supported by this codec.
102  *
103  * @param file the specific header to return length of (taking its
104  * variable-length fields into account). if NULL, return minimum
105  * guaranteed header size, i.e. the header without any
106  * variable-length fields.
107  * @return size [bytes]
108  **/
109  size_t (*hdr_size)(const u8* file);
110 
111  /**
112  * name of codec for debug purposes. typically set via TEX_CODEC_REGISTER.
113  **/
114  const wchar_t* name;
115 
116  /**
117  * intrusive linked-list of codecs: more convenient than fixed-size
118  * static storage.
119  * set by caller; should be initialized to NULL.
120  **/
122 };
123 
124 
125 /**
126  * build codec vtbl and register it. the codec will be queried for future
127  * texture load requests. call order is undefined, but since each codec
128  * only steps up if it can handle the given format, this is not a problem.
129  *
130  * @param name identifier of codec (not string!). used to bind 'member'
131  * functions prefixed with it to the vtbl, and as the TexCodecVTbl name.
132  * it should also mirror the default file extension (e.g. dds) -
133  * this is relied upon (but verified) in the self-test.
134  *
135  * usage: at file scope within the source file containing the codec's methods.
136  **/
137 #define TEX_CODEC_REGISTER(name)\
138  static TexCodecVTbl UID__ = \
139  {\
140  name##_decode, name##_encode, name##_transform,\
141  name##_is_hdr, name##_is_ext, name##_hdr_size,\
142  WIDEN(#name)\
143  };\
144  /*static int dummy = tex_codec_register(&vtbl);*/\
145  /* note: when building as a static library, pre-main initializers */\
146  /* will not run! as a workaround, we build an externally visible */\
147  /* registration function that must be called via */\
148  /* tex_codec_register_all - see comments there. */\
149  void name##_register() { tex_codec_register(&UID__); }
150 
151 
152 /**
153  * add this vtbl to the codec list. called at NLSO init time by the
154  * TEX_CODEC_REGISTER in each codec file.
155  * order in list is unspecified; see TEX_CODEC_REGISTER.
156  *
157  * @param c pointer to vtbl.
158  * @return int (allows calling from a macro at file scope; value is not used)
159  **/
160 extern int tex_codec_register(TexCodecVTbl* c);
161 
162 
163 /**
164  * Find codec that recognizes the desired output file extension.
165  *
166  * @param extension
167  * @param c (out) vtbl of responsible codec
168  * @return Status; ERR::RES_UNKNOWN_FORMAT (without warning, because this is
169  * called by tex_is_known_extension) if no codec indicates they can
170  * handle the given extension.
171  **/
172 extern Status tex_codec_for_filename(const OsPath& extension, const TexCodecVTbl** c);
173 
174 /**
175  * find codec that recognizes the header's magic field.
176  *
177  * @param data typically contents of file, but need only include the
178  * (first 4 bytes of) header.
179  * @param data_size [bytes]
180  * @param c (out) vtbl of responsible codec
181  * @return Status; ERR::RES_UNKNOWN_FORMAT if no codec indicates they can
182  * handle the given format (header).
183  **/
184 extern Status tex_codec_for_header(const u8* data, size_t data_size, const TexCodecVTbl** c);
185 
186 /**
187  * enumerate all registered codecs.
188  *
189  * used by self-test to test each one of them in turn.
190  *
191  * @param prev_codec the last codec returned by this function.
192  * pass 0 the first time.
193  * note: this routine is stateless and therefore reentrant.
194  * @return the next codec, or 0 if all have been returned.
195  **/
196 extern const TexCodecVTbl* tex_codec_next(const TexCodecVTbl* prev_codec);
197 
198 /**
199  * transform the texture's pixel format.
200  * tries each codec's transform method once, or until one indicates success.
201  *
202  * @param t texture object
203  * @param transforms: OR-ed combination of TEX_* flags that are to
204  * be changed.
205  * @return Status
206  **/
207 extern Status tex_codec_transform(Tex* t, size_t transforms);
208 
209 /**
210  * allocate an array of row pointers that point into the given texture data.
211  * for texture decoders that support output via row pointers (e.g. PNG),
212  * this allows flipping the image vertically (useful when matching bottom-up
213  * textures to a global orientation) directly, which is much more
214  * efficient than transforming later via copying all pixels.
215  *
216  * @param data the texture data into which row pointers will point.
217  * note: we don't allocate it here because this function is
218  * needed for encoding, too (where data is already present).
219  * @param h height [pixels] of texture.
220  * @param pitch size [bytes] of one texture row, i.e. width*bytes_per_pixel.
221  * @param src_flags TexFlags of source texture. used to extract its
222  * orientation.
223  * @param dst_orientation desired orientation of the output data.
224  * can be one of TEX_BOTTOM_UP, TEX_TOP_DOWN, or 0 for the
225  * "global orientation".
226  * depending on src and dst, the row array is flipped if necessary.
227  **/
228 typedef const u8* RowPtr;
229 extern std::vector<RowPtr> tex_codec_alloc_rows(const u8* data, size_t h, size_t pitch, size_t src_flags, size_t dst_orientation);
230 
231 /**
232  * apply transforms and then copy header and image into output buffer.
233  *
234  * @param t input texture object
235  * @param transforms transformations to be applied to pixel format
236  * @param hdr header data
237  * @param hdr_size [bytes]
238  * @param da output data array (will be expanded as necessary)
239  * @return Status
240  **/
241 extern Status tex_codec_write(Tex* t, size_t transforms, const void* hdr, size_t hdr_size, DynArray* da);
242 
243 #endif // #ifndef INCLUDED_TEX_CODEC
bool(* is_ext)(const OsPath &extension)
is the extension that of a file format supported by this codec?
Definition: tex_codec.h:98
Status(* transform)(Tex *t, size_t transforms)
transform the texture&#39;s pixel format.
Definition: tex_codec.h:76
#define u8
Definition: types.h:39
Status tex_codec_for_filename(const OsPath &extension, const TexCodecVTbl **c)
Find codec that recognizes the desired output file extension.
Definition: tex_codec.cpp:65
Status tex_codec_write(Tex *t, size_t transforms, const void *hdr, size_t hdr_size, DynArray *da)
apply transforms and then copy header and image into output buffer.
Definition: tex_codec.cpp:176
const TexCodecVTbl * tex_codec_next(const TexCodecVTbl *prev_codec)
enumerate all registered codecs.
Definition: tex_codec.cpp:96
Status(* encode)(Tex *RESTRICT t, DynArray *RESTRICT da)
encode the texture data into the codec&#39;s file format (in memory).
Definition: tex_codec.h:65
provides a memory range that can be expanded but doesn&#39;t waste physical memory or relocate itself...
Definition: dynarray.h:39
const wchar_t * name
name of codec for debug purposes.
Definition: tex_codec.h:114
Status(* decode)(u8 *data, size_t size, Tex *RESTRICT t)
decode the file into a Tex structure.
Definition: tex_codec.h:52
std::vector< RowPtr > tex_codec_alloc_rows(const u8 *data, size_t h, size_t pitch, size_t src_flags, size_t dst_orientation)
Definition: tex_codec.cpp:154
Definition: path.h:75
const TexCodecVTbl * next
intrusive linked-list of codecs: more convenient than fixed-size static storage.
Definition: tex_codec.h:121
bool(* is_hdr)(const u8 *file)
indicate if the data appears to be an instance of this codec&#39;s header, i.e.
Definition: tex_codec.h:86
i64 Status
Error handling system.
Definition: status.h:171
stores all data describing an image.
Definition: tex.h:210
Status tex_codec_transform(Tex *t, size_t transforms)
transform the texture&#39;s pixel format.
Definition: tex_codec.cpp:107
const char * extension
Definition: mongoose.cpp:1736
#define RESTRICT
const u8 * RowPtr
allocate an array of row pointers that point into the given texture data.
Definition: tex_codec.h:228
virtual method table for TexCodecs.
Definition: tex_codec.h:39
size_t(* hdr_size)(const u8 *file)
return size of the file header supported by this codec.
Definition: tex_codec.h:109
Status tex_codec_for_header(const u8 *file, size_t file_size, const TexCodecVTbl **c)
find codec that recognizes the header&#39;s magic field.
Definition: tex_codec.cpp:79
int tex_codec_register(TexCodecVTbl *c)
add this vtbl to the codec list.
Definition: tex_codec.cpp:44