Simple Image Loading LibrarY 0.1.0
|
00001 /*********************************************************************** 00002 filename: SILLYTGAImageLoader.cpp 00003 created: 11 Jun 2006 00004 author: Olivier Delannoy 00005 00006 purpose: Load TGA Image 00007 *************************************************************************/ 00008 /*************************************************************************** 00009 * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team 00010 * 00011 * Permission is hereby granted, free of charge, to any person obtaining 00012 * a copy of this software and associated documentation files (the 00013 * "Software"), to deal in the Software without restriction, including 00014 * without limitation the rights to use, copy, modify, merge, publish, 00015 * distribute, sublicense, and/or sell copies of the Software, and to 00016 * permit persons to whom the Software is furnished to do so, subject to 00017 * the following conditions: 00018 * 00019 * The above copyright notice and this permission notice shall be 00020 * included in all copies or substantial portions of the Software. 00021 * 00022 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00023 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00024 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00025 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 00026 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00027 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00028 * OTHER DEALINGS IN THE SOFTWARE. 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 // Start section of namespace SILLY 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 // Unsupported image format 00086 return 0; 00087 } 00088 // offset: 3 Skip color map + 5 bytes 00089 // offset: 8 Skip xorg / yorg + 4 bytes 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 // Read image data 00145 byte red; 00146 byte green; 00147 byte blue; 00148 byte alpha; 00149 // Uncompressed 00150 if (tga->d_imageType == 2) 00151 { 00152 00153 switch(bpp) 00154 { 00155 case 2: //A1B5G5R5 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: // BGR_24 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: // BGRA_32 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: //A1B5G5R5 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 // Flip or not flip that is the question 00306 if ((tga->d_description & 0x10) == 0x10) // Upper Left origin 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 } // End section of namespace SILLY