Simple Image Loading LibrarY 0.1.0
SILLYTGAImageLoader.cpp
1/***********************************************************************
2 filename: SILLYTGAImageLoader.cpp
3 created: 11 Jun 2006
4 author: Olivier Delannoy
5
6 purpose: Load TGA Image
7*************************************************************************/
8/***************************************************************************
9 * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining
12 * a copy of this software and associated documentation files (the
13 * "Software"), to deal in the Software without restriction, including
14 * without limitation the rights to use, copy, modify, merge, publish,
15 * distribute, sublicense, and/or sell copies of the Software, and to
16 * permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be
20 * included in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 ***************************************************************************/
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#include "loaders/SILLYTGAImageLoader.h"
35
36#ifndef SILLY_OPT_INLINE
37#define inline
38#include "loaders/SILLYTGAImageLoader.icpp"
39#undef inline
40#endif
41#include "SILLYDataSource.h"
42#include "loaders/SILLYTGAImageContext.h"
43
44#include <cstring>
45#include <cstdio>
46
47// Start section of namespace SILLY
48namespace SILLY
49{
50
51TGAImageLoader::TGAImageLoader()
52 : ImageLoader("TGA Image loader (builtin)")
53{
54}
55
56TGAImageLoader::~TGAImageLoader()
57{
58}
59
60#ifdef SILLY_BE
61#define READ_WORD(res, start) \
62 (res) = 0; \
63 (res) = data->getDataPtr()[(start) + 1]; \
64 (res) = (res) << 8; \
65 (res) |= data->getDataPtr()[(start)];
66#else
67#define READ_WORD(res, start) \
68 (res) = 0; \
69 (res) = data->getDataPtr()[(start)]; \
70 (res) = (res) << 8; \
71 (res) |= data->getDataPtr()[(start) + 1];
72#endif
73
74ImageContext* TGAImageLoader::loadHeader(PixelFormat& formatSource, DataSource* data)
75{
76 byte idLength = data->getDataPtr()[0];
77 byte colorMapType = data->getDataPtr()[1];
78 byte imageType = data->getDataPtr()[2];
79 size_t width;
80 size_t height;
81 byte depth;
82 byte description;
83 if ((imageType != 2 && imageType != 10) || colorMapType)
84 {
85 // Unsupported image format
86 return 0;
87 }
88 // offset: 3 Skip color map + 5 bytes
89 // offset: 8 Skip xorg / yorg + 4 bytes
90#ifdef SILLY_BE
91 width = data->getDataPtr()[12];
92 width = width << 8;
93 width |= data->getDataPtr()[13];
94 height = data->getDataPtr()[14];
95 height = height << 8;
96 height |= data->getDataPtr()[15];
97#else
98 width = data->getDataPtr()[13];
99 width = width << 8;
100 width |= data->getDataPtr()[12];
101 height = data->getDataPtr()[15];
102 height = height << 8;
103 height |= data->getDataPtr()[14];
104#endif
105 depth = data->getDataPtr()[16] >> 3;
106 switch (depth)
107 {
108 case 2:
109 formatSource = PF_A1B5G5R5;
110 break;
111 case 3:
112 formatSource = PF_RGB;
113 break;
114 case 4:
115 formatSource = PF_RGBA;
116 break;
117 default:
118 return 0;
119 }
120 description = (*data)[17];
121
122
123 TGAImageContext* context = new TGAImageContext(width, height);
124 if (context)
125 {
126 context->d_idLength = idLength;
127 context->d_imageType = imageType;
128 context->d_depth = depth;
129 context->d_description = description;
130 }
131 return context;
132}
133
134bool TGAImageLoader::loadImageData(PixelOrigin origin, DataSource* data, ImageContext* context)
135{
136 TGAImageContext* tga = static_cast<TGAImageContext*>(context);
137 size_t bpp = tga->d_depth;
138 size_t w = tga->getWidth();
139 size_t h = tga->getHeight();
140 size_t imgSize = w * h * bpp;
141 size_t offset = 18 + tga->d_idLength;
142 size_t numPixels = w * h;
143 const byte* input = data->getDataPtr() + offset;
144 // Read image data
145 byte red;
146 byte green;
147 byte blue;
148 byte alpha;
149 // Uncompressed
150 if (tga->d_imageType == 2)
151 {
152
153 switch(bpp)
154 {
155 case 2: //A1B5G5R5
156 for(size_t i = 0 ; i < numPixels ; ++i)
157 {
158 unsigned short pixel;
159 pixel = *(input++);
160 pixel = pixel << 8;
161 pixel |= *(input++);
162
163 alpha = pixel & 0xf000 ? 0xff : 0x00;
164 blue = static_cast<byte>((pixel & 0x1f) << 3);
165 green = static_cast<byte>(((pixel >> 5) & 0x1f) << 3);
166 red = static_cast<byte>(((pixel >> 10) & 0x1f) << 3);
167 context->setNextPixel(red, green, blue, alpha);
168 }
169 break;
170
171 case 3: // BGR_24
172 alpha = 0xff;
173 for(size_t i = 0 ; i < numPixels ; ++i)
174 {
175 blue = *(input++);
176 green = *(input++);
177 red = *(input++);
178 context->setNextPixel(red, green, blue, alpha);
179 }
180 break;
181
182 case 4: // BGRA_32
183 alpha = 0xff;
184 for(size_t i = 0 ; i < numPixels ; ++i)
185 {
186 blue = *(input++);
187 green = *(input++);
188 red = *(input++);
189 alpha = *(input++);
190 context->setNextPixel(red, green, blue, alpha);
191 }
192 break;
193 }
194 }
195 else
196 {
197 size_t pixelsRead = 0;
198 size_t num, i;
199 byte header;
200
201 switch(bpp)
202 {
203 case 2: //A1B5G5R5
204 while(pixelsRead < numPixels)
205 {
206 header = *(input++);
207 num = 1 + (header & 0x7f);
208 if (header & 0x80)
209 {
210 unsigned short pixel;
211 pixel = *(input++);
212 pixel = pixel << 8;
213 pixel |= *(input++);
214
215 alpha = pixel & 0xf000 ? 0xff : 0x00;
216 blue = static_cast<byte>((pixel & 0x1f) << 3);
217 green = static_cast<byte>(((pixel >> 5) & 0x1f) << 3);
218 red = static_cast<byte>(((pixel >> 10) & 0x1f) << 3);
219 for(i = 0 ; i < num ; ++i)
220 {
221 context->setNextPixel(red, green, blue, alpha);
222 }
223 }
224 else
225 {
226 for (i = 0 ; i < num ; ++i)
227 {
228 unsigned short pixel;
229 pixel = *(input++);
230 pixel = pixel << 8;
231 pixel |= *(input++);
232 alpha = pixel & 0xf000 ? 0xff : 0x00;
233 blue = static_cast<byte>((pixel & 0x1f) << 3);
234 green = static_cast<byte>(((pixel >> 5) & 0x1f) << 3);
235 red = static_cast<byte>(((pixel >> 10) & 0x1f) << 3);
236 context->setNextPixel(red, green, blue, alpha);
237 }
238 }
239 pixelsRead += num;
240 }
241
242 break;
243 case 3:
244 alpha = 0xff;
245 while(pixelsRead < numPixels)
246 {
247 header = *(input++);
248 num = 1 + (header & 0x7f);
249 if (header & 0x80)
250 {
251 blue = *(input++);
252 green = *(input++);
253 red = *(input++);
254 for(i = 0 ; i < num ; ++i)
255 {
256 context->setNextPixel(red, green, blue, alpha);
257 }
258 }
259 else
260 {
261 for (i = 0 ; i < num ; ++i)
262 {
263 blue = *(input++);
264 green = *(input++);
265 red = *(input++);
266 context->setNextPixel(red, green, blue, alpha);
267 }
268 }
269 pixelsRead += num;
270 }
271 break;
272
273 case 4:
274 while(pixelsRead < numPixels)
275 {
276 header = *(input++);
277 num = 1 + (header & 0x7f);
278 if (header & 0x80)
279 {
280 blue = *(input++);
281 green = *(input++);
282 red = *(input++);
283 alpha = *(input++);
284 for(i = 0 ; i < num ; ++i)
285 {
286 context->setNextPixel(red, green, blue, alpha);
287 }
288 }
289 else
290 {
291 for (i = 0 ; i < num ; ++i)
292 {
293 blue = *(input++);
294 green = *(input++);
295 red = *(input++);
296 alpha = *(input++);
297 context->setNextPixel(red, green, blue, alpha);
298 }
299 }
300 pixelsRead += num;
301 }
302 break;
303 }
304 }
305 // Flip or not flip that is the question
306 if ((tga->d_description & 0x10) == 0x10) // Upper Left origin
307 {
308 if (origin == PO_BOTTOM_LEFT)
309 return tga->flipVertically();
310 }
311 else
312 {
313 if (origin == PO_TOP_LEFT)
314 return tga->flipVertically();
315 }
316 return true;
317}
318
319} // End section of namespace SILLY
Simple Image Loading LibrarY namespace.
PixelFormat
List all pixel format supported.
Definition SILLYBase.h:60
PixelOrigin
List all pixel origin supported.
Definition SILLYBase.h:71
Image Context for Targa image.
This is an abstract class used to provide data to the loader.
virtual const byte * getDataPtr() const =0
Get raw access to the image data.
Store the data needed by an ImageLoader object during the parsing of an image.
void setNextPixel(byte red, byte green, byte bleu, byte alpha)
Set the next pixel of the image.
bool flipVertically()
Flip pixel ordering.