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
SILLY
Simple Image Loading LibrarY namespace.
Definition: SILLYJPGImageContext.cpp:46
SILLY::PixelFormat
PixelFormat
List all pixel format supported.
Definition: SILLYBase.h:60
SILLY::ImageContext
Store the data needed by an ImageLoader object during the parsing of an image.
Definition: SILLYImageContext.h:44
SILLY::TGAImageContext
Image Context for Targa image.
Definition: SILLYTGAImageContext.h:43
SILLY::PixelOrigin
PixelOrigin
List all pixel origin supported.
Definition: SILLYBase.h:71
SILLY::TGAImageLoader::loadImageData
bool loadImageData(PixelOrigin origin, DataSource *data, ImageContext *context)
Parse the pixels data of the image and fill the header struct.
Definition: SILLYTGAImageLoader.cpp:134
SILLY::DataSource
This is an abstract class used to provide data to the loader.
Definition: SILLYDataSource.h:47
SILLY::TGAImageLoader::loadHeader
ImageContext * loadHeader(PixelFormat &formatSource, DataSource *data)
Parse the header of the image and fill the header struct.
Definition: SILLYTGAImageLoader.cpp:74
SILLY::DataSource::getDataPtr
virtual const byte * getDataPtr() const =0
Get raw access to the image data.
SILLY::ImageContext::flipVertically
bool flipVertically()
Flip pixel ordering.
Definition: SILLYImageContext.cpp:45
SILLY::ImageContext::setNextPixel
void setNextPixel(byte red, byte green, byte bleu, byte alpha)
Set the next pixel of the image.