Line data Source code
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 : **/
39 : class ITexCodec
40 : {
41 : public:
42 : /**
43 : * decode the file into a Tex structure.
44 : *
45 : * @param data input data array (non-const, because the texture
46 : * may have to be flipped in-place - see "texture orientation").
47 : * @param size [bytes] of data, always >= 4
48 : * (this is usually enough to compare the header's "magic" field,
49 : * and no legitimate file will be smaller)
50 : * @param t output texture object
51 : * @return Status
52 : **/
53 : virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const = 0;
54 :
55 : /**
56 : * encode the texture data into the codec's file format (in memory).
57 : *
58 : * @param t input texture object. note: non-const because encoding may
59 : * require a Tex::transform.
60 : * @param da output data array, allocated by codec.
61 : * rationale: some codecs cannot calculate the output size beforehand
62 : * (e.g. PNG output via libpng), so the output memory cannot be allocated
63 : * by the caller.
64 : * @return Status
65 : **/
66 : virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const = 0;
67 :
68 : /**
69 : * transform the texture's pixel format.
70 : *
71 : * @param t texture object
72 : * @param transforms: OR-ed combination of TEX_* flags that are to
73 : * be changed. note: the codec needs only handle situations specific
74 : * to its format; generic pixel format transforms are handled by
75 : * the caller.
76 : **/
77 : virtual Status transform(Tex* t, size_t transforms) const = 0;
78 :
79 : /**
80 : * indicate if the data appears to be an instance of this codec's header,
81 : * i.e. can this codec decode it?
82 : *
83 : * @param file input data; only guaranteed to be 4 bytes!
84 : * (this should be enough to examine the header's 'magic' field)
85 : * @return bool
86 : **/
87 : virtual bool is_hdr(const u8* file) const = 0;
88 :
89 : /**
90 : * is the extension that of a file format supported by this codec?
91 : *
92 : * rationale: cannot just return the extension string and have
93 : * caller compare it (-> smaller code) because a codec's file format
94 : * may have several valid extensions (e.g. jpg and jpeg).
95 : *
96 : * @param extension (including '.')
97 : * @return bool
98 : **/
99 : virtual bool is_ext(const OsPath& extension) const = 0;
100 :
101 : /**
102 : * return size of the file header supported by this codec.
103 : *
104 : * @param file the specific header to return length of (taking its
105 : * variable-length fields into account). if NULL, return minimum
106 : * guaranteed header size, i.e. the header without any
107 : * variable-length fields.
108 : * @return size [bytes]
109 : **/
110 : virtual size_t hdr_size(const u8* file) const = 0;
111 :
112 : /**
113 : * name of codec for debug purposes. typically set via TEX_CODEC_REGISTER.
114 : **/
115 : virtual const wchar_t* get_name() const = 0;
116 :
117 4 : virtual ~ITexCodec() {}
118 : };
119 :
120 1 : class TexCodecPng:ITexCodec {
121 : public:
122 : virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
123 : virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
124 : virtual Status transform(Tex* t, size_t transforms) const;
125 : virtual bool is_hdr(const u8* file) const;
126 : virtual bool is_ext(const OsPath& extension) const;
127 : virtual size_t hdr_size(const u8* file) const;
128 0 : virtual const wchar_t* get_name() const {
129 : static const wchar_t *name = L"png";
130 0 : return name;
131 : };
132 : };
133 :
134 1 : class TexCodecDds:ITexCodec {
135 : public:
136 : virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
137 : virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
138 : virtual Status transform(Tex* t, size_t transforms) const;
139 : virtual bool is_hdr(const u8* file) const;
140 : virtual bool is_ext(const OsPath& extension) const;
141 : virtual size_t hdr_size(const u8* file) const;
142 0 : virtual const wchar_t* get_name() const {
143 : static const wchar_t *name = L"dds";
144 0 : return name;
145 : };
146 : };
147 :
148 1 : class TexCodecTga:ITexCodec {
149 : public:
150 : virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
151 : virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
152 : virtual Status transform(Tex* t, size_t transforms) const;
153 : virtual bool is_hdr(const u8* file) const;
154 : virtual bool is_ext(const OsPath& extension) const;
155 : virtual size_t hdr_size(const u8* file) const;
156 0 : virtual const wchar_t* get_name() const {
157 : static const wchar_t *name = L"tga";
158 0 : return name;
159 : };
160 : };
161 :
162 1 : class TexCodecBmp:ITexCodec {
163 : public:
164 : virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
165 : virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
166 : virtual Status transform(Tex* t, size_t transforms) const;
167 : virtual bool is_hdr(const u8* file) const;
168 : virtual bool is_ext(const OsPath& extension) const;
169 : virtual size_t hdr_size(const u8* file) const;
170 0 : virtual const wchar_t* get_name() const {
171 : static const wchar_t *name = L"bmp";
172 0 : return name;
173 : };
174 : };
175 :
176 : /**
177 : * Find codec that recognizes the desired output file extension.
178 : *
179 : * @param extension
180 : * @param c (out) vtbl of responsible codec
181 : * @return Status; ERR::RES_UNKNOWN_FORMAT (without warning, because this is
182 : * called by tex_is_known_extension) if no codec indicates they can
183 : * handle the given extension.
184 : **/
185 : extern Status tex_codec_for_filename(const OsPath& extension, const ITexCodec** c);
186 :
187 : /**
188 : * find codec that recognizes the header's magic field.
189 : *
190 : * @param data typically contents of file, but need only include the
191 : * (first 4 bytes of) header.
192 : * @param data_size [bytes]
193 : * @param c (out) vtbl of responsible codec
194 : * @return Status; ERR::RES_UNKNOWN_FORMAT if no codec indicates they can
195 : * handle the given format (header).
196 : **/
197 : extern Status tex_codec_for_header(const u8* data, size_t data_size, const ITexCodec** c);
198 :
199 : /**
200 : * transform the texture's pixel format.
201 : * tries each codec's transform method once, or until one indicates success.
202 : *
203 : * @param t texture object
204 : * @param transforms: OR-ed combination of TEX_* flags that are to
205 : * be changed.
206 : * @return Status
207 : **/
208 : extern Status tex_codec_transform(Tex* t, size_t transforms);
209 :
210 : /**
211 : * allocate an array of row pointers that point into the given texture data.
212 : * for texture decoders that support output via row pointers (e.g. PNG),
213 : * this allows flipping the image vertically (useful when matching bottom-up
214 : * textures to a global orientation) directly, which is much more
215 : * efficient than transforming later via copying all pixels.
216 : *
217 : * @param data the texture data into which row pointers will point.
218 : * note: we don't allocate it here because this function is
219 : * needed for encoding, too (where data is already present).
220 : * @param h height [pixels] of texture.
221 : * @param pitch size [bytes] of one texture row, i.e. width*bytes_per_pixel.
222 : * @param src_flags TexFlags of source texture. used to extract its
223 : * orientation.
224 : * @param dst_orientation desired orientation of the output data.
225 : * can be one of TEX_BOTTOM_UP, TEX_TOP_DOWN, or 0 for the
226 : * "global orientation".
227 : * depending on src and dst, the row array is flipped if necessary.
228 : **/
229 : typedef const u8* RowPtr;
230 : 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);
231 :
232 : /**
233 : * apply transforms and then copy header and image into output buffer.
234 : *
235 : * @param t input texture object
236 : * @param transforms transformations to be applied to pixel format
237 : * @param hdr header data
238 : * @param hdr_size [bytes]
239 : * @param da output data array (will be expanded as necessary)
240 : * @return Status
241 : **/
242 : extern Status tex_codec_write(Tex* t, size_t transforms, const void* hdr, size_t hdr_size, DynArray* da);
243 :
244 : #endif // #ifndef INCLUDED_TEX_CODEC
|