D:/Projects/CEGUI/Silly/src/loaders/SILLYTGAImageLoader.cpp

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 

Generated on Sun Apr 6 14:47:06 2008 for Simple Image Loading LibrarY by  doxygen 1.5.2