Line data Source code
1 : /* Copyright (C) 2014 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 : // Statically allocate all of the codecs...
37 1 : TexCodecDds DdsCodec;
38 1 : TexCodecPng PngCodec;
39 1 : TexCodecTga TgaCodec;
40 1 : TexCodecBmp BmpCodec;
41 : // Codecs will be searched in this order
42 : static const ITexCodec *codecs[] = {(ITexCodec *)&DdsCodec, (ITexCodec *)&PngCodec,
43 : (ITexCodec *)&TgaCodec, (ITexCodec *)&BmpCodec};
44 : static const int codecs_len = sizeof(codecs) / sizeof(ITexCodec*);
45 :
46 : // find codec that recognizes the desired output file extension,
47 : // or return ERR::TEX_UNKNOWN_FORMAT if unknown.
48 : // note: does not raise a warning because it is used by
49 : // tex_is_known_extension.
50 0 : Status tex_codec_for_filename(const OsPath& extension, const ITexCodec** c)
51 : {
52 0 : for(int i = 0; i < codecs_len; ++i)
53 : {
54 : // we found it
55 0 : if(codecs[i]->is_ext(extension)) {
56 0 : *c = codecs[i];
57 0 : return INFO::OK;
58 : }
59 : }
60 :
61 0 : return ERR::TEX_UNKNOWN_FORMAT; // NOWARN
62 : }
63 :
64 :
65 : // find codec that recognizes the header's magic field
66 14 : Status tex_codec_for_header(const u8* file, size_t file_size, const ITexCodec** c)
67 : {
68 : // we guarantee at least 4 bytes for is_hdr to look at
69 14 : if(file_size < 4)
70 0 : return ERR::TEX_INCOMPLETE_HEADER;
71 :
72 19 : for(int i = 0; i < codecs_len; ++i)
73 : {
74 : // we found it
75 19 : if(codecs[i]->is_hdr(file)) {
76 14 : *c = codecs[i];
77 14 : return INFO::OK;
78 : }
79 : }
80 :
81 0 : return ERR::TEX_UNKNOWN_FORMAT;
82 : }
83 :
84 30 : Status tex_codec_transform(Tex* t, size_t transforms)
85 : {
86 30 : Status ret = INFO::TEX_CODEC_CANNOT_HANDLE;
87 :
88 : // find codec that understands the data, and transform
89 82 : for(int i = 0; i < codecs_len; ++i)
90 : {
91 69 : Status err = codecs[i]->transform(t, transforms);
92 : // success
93 69 : if(err == INFO::OK)
94 17 : return INFO::OK;
95 : // something went wrong
96 52 : else if(err != INFO::TEX_CODEC_CANNOT_HANDLE)
97 : {
98 0 : ret = err;
99 0 : DEBUG_WARN_ERR(ERR::LOGIC); // codec indicates error
100 : }
101 : }
102 :
103 13 : return ret;
104 : }
105 :
106 :
107 : //-----------------------------------------------------------------------------
108 : // helper functions used by codecs
109 : //-----------------------------------------------------------------------------
110 :
111 : // allocate an array of row pointers that point into the given texture data.
112 : // <file_orientation> indicates whether the file format is top-down or
113 : // bottom-up; the row array is inverted if necessary to match global
114 : // orienatation. (this is more efficient than "transforming" later)
115 : //
116 : // used by PNG and JPG codecs.
117 : //
118 : // note: we don't allocate the data param ourselves because this function is
119 : // needed for encoding, too (where data is already present).
120 3 : std::vector<RowPtr> tex_codec_alloc_rows(const u8* data, size_t h, size_t pitch, size_t src_flags, size_t dst_orientation)
121 : {
122 3 : const bool flip = !tex_orientations_match(src_flags, dst_orientation);
123 :
124 3 : std::vector<RowPtr> rows(h);
125 :
126 : // determine start position and direction
127 3 : RowPtr pos = flip? data+pitch*(h-1) : data;
128 3 : const ssize_t add = flip? -(ssize_t)pitch : (ssize_t)pitch;
129 3 : const RowPtr end = flip? data-pitch : data+pitch*h;
130 :
131 75 : for(size_t i = 0; i < h; i++)
132 : {
133 72 : rows[i] = pos;
134 72 : pos += add;
135 : }
136 :
137 3 : ENSURE(pos == end);
138 3 : return rows;
139 : }
140 :
141 :
142 0 : Status tex_codec_write(Tex* t, size_t transforms, const void* hdr, size_t hdr_size, DynArray* da)
143 : {
144 0 : RETURN_STATUS_IF_ERR(t->transform(transforms));
145 :
146 0 : void* img_data = t->get_data(); const size_t img_size = t->img_size();
147 0 : RETURN_STATUS_IF_ERR(da_append(da, hdr, hdr_size));
148 0 : RETURN_STATUS_IF_ERR(da_append(da, img_data, img_size));
149 0 : return INFO::OK;
150 3 : }
|