Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tex_codec.cpp
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 for texture codecs
25  */
26 
27 #include "precompiled.h"
28 #include "tex_codec.h"
29 
30 #include <string.h>
31 #include <stdlib.h>
32 
33 #include "lib/allocators/shared_ptr.h" // ArrayDeleter
34 #include "tex.h"
35 
36 static const TexCodecVTbl* codecs;
37 
38 // add this vtbl to the codec list. called at NLSO init time by the
39 // TEX_CODEC_REGISTER in each codec file. note that call order and therefore
40 // order in the list is undefined, but since each codec only steps up if it
41 // can handle the given format, this is not a problem.
42 //
43 // returns int to alloc calling from a macro at file scope.
45 {
46  ENSURE(c);
47 
48  // insert at front of list.
49  c->next = codecs;
50  codecs = c;
51 
52  return 0; // (assigned to dummy variable)
53 }
54 
55 // remove all codecs that have been registered.
57 {
58  codecs = NULL;
59 }
60 
61 // find codec that recognizes the desired output file extension,
62 // or return ERR::TEX_UNKNOWN_FORMAT if unknown.
63 // note: does not raise a warning because it is used by
64 // tex_is_known_extension.
66 {
67  for(*c = codecs; *c; *c = (*c)->next)
68  {
69  // we found it
70  if((*c)->is_ext(extension))
71  return INFO::OK;
72  }
73 
74  return ERR::TEX_UNKNOWN_FORMAT; // NOWARN
75 }
76 
77 
78 // find codec that recognizes the header's magic field
79 Status tex_codec_for_header(const u8* file, size_t file_size, const TexCodecVTbl** c)
80 {
81  // we guarantee at least 4 bytes for is_hdr to look at
82  if(file_size < 4)
84 
85  for(*c = codecs; *c; *c = (*c)->next)
86  {
87  // we found it
88  if((*c)->is_hdr(file))
89  return INFO::OK;
90  }
91 
93 }
94 
95 
96 const TexCodecVTbl* tex_codec_next(const TexCodecVTbl* prev_codec)
97 {
98  // first time
99  if(!prev_codec)
100  return codecs;
101  // middle of list: return next (can be 0 to indicate end of list)
102  else
103  return prev_codec->next;
104 }
105 
106 
107 Status tex_codec_transform(Tex* t, size_t transforms)
108 {
110 
111  // find codec that understands the data, and transform
112  for(const TexCodecVTbl* c = codecs; c; c = c->next)
113  {
114  Status err = c->transform(t, transforms);
115  // success
116  if(err == INFO::OK)
117  return INFO::OK;
118  // something went wrong
119  else if(err != INFO::TEX_CODEC_CANNOT_HANDLE)
120  {
121  ret = err;
122  DEBUG_WARN_ERR(ERR::LOGIC); // codec indicates error
123  }
124  }
125 
126  return ret;
127 }
128 
129 
130 //-----------------------------------------------------------------------------
131 // helper functions used by codecs
132 //-----------------------------------------------------------------------------
133 
135 {
136 #define REGISTER_CODEC(name) extern void name##_register(); name##_register()
137  REGISTER_CODEC(bmp);
138  REGISTER_CODEC(dds);
139  REGISTER_CODEC(jpg);
140  REGISTER_CODEC(png);
141  REGISTER_CODEC(tga);
142 #undef REGISTER_CODEC
143 }
144 
145 // allocate an array of row pointers that point into the given texture data.
146 // <file_orientation> indicates whether the file format is top-down or
147 // bottom-up; the row array is inverted if necessary to match global
148 // orienatation. (this is more efficient than "transforming" later)
149 //
150 // used by PNG and JPG codecs.
151 //
152 // note: we don't allocate the data param ourselves because this function is
153 // needed for encoding, too (where data is already present).
154 std::vector<RowPtr> tex_codec_alloc_rows(const u8* data, size_t h, size_t pitch, size_t src_flags, size_t dst_orientation)
155 {
156  const bool flip = !tex_orientations_match(src_flags, dst_orientation);
157 
158  std::vector<RowPtr> rows(h);
159 
160  // determine start position and direction
161  RowPtr pos = flip? data+pitch*(h-1) : data;
162  const ssize_t add = flip? -(ssize_t)pitch : (ssize_t)pitch;
163  const RowPtr end = flip? data-pitch : data+pitch*h;
164 
165  for(size_t i = 0; i < h; i++)
166  {
167  rows[i] = pos;
168  pos += add;
169  }
170 
171  ENSURE(pos == end);
172  return rows;
173 }
174 
175 
176 Status tex_codec_write(Tex* t, size_t transforms, const void* hdr, size_t hdr_size, DynArray* da)
177 {
178  RETURN_STATUS_IF_ERR(tex_transform(t, transforms));
179 
180  void* img_data = tex_get_data(t); const size_t img_size = tex_img_size(t);
181  RETURN_STATUS_IF_ERR(da_append(da, hdr, hdr_size));
182  RETURN_STATUS_IF_ERR(da_append(da, img_data, img_size));
183  return INFO::OK;
184 }
#define u8
Definition: types.h:39
const Status LOGIC
Definition: status.h:409
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 Status TEX_CODEC_CANNOT_HANDLE
Definition: tex.h:132
const Status OK
Definition: status.h:386
const TexCodecVTbl * tex_codec_next(const TexCodecVTbl *prev_codec)
enumerate all registered codecs.
Definition: tex_codec.cpp:96
static const TexCodecVTbl * codecs
Definition: tex_codec.cpp:36
provides a memory range that can be expanded but doesn&#39;t waste physical memory or relocate itself...
Definition: dynarray.h:39
const Status TEX_INCOMPLETE_HEADER
Definition: tex.h:116
#define REGISTER_CODEC(name)
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
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
u8 * tex_get_data(const Tex *t)
rationale: since Tex is a struct, its fields are accessible to callers.
Definition: tex.cpp:629
bool tex_orientations_match(size_t src_flags, size_t dst_orientation)
indicate if the two vertical orientations match.
Definition: tex.cpp:548
const Status TEX_UNKNOWN_FORMAT
Definition: tex.h:115
Status da_append(DynArray *da, const void *data, size_t size)
&quot;write&quot; to array, i.e.
Definition: dynarray.cpp:139
i64 Status
Error handling system.
Definition: status.h:171
stores all data describing an image.
Definition: tex.h:210
intptr_t ssize_t
Definition: wposix_types.h:82
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
Definition: debug.h:331
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 WARN_RETURN(status)
Definition: status.h:255
void tex_codec_register_all()
Manually register codecs.
Definition: tex_codec.cpp:134
size_t tex_img_size(const Tex *t)
return total byte size of the image pixels.
Definition: tex.cpp:683
const u8 * RowPtr
allocate an array of row pointers that point into the given texture data.
Definition: tex_codec.h:228
Status tex_transform(Tex *t, size_t transforms)
Change &lt;t&gt;&#39;s pixel format.
Definition: tex.cpp:467
void tex_codec_unregister_all()
remove all codecs that have been registered.
Definition: tex_codec.cpp:56
virtual method table for TexCodecs.
Definition: tex_codec.h:39
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
#define RETURN_STATUS_IF_ERR(expression)
Definition: status.h:276