00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033
00034 #include "loaders/SILLYTGAImageLoader.h"
00035
00036 #ifndef SILLY_OPT_INLINE
00037 #define inline
00038 #include "loaders/SILLYTGAImageLoader.icpp"
00039 #undef inline
00040 #endif
00041 #include "SILLYDataSource.h"
00042 #include "loaders/SILLYTGAImageContext.h"
00043
00044 #include <cstring>
00045 #include <cstdio>
00046
00047
00048 namespace SILLY
00049 {
00050
00051 TGAImageLoader::TGAImageLoader()
00052 : ImageLoader("TGA Image loader (builtin)")
00053 {
00054 }
00055
00056 TGAImageLoader::~TGAImageLoader()
00057 {
00058 }
00059
00060 #ifdef SILLY_BE
00061 #define READ_WORD(res, start) \
00062 (res) = 0; \
00063 (res) = data->getDataPtr()[(start) + 1]; \
00064 (res) = (res) << 8; \
00065 (res) |= data->getDataPtr()[(start)];
00066 #else
00067 #define READ_WORD(res, start) \
00068 (res) = 0; \
00069 (res) = data->getDataPtr()[(start)]; \
00070 (res) = (res) << 8; \
00071 (res) |= data->getDataPtr()[(start) + 1];
00072 #endif
00073
00074 ImageContext* TGAImageLoader::loadHeader(PixelFormat& formatSource, DataSource* data)
00075 {
00076 byte idLength = data->getDataPtr()[0];
00077 byte colorMapType = data->getDataPtr()[1];
00078 byte imageType = data->getDataPtr()[2];
00079 size_t width;
00080 size_t height;
00081 byte depth;
00082 byte description;
00083 if ((imageType != 2 && imageType != 10) || colorMapType)
00084 {
00085
00086 return 0;
00087 }
00088
00089
00090 #ifdef SILLY_BE
00091 width = data->getDataPtr()[12];
00092 width = width << 8;
00093 width |= data->getDataPtr()[13];
00094 height = data->getDataPtr()[14];
00095 height = height << 8;
00096 height |= data->getDataPtr()[15];
00097 #else
00098 width = data->getDataPtr()[13];
00099 width = width << 8;
00100 width |= data->getDataPtr()[12];
00101 height = data->getDataPtr()[15];
00102 height = height << 8;
00103 height |= data->getDataPtr()[14];
00104 #endif
00105 depth = data->getDataPtr()[16] >> 3;
00106 switch (depth)
00107 {
00108 case 2:
00109 formatSource = PF_A1B5G5R5;
00110 break;
00111 case 3:
00112 formatSource = PF_RGB;
00113 break;
00114 case 4:
00115 formatSource = PF_RGBA;
00116 break;
00117 default:
00118 return 0;
00119 }
00120 description = (*data)[17];
00121
00122
00123 TGAImageContext* context = new TGAImageContext(width, height);
00124 if (context)
00125 {
00126 context->d_idLength = idLength;
00127 context->d_imageType = imageType;
00128 context->d_depth = depth;
00129 context->d_description = description;
00130 }
00131 return context;
00132 }
00133
00134 bool TGAImageLoader::loadImageData(PixelOrigin origin, DataSource* data, ImageContext* context)
00135 {
00136 TGAImageContext* tga = static_cast<TGAImageContext*>(context);
00137 size_t bpp = tga->d_depth;
00138 size_t w = tga->getWidth();
00139 size_t h = tga->getHeight();
00140 size_t imgSize = w * h * bpp;
00141 size_t offset = 18 + tga->d_idLength;
00142 size_t numPixels = w * h;
00143 const byte* input = data->getDataPtr() + offset;
00144
00145 byte red;
00146 byte green;
00147 byte blue;
00148 byte alpha;
00149
00150 if (tga->d_imageType == 2)
00151 {
00152
00153 switch(bpp)
00154 {
00155 case 2:
00156 for(size_t i = 0 ; i < numPixels ; ++i)
00157 {
00158 unsigned short pixel;
00159 pixel = *(input++);
00160 pixel = pixel << 8;
00161 pixel |= *(input++);
00162
00163 alpha = pixel & 0xf000 ? 0xff : 0x00;
00164 blue = static_cast<byte>((pixel & 0x1f) << 3);
00165 green = static_cast<byte>(((pixel >> 5) & 0x1f) << 3);
00166 red = static_cast<byte>(((pixel >> 10) & 0x1f) << 3);
00167 context->setNextPixel(red, green, blue, alpha);
00168 }
00169 break;
00170
00171 case 3:
00172 alpha = 0xff;
00173 for(size_t i = 0 ; i < numPixels ; ++i)
00174 {
00175 blue = *(input++);
00176 green = *(input++);
00177 red = *(input++);
00178 context->setNextPixel(red, green, blue, alpha);
00179 }
00180 break;
00181
00182 case 4:
00183 alpha = 0xff;
00184 for(size_t i = 0 ; i < numPixels ; ++i)
00185 {
00186 blue = *(input++);
00187 green = *(input++);
00188 red = *(input++);
00189 alpha = *(input++);
00190 context->setNextPixel(red, green, blue, alpha);
00191 }
00192 break;
00193 }
00194 }
00195 else
00196 {
00197 size_t pixelsRead = 0;
00198 size_t num, i;
00199 byte header;
00200
00201 switch(bpp)
00202 {
00203 case 2:
00204 while(pixelsRead < numPixels)
00205 {
00206 header = *(input++);
00207 num = 1 + (header & 0x7f);
00208 if (header & 0x80)
00209 {
00210 unsigned short pixel;
00211 pixel = *(input++);
00212 pixel = pixel << 8;
00213 pixel |= *(input++);
00214
00215 alpha = pixel & 0xf000 ? 0xff : 0x00;
00216 blue = static_cast<byte>((pixel & 0x1f) << 3);
00217 green = static_cast<byte>(((pixel >> 5) & 0x1f) << 3);
00218 red = static_cast<byte>(((pixel >> 10) & 0x1f) << 3);
00219 for(i = 0 ; i < num ; ++i)
00220 {
00221 context->setNextPixel(red, green, blue, alpha);
00222 }
00223 }
00224 else
00225 {
00226 for (i = 0 ; i < num ; ++i)
00227 {
00228 unsigned short pixel;
00229 pixel = *(input++);
00230 pixel = pixel << 8;
00231 pixel |= *(input++);
00232 alpha = pixel & 0xf000 ? 0xff : 0x00;
00233 blue = static_cast<byte>((pixel & 0x1f) << 3);
00234 green = static_cast<byte>(((pixel >> 5) & 0x1f) << 3);
00235 red = static_cast<byte>(((pixel >> 10) & 0x1f) << 3);
00236 context->setNextPixel(red, green, blue, alpha);
00237 }
00238 }
00239 pixelsRead += num;
00240 }
00241
00242 break;
00243 case 3:
00244 alpha = 0xff;
00245 while(pixelsRead < numPixels)
00246 {
00247 header = *(input++);
00248 num = 1 + (header & 0x7f);
00249 if (header & 0x80)
00250 {
00251 blue = *(input++);
00252 green = *(input++);
00253 red = *(input++);
00254 for(i = 0 ; i < num ; ++i)
00255 {
00256 context->setNextPixel(red, green, blue, alpha);
00257 }
00258 }
00259 else
00260 {
00261 for (i = 0 ; i < num ; ++i)
00262 {
00263 blue = *(input++);
00264 green = *(input++);
00265 red = *(input++);
00266 context->setNextPixel(red, green, blue, alpha);
00267 }
00268 }
00269 pixelsRead += num;
00270 }
00271 break;
00272
00273 case 4:
00274 while(pixelsRead < numPixels)
00275 {
00276 header = *(input++);
00277 num = 1 + (header & 0x7f);
00278 if (header & 0x80)
00279 {
00280 blue = *(input++);
00281 green = *(input++);
00282 red = *(input++);
00283 alpha = *(input++);
00284 for(i = 0 ; i < num ; ++i)
00285 {
00286 context->setNextPixel(red, green, blue, alpha);
00287 }
00288 }
00289 else
00290 {
00291 for (i = 0 ; i < num ; ++i)
00292 {
00293 blue = *(input++);
00294 green = *(input++);
00295 red = *(input++);
00296 alpha = *(input++);
00297 context->setNextPixel(red, green, blue, alpha);
00298 }
00299 }
00300 pixelsRead += num;
00301 }
00302 break;
00303 }
00304 }
00305
00306 if ((tga->d_description & 0x10) == 0x10)
00307 {
00308 if (origin == PO_BOTTOM_LEFT)
00309 return tga->flipVertically();
00310 }
00311 else
00312 {
00313 if (origin == PO_TOP_LEFT)
00314 return tga->flipVertically();
00315 }
00316 return true;
00317 }
00318
00319 }