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
48 namespace SILLY
49 {
50 
51 TGAImageLoader::TGAImageLoader()
52  : ImageLoader("TGA Image loader (builtin)")
53 {
54 }
55 
56 TGAImageLoader::~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 
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 
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
PixelFormat
List all pixel format supported.
Definition: SILLYBase.h:59
bool flipVertically()
Flip pixel ordering.
void setNextPixel(byte red, byte green, byte bleu, byte alpha)
Set the next pixel of the image.
unsigned char byte
Typename for a byte.
Definition: SILLYBase.h:80
bool loadImageData(PixelOrigin origin, DataSource *data, ImageContext *context)
Parse the pixels data of the image and fill the header struct.
PixelOrigin
List all pixel origin supported.
Definition: SILLYBase.h:70
ImageContext * loadHeader(PixelFormat &formatSource, DataSource *data)
Parse the header of the image and fill the header struct.
Store the data needed by an ImageLoader object during the parsing of an image.
Image Context for Targa image.
Simple Image Loading LibrarY namespace.
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.