# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlCore/plugins/vlTGA.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.com                                               */
    00005 /*                                                                                    */
    00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
    00007 /*  All rights reserved.                                                              */
    00008 /*                                                                                    */
    00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
    00010 /*  are permitted provided that the following conditions are met:                     */
    00011 /*                                                                                    */
    00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
    00013 /*  list of conditions and the following disclaimer.                                  */
    00014 /*                                                                                    */
    00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
    00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
    00017 /*  other materials provided with the distribution.                                   */
    00018 /*                                                                                    */
    00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
    00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
    00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
    00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
    00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
    00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
    00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
    00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
    00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
    00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
    00029 /*                                                                                    */
    00030 /**************************************************************************************/
    00031
    00032 #include "vlTGA.hpp"
    00033 #include <vlCore/LoadWriterManager.hpp>
    00034 #include <vlCore/VisualizationLibrary.hpp>
    00035 #include <vlCore/VisualizationLibrary.hpp>
    00036 #include <vlCore/FileSystem.hpp>
    00037 #include <vlCore/DiskFile.hpp>
    00038 #include <vlCore/Image.hpp>
    00039
    00040 using namespace vl;
    00041
    00042 #include <vlCore/ImageTools.hpp>
    00043
    00044 //-----------------------------------------------------------------------------
    00045 namespace
    00046 {
    00047   const unsigned long TGA_NO_IMAGE_DATA = 0;
    00048   const unsigned long TGA_8BIT_UNCOMPRESSED = 1;
    00049   const unsigned long TGA_RGB_UNCOMPRESSED  = 2;
    00050   const unsigned long TGA_GRAYSCALE_UNCOMPRESSED  = 3;
    00051   const unsigned long TGA_8BIT_COMPRESSED   = 9;
    00052   const unsigned long TGA_RGB_COMPRESSED    = 10;
    00053   const unsigned long TGA_GRAYSCALE_COMPRESSED = 11;
    00054
    00055   typedef struct
    00056   {
    00057     unsigned char IdFieldSize; /* at offset 18 it starts, usually 0 */
    00058     unsigned char HasColMap;   /* 1 for indexed images, 0 otherwise */
    00059     unsigned char ImageType;   /* see defines above */
    00060     unsigned char ColMapOrigin[2];
    00061     unsigned char ColMapCount_lo;
    00062     unsigned char ColMapCount_hi;
    00063     unsigned char ColMapEntrySize; /* 16, 24, 32 */
    00064     unsigned char ImageOrigins[4]; /* lo/hi bytes for x/y origins */
    00065     unsigned char Width_lo;
    00066     unsigned char Width_hi;
    00067     unsigned char Height_lo;
    00068     unsigned char Height_hi;
    00069     unsigned char BitsPerPixel;  /* 8/16(?), 16, 24, 32 */
    00070     unsigned char ImageDescriptor; /* origin | alpha channel bits */
    00071   } STGAHeader;
    00072 }
    00073 //-----------------------------------------------------------------------------
    00088 ref<Image> vl::loadTGA( const String& path )
    00089 {
    00090   ref<VirtualFile> file = defFileSystem()->locateFile(path);
    00091   if ( !file )
    00092   {
    00093     Log::error( Say("File '%s' not found.\n") << path );
    00094     return NULL;
    00095   }
    00096
    00097   return loadTGA( file.get() );
    00098 }
    00099 //-----------------------------------------------------------------------------
    00100 ref<Image> vl::loadTGA( VirtualFile* file )
    00101 {
    00102   if ( !file->open(OM_ReadOnly) )
    00103   {
    00104     Log::error( Say("loadTGA: cannot load TGA file '%s'\n") << file->path() );
    00105     return NULL;
    00106   }
    00107
    00108   ref<Image> img = new Image;
    00109   img->setObjectName(file->path().toStdString());
    00110
    00111   STGAHeader header;
    00112   memset(&header, 0, sizeof(header));
    00113   file->read( &header, sizeof(STGAHeader) );
    00114
    00115   unsigned int colmap_offset = 18 + header.IdFieldSize;
    00116   unsigned int pixels_offset = colmap_offset +
    00117     (header.ColMapCount_lo + header.ColMapCount_hi*256)*header.ColMapEntrySize/8;
    00118   unsigned int w = header.Width_lo  + header.Width_hi*256;
    00119   unsigned int h = header.Height_lo + header.Height_hi*256;
    00120
    00121   #ifndef NDEBUG
    00122     unsigned int bpp = header.BitsPerPixel;
    00123     const char *type = "";
    00124     switch(header.ImageType)
    00125     {
    00126       case TGA_NO_IMAGE_DATA:          type = "TGA_NO_IMAGE_DATA"; break;
    00127       case TGA_8BIT_UNCOMPRESSED:      type = "TGA_8BIT_UNCOMPRESSED"; break;
    00128       case TGA_RGB_UNCOMPRESSED:       type = "TGA_RGB_UNCOMPRESSED"; break;
    00129       case TGA_GRAYSCALE_UNCOMPRESSED: type = "TGA_GRAYSCALE_UNCOMPRESSED"; break;
    00130       case TGA_8BIT_COMPRESSED:        type = "TGA_8BIT_COMPRESSED"; break;
    00131       case TGA_RGB_COMPRESSED:         type = "TGA_RGB_COMPRESSED"; break;
    00132       case TGA_GRAYSCALE_COMPRESSED:   type = "TGA_GRAYSCALE_COMPRESSED"; break;
    00133     }
    00134     Log::info( Say("TGA %s: w=%n, h=%n, bpp=%n/%n %s\n") << file->path() << w << h << bpp << header.ColMapEntrySize << type);
    00135   #endif
    00136
    00137   if (header.ImageType == TGA_NO_IMAGE_DATA)
    00138     return NULL;
    00139
    00140   if (header.ImageType == TGA_RGB_COMPRESSED)
    00141   {
    00142     int pixsize = 0;
    00143     switch(header.BitsPerPixel)
    00144     {
    00145       case 32: pixsize = 4; break;
    00146       case 24: pixsize = 3; break;
    00147       case 16: pixsize = 2; break;
    00148     }
    00149
    00150     if (pixsize)
    00151     {
    00152       img->allocate2D(w, h, 4, IF_RGBA, IT_UNSIGNED_BYTE);
    00153
    00154       file->seekSet(pixels_offset);
    00155       int pixcount = w*h;
    00156       int pix = 0;
    00157       while(pix < pixcount)
    00158       {
    00159         unsigned char header_ch = 0;
    00160         file->read(&header_ch, 1);
    00161         if (header_ch >= 128)
    00162         {
    00163           int count = header_ch - 128 + 1;
    00164           unsigned char bgra[4];
    00165           file->read(bgra, pixsize);
    00166           while(count--)
    00167           {
    00168             memcpy((unsigned char*)img->pixels() + pix*pixsize, bgra, pixsize);
    00169             pix++;
    00170           }
    00171         }
    00172         else
    00173         {
    00174           int count = header_ch + 1;
    00175           file->read((unsigned char*)img->pixels() + pix*pixsize, pixsize*count);
    00176           pix += count;
    00177         }
    00178       }
    00179
    00180       switch(header.BitsPerPixel)
    00181       {
    00182         case 24: convertRGBToRGBA(img->pixels(), img->width(), img->height(), 0xFF); // break;
    00183         case 32: swapBytes32_BGRA_RGBA(img->pixels(), img->requiredMemory()); break;
    00184         case 16: convertA1R5G5B5ToRGBA(img->pixels(), w*h, 0xFF); break;
    00185       }
    00186
    00187     }
    00188     else
    00189     {
    00190       Log::error( Say("TGA ERROR: TGA_RGB_COMPRESSED %nbpp not supported.\n") << header.BitsPerPixel );
    00191       file->close();
    00192       return NULL;
    00193     }
    00194
    00195   }
    00196   else
    00197   if (header.ImageType == TGA_RGB_UNCOMPRESSED)
    00198   {
    00199     int pixsize = 0;
    00200
    00201     switch(header.BitsPerPixel)
    00202     {
    00203       case 32: pixsize = 4; break;
    00204       case 24: pixsize = 3; break;
    00205       case 16: pixsize = 2; break;
    00206     }
    00207
    00208     if (pixsize)
    00209     {
    00210       file->seekSet(pixels_offset);
    00211       img->allocate2D(w, h, 4, IF_RGBA, IT_UNSIGNED_BYTE);
    00212       file->read(img->pixels(), w*h*pixsize);
    00213       switch(header.BitsPerPixel)
    00214       {
    00215         case 24: convertRGBToRGBA(img->pixels(), img->width(), img->height(), 0xFF); // break;
    00216         case 32: swapBytes32_BGRA_RGBA(img->pixels(), img->requiredMemory()); break;
    00217         case 16: convertA1R5G5B5ToRGBA(img->pixels(), w*h, 0xFF); break;
    00218       }
    00219     }
    00220     else
    00221     {
    00222       Log::error( Say("TGA ERROR: TGA_RGB_UNCOMPRESSED %nbpp not supported.\n") << header.BitsPerPixel );
    00223       file->close();
    00224       return NULL;
    00225     }
    00226
    00227   }
    00228   else
    00229   if (header.ImageType == TGA_8BIT_UNCOMPRESSED || header.ImageType == TGA_8BIT_COMPRESSED)
    00230   {
    00231     if (header.BitsPerPixel == 8)
    00232     {
    00233
    00234       unsigned int colmap_count = header.ColMapCount_lo + header.ColMapCount_hi*256;
    00235       VL_CHECK(colmap_count<=256);
    00236       if (header.ColMapEntrySize == 24)
    00237       {
    00238         TPalette3x256 palette;
    00239         file->seekSet(colmap_offset);
    00240         file->read(palette, colmap_count*3);
    00241
    00242         file->seekSet(pixels_offset);
    00243
    00244         img->allocate2D(w, h, 4, IF_RGBA, IT_UNSIGNED_BYTE);
    00245         if (header.ImageType == TGA_8BIT_UNCOMPRESSED)
    00246         {
    00247           file->read(img->pixels(), w*h*1);
    00248         }
    00249         else // TGA_8BIT_UNCOMPRESSED
    00250         {
    00251           int pixsize = 1;
    00252           int pixcount = w*h;
    00253           int pix = 0;
    00254           while(pix < pixcount)
    00255           {
    00256             unsigned char header_ch = 0;
    00257             file->read(&header_ch, 1);
    00258             if (header_ch >= 128)
    00259             {
    00260               int count = header_ch - 128 + 1;
    00261               unsigned char bgra[4];
    00262               file->read(bgra, pixsize);
    00263               while(count--)
    00264               {
    00265                 memcpy((unsigned char*)img->pixels() + pix*pixsize, bgra, pixsize);
    00266                 pix++;
    00267               }
    00268             }
    00269             else
    00270             {
    00271               int count = header_ch + 1;
    00272               file->read((unsigned char*)img->pixels() + pix*pixsize, pixsize*count);
    00273               pix += count;
    00274             }
    00275           }
    00276         }
    00277
    00278         convert8ToRGBA(palette, img->pixels(), img->width(), img->height(), 0xFF);
    00279         swapBytes32_BGRA_RGBA(img->pixels(), img->requiredMemory());
    00280       }
    00281       else if (header.ColMapEntrySize == 32)
    00282       {
    00283         TPalette4x256 palette;
    00284         file->seekSet(colmap_offset);
    00285         file->read(palette, colmap_count*4);
    00286
    00287         file->seekSet( pixels_offset );
    00288         img->allocate2D(w, h, 4, IF_RGBA, IT_UNSIGNED_BYTE);
    00289         if (header.ImageType == TGA_8BIT_UNCOMPRESSED)
    00290         {
    00291           file->read(img->pixels(), w*h*1);
    00292         }
    00293         else // TGA_8BIT_UNCOMPRESSED
    00294         {
    00295           int pixsize = 1;
    00296           int pixcount = w*h;
    00297           int pix = 0;
    00298           while(pix < pixcount)
    00299           {
    00300             unsigned char header_ch = 0;
    00301             file->read(&header_ch, 1);
    00302             if (header_ch >= 128)
    00303             {
    00304               int count = header_ch - 128 + 1;
    00305               unsigned char bgra[4];
    00306               file->read(bgra, pixsize);
    00307               while(count--)
    00308               {
    00309                 memcpy((unsigned char*)img->pixels() + pix*pixsize, bgra, pixsize);
    00310                 pix++;
    00311               }
    00312             }
    00313             else
    00314             {
    00315               int count = header_ch + 1;
    00316               file->read((unsigned char*)img->pixels() + pix*pixsize, pixsize*count);
    00317               pix += count;
    00318             }
    00319           }
    00320         }
    00321
    00322         convert8ToRGBA(palette, img->pixels(), img->width(), img->height());
    00323         swapBytes32_BGRA_RGBA(img->pixels(), img->requiredMemory());
    00324       }
    00325       else
    00326       {
    00327         Log::error( Say("TGA ERROR: TGA_8BIT_UNCOMPRESSED entry size = %n not supported.\n") << header.ColMapEntrySize );
    00328         file->close();
    00329         return NULL;
    00330       }
    00331     }
    00332     else
    00333     {
    00334       Log::error( Say("TGA ERROR: TGA_8BIT_UNCOMPRESSED %nbpp bit not supported.\n") << header.BitsPerPixel );
    00335       file->close();
    00336       return NULL;
    00337     }
    00338   }
    00339   else
    00340   if (header.ImageType == TGA_GRAYSCALE_UNCOMPRESSED || header.ImageType == TGA_GRAYSCALE_COMPRESSED)
    00341   {
    00342     if (header.BitsPerPixel == 8)
    00343     {
    00344       file->seekSet(pixels_offset);
    00345       img->allocate2D(w, h, 1, IF_LUMINANCE, IT_UNSIGNED_BYTE);
    00346       if (header.ImageType == TGA_GRAYSCALE_UNCOMPRESSED)
    00347       {
    00348         file->read(img->pixels(), w*h);
    00349       }
    00350       else  // TGA_GRAYSCALE_COMPRESSED
    00351       {
    00352         int pixsize = 1;
    00353         int pixcount = w*h;
    00354         int pix = 0;
    00355         while(pix < pixcount)
    00356         {
    00357           unsigned char header_ch = 0;
    00358           file->read(&header_ch, 1);
    00359           if (header_ch >= 128)
    00360           {
    00361             int count = header_ch - 128 + 1;
    00362             unsigned char bgra[4];
    00363             file->read(bgra, pixsize);
    00364             while(count--)
    00365             {
    00366               memcpy((unsigned char*)img->pixels() + pix*pixsize, bgra, pixsize);
    00367               pix++;
    00368             }
    00369           }
    00370           else
    00371           {
    00372             int count = header_ch + 1;
    00373             file->read((unsigned char*)img->pixels() + pix*pixsize, pixsize*count);
    00374             pix += count;
    00375           }
    00376         }
    00377       }
    00378     }
    00379     else
    00380     {
    00381       Log::error( Say("TGA ERROR: TGA_GRAYSCALE_UNCOMPRESSED %nbpp not supported.\n") << header.BitsPerPixel );
    00382       file->close();
    00383       return NULL;
    00384     }
    00385
    00386   }
    00387   else
    00388   {
    00389     Log::error( Say("TGA ERROR: this type %n not supported.\n") << header.ImageType);
    00390     file->close();
    00391     return NULL;
    00392   }
    00393
    00394   if ((header.ImageDescriptor & (1<<5)))
    00395     img->flipVertically();
    00396
    00397   file->close();
    00398   return img;
    00399 }
    00400 //-----------------------------------------------------------------------------
    00401 bool vl::saveTGA(const Image* src, const String& path)
    00402 {
    00403   ref<DiskFile> file = new DiskFile(path);
    00404   return saveTGA(src, file.get());
    00405 }
    00406 //-----------------------------------------------------------------------------
    00407 bool vl::saveTGA(const Image* src, VirtualFile* fout)
    00408 {
    00409   //if (src->dimension() != ID_2D )
    00410   //{
    00411   //  Log::error( Say("saveTGA('%s'): can save only 2D images.\n") << fout->path() );
    00412   //  return false;
    00413   //}
    00414
    00415   int w = src->width();
    00416   int h = src->height();
    00417   int d = src->depth();
    00418   if (h == 0) h=1;
    00419   if (d == 0) d=1;
    00420   if (src->isCubemap()) d=6;
    00421   h = h*d;
    00422
    00423   // convert src to IT_UNSIGNED_BYTE / IF_RGBA
    00424   ref<Image> cimg;
    00425   if (src->type() != IT_UNSIGNED_BYTE)
    00426   {
    00427     cimg = src->convertType(IT_UNSIGNED_BYTE);
    00428     src = cimg.get();
    00429     if (!cimg)
    00430     {
    00431       Log::error( Say("saveTGA('%s'): could not convert image to IT_UNSIGNED_BYTE.\n") << fout->path() );
    00432       return false;
    00433     }
    00434   }
    00435   if (src->format() != IF_BGRA)
    00436   {
    00437     cimg = src->convertFormat(IF_BGRA);
    00438     src = cimg.get();
    00439     if (!cimg)
    00440     {
    00441       Log::error( Say("saveTGA('%s'): could not convert image to IF_BGRA.\n") << fout->path() );
    00442       return false;
    00443     }
    00444   }
    00445
    00446   if(!fout->open(OM_WriteOnly))
    00447   {
    00448     Log::error( Say("TGA: could not write to '%s'.\n") << fout->path() );
    00449     return false;
    00450   }
    00451
    00452   STGAHeader header;
    00453   memset(&header, 0, sizeof(STGAHeader));
    00454   // flip vertically
    00455   // header.ImageDescriptor |= 1<<5;
    00456   header.ImageType = TGA_RGB_UNCOMPRESSED;
    00457   header.Width_lo  = (unsigned char)(w & 0x00FF);
    00458   header.Width_hi  = (unsigned char)(w >> 8);
    00459   header.Height_lo = (unsigned char)(h & 0x00FF);
    00460   header.Height_hi = (unsigned char)(h >> 8);
    00461   header.BitsPerPixel = 32;
    00462   fout->write(&header, sizeof(header));
    00463
    00464   fout->write(src->pixels(), src->requiredMemory());
    00465
    00466   // TGA footer
    00467
    00468   // extension area offset
    00469   fout->writeUInt32(0);
    00470   // developer directory offset
    00471   fout->writeUInt32(0);
    00472   // signature + "." + "0"
    00473   fout->write("TRUEVISION-XFILE.", 18);
    00474
    00475   fout->close();
    00476   return true;
    00477 }
    00478 //-----------------------------------------------------------------------------
    00480 bool vl::isTGA( VirtualFile* file )
    00481 {
    00482   if (!file->open(OM_ReadOnly))
    00483     return false;
    00484
    00485   STGAHeader header;
    00486   memset(&header, 0, sizeof(header));
    00487   file->read(&header, sizeof(STGAHeader) );
    00488
    00489   char signature[17];
    00490   memset(signature, 0, 17);
    00491   file->seekEnd(-18);
    00492   file->read(signature, 16);
    00493   file->close();
    00494
    00495   // unfortunately many TGA files are without this field
    00496
    00497   if (strcmp("TRUEVISION-XFILE", signature) == 0)
    00498     return true;
    00499
    00500   // do some heuristic checks
    00501
    00502   switch( header.ImageType )
    00503   {
    00504     case 0:
    00505     case 1:
    00506     case 2:
    00507     case 3:
    00508     case 9:
    00509     case 10:
    00510     case 11:
    00511       break;
    00512     default:
    00513       return false;
    00514   }
    00515
    00516   // unsigned int colmap_offset = 18 + header.IdFieldSize;
    00517   // unsigned int pixels_offset = colmap_offset + (header.ColMapCount_lo + header.ColMapCount_hi*256)*header.ColMapEntrySize/8;
    00518   unsigned int width  = header.Width_lo  + header.Width_hi*256;
    00519   unsigned int height = header.Height_lo + header.Height_hi*256;
    00520   unsigned int bpp = header.BitsPerPixel;
    00521
    00522   if (width * height == 0)
    00523     return false;
    00524
    00525   switch( bpp )
    00526   {
    00527     case 1:
    00528     case 4:
    00529     case 8:
    00530     case 16:
    00531     case 24:
    00532     case 32:
    00533       break;
    00534     default:
    00535       return false;
    00536   }
    00537
    00538   // ends with .tga
    00539   if ( !file->path().toLowerCase().endsWith(".tga") )
    00540     return false;
    00541
    00542   Log::warning( Say("isTGA: the file '%s' looks like a TGA but is missing the 'TRUEVISION-XFILE' signature.\n") << file->path() );
    00543   return true;
    00544 }
    00545 //-----------------------------------------------------------------------------

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:21.
Permission is granted to use this page to write and publish articles regarding Visualization Library.