fs/ras/fsTgaLdr.cpp

Go to the documentation of this file.
00001 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
00002 /*                          _______      ______    ______          __      */
00003 /*  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~    / ____(_)___ / ___ /)  / ____/___  ____/ /__    */
00004 /*     [fsTgaLdr]         / /_  / / __ \\__ \|/  / /   / __ \/ __  / _ \   */
00005 /*       rev. 4          / __/ / / /_/ /__/ /   / /___/ /_/ / /_/ /  __/   */
00006 /*    5th Feb 2007      /_/   /_/ ,___/____/    \____/\____/\__,_/\___/    */
00007 /*     [x] stable              /_/ (c) 2006-7 Filip STOKLAS (FipS)         */
00008 /*  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~       http://HOLE.4FipS.com/fips_code.php          */
00009 /*                                                                         */
00010 /* This code is free for personal and commercial use. You may redistribute */
00011 /* it by any means. If you use the code for your own projects please give  */
00012 /* me credit. Please send a bug report. Don't alter or remove this header! */
00013 /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
00014 #include <fs/ras/fsTgaLdr.h>
00015 
00016 // >>> COMMON SUPPORT BLOCK (rev. 6)
00017 #if defined(FS_HAS_FSASSERT)
00018 #   include <fs/sys/fsAssert.h>
00019 #else
00020 #   include <cassert>
00021 #   if !defined(FS_ASSERT)
00022 #       define FS_ASSERT(exp) assert(exp)
00023 #   endif
00024 #   if !defined(FS_ASSERT_MSG)
00025 #       define FS_ASSERT_MSG(exp, msg) assert(exp && msg)
00026 #   endif
00027 #   if !defined(FS_VERIFY)
00028 #       define FS_VERIFY(exp) \
00029         { bool bExp = !!(exp); assert(bExp && #exp); bExp; }
00030 #   endif
00031 #   if !defined(FS_VERIFY_MSG)
00032 #       define FS_VERIFY_MSG(exp, msg) \
00033         { bool bExp = !!(exp); assert(bExp && #exp && msg); bExp; }
00034 #   endif
00035 #   if !defined(FS_STATIC_ASSERT)
00036 #       define FS_STATIC_ASSERT(exp) { char error[(exp) ? 1 : 0]; error; }
00037 #   endif
00038 #endif
00039 #if !defined(FS_VERIFY_RETURN)
00040 #   define FS_VERIFY_RETURN(exp) \
00041     if(!(exp)) { FS_ASSERT_MSG(0, #exp "<return>"); return; }
00042 #endif
00043 #if !defined(FS_VERIFY_RETURN_VAL)
00044 #   define FS_VERIFY_RETURN_VAL(exp, ret) \
00045     if(!(exp)) { FS_ASSERT_MSG(0, #exp "<returns:>" #ret); return (ret); }
00046 #endif
00047 // <<< COMMON SUPPORT BLOCK (rev. 6)
00048 
00049 #include <stdio.h>
00050 #include <vector>
00051 
00052 // provide detailed memory tracking information
00053 #if defined(FS_HAS_FSMEMMGR)
00054 #   include <fs/sys/fsMemMgr.h>
00055 #endif
00056 //---------------------------------------------------------------------------
00057 #if (_MSC_VER >= 1400) // MSVC8
00058 #   pragma warning(disable : 4996) // function was marked as deprecated
00059 #endif
00060 //---------------------------------------------------------------------------
00061 using namespace fs::ras;
00062 //---------------------------------------------------------------------------
00063 //--- ANONYMOUS NAMESPACE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00064 //---------------------------------------------------------------------------
00065 namespace {
00066 //---------------------------------------------------------------------------
00067 template<typename T>
00068 bool ReadType(T &Dest, FILE *pIn)
00069 {
00070     return ::fread(&Dest, sizeof(T), 1, pIn) == 1;
00071 }
00072 //---------------------------------------------------------------------------
00073 struct TgaHdr_t
00074 {
00075     typedef unsigned char uint8;
00076     typedef unsigned short uint16;
00077 
00078     uint8  m_uTagLen;
00079     uint8  m_uNoPal;
00080     uint8  m_uImgFmt;
00081     uint16 m_uPalStart;
00082     uint16 m_uPalLen;
00083     uint8  m_uPalBits;
00084     uint16 m_uXoff;
00085     uint16 m_uYoff;
00086     uint16 m_uW;
00087     uint16 m_uH;
00088     uint8  m_uPxBits;
00089     uint8  m_uImgDsc;
00090     
00091     bool Read(FILE *pIn)
00092     {
00093         FS_STATIC_ASSERT(sizeof(uint8) == 1);
00094         FS_STATIC_ASSERT(sizeof(uint16) == 2);
00095     
00096         if(!ReadType(m_uTagLen, pIn)) return false;
00097         if(!ReadType(m_uNoPal, pIn)) return false;
00098         if(!ReadType(m_uImgFmt, pIn)) return false;
00099         if(!ReadType(m_uPalStart, pIn)) return false;
00100         if(!ReadType(m_uPalLen, pIn)) return false;
00101         if(!ReadType(m_uPalBits, pIn)) return false;
00102         if(!ReadType(m_uXoff, pIn)) return false;
00103         if(!ReadType(m_uYoff, pIn)) return false;
00104         if(!ReadType(m_uW, pIn)) return false;
00105         if(!ReadType(m_uH, pIn)) return false;
00106         if(!ReadType(m_uPxBits, pIn)) return false;
00107         if(!ReadType(m_uImgDsc, pIn)) return false;
00108     
00109         return true;
00110     }
00111 };
00112 //---------------------------------------------------------------------------
00113 //--- CLASS TgaLdrImpl_t >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00114 //---------------------------------------------------------------------------
00115 class TgaLdrImpl_t
00116 {
00117 public:
00118     
00119     explicit TgaLdrImpl_t(const char *pszFile);
00120     bool IsValid() const;
00121     
00122     int GetW() const;
00123     int GetH() const;
00124     const TgaLdr_t::PxFmt888_t * GetData888() const;
00125     const TgaLdr_t::PxFmt8888_t * GetData8888() const;
00126 
00127 private:
00128 
00129     TgaLdrImpl_t(); 
00130     TgaLdrImpl_t(const TgaLdrImpl_t &); 
00131     TgaLdrImpl_t & operator = (const TgaLdrImpl_t &); 
00132     
00133     //---
00134     
00135     int m_nW, m_nH;
00136     int m_nPxBits;
00137     typedef std::vector<TgaHdr_t::uint8> Data_t;
00138     Data_t m_Data;
00139 };
00140 //---------------------------------------------------------------------------
00141 TgaLdrImpl_t::TgaLdrImpl_t(const char *pszFile):
00142 m_nW(0),
00143 m_nH(0),
00144 m_nPxBits(0)
00145 {
00146     FS_VERIFY_RETURN(pszFile);
00147 
00148     //--- READ IMAGE DATA ---
00149     
00150     // open the file for reading
00151     FILE *pIn = ::fopen(pszFile, "rb");
00152     if(!pIn)
00153         return; // couldn't open the file
00154         
00155     // read TGA header
00156     TgaHdr_t Hdr;
00157     if(!Hdr.Read(pIn))
00158     {
00159         ::fclose(pIn);
00160         return; // couldn't read the header
00161     }
00162 
00163     // check image data format
00164     if(Hdr.m_uImgFmt != 2) // (A)RGB, uncompressed
00165     {
00166         ::fclose(pIn);
00167         return; // unsupported data format
00168     }
00169     
00170     // check pixel depth
00171     if(Hdr.m_uPxBits != 24 && Hdr.m_uPxBits != 32)
00172     {
00173         ::fclose(pIn);
00174         return; // unsupported pixel depth
00175     }
00176             
00177     // read image data itself    
00178     size_t uDataSize = Hdr.m_uW * Hdr.m_uH * Hdr.m_uPxBits / 8;
00179     Data_t Data;
00180     Data.resize(uDataSize);
00181     
00182     if(::fread(&Data[0], uDataSize, 1, pIn) != 1)
00183     {
00184         ::fclose(pIn);
00185         return; // IO error
00186     }
00187     
00188     // close the file
00189     ::fclose(pIn);
00190     
00191     //--- REARRANGE IMAGE DATA ---
00192 
00193     if(Hdr.m_uPxBits == 24) // BGR
00194     {
00195         // swap channels: BGR => RGB
00196         for(size_t i = 0, n = Hdr.m_uW * Hdr.m_uH * 3; i < n; i += 3)
00197         {
00198             TgaHdr_t::uint8 tmp = Data[i];
00199             Data[i]     = Data[i + 2];
00200             Data[i + 2] = tmp;
00201         }
00202     }
00203     else if(Hdr.m_uPxBits == 32) // BGRA
00204     {
00205         // swap channels: BGRA => RGBA
00206         for(size_t i = 0, n = Hdr.m_uW * Hdr.m_uH * 4; i < n; i += 4)
00207         {
00208             TgaHdr_t::uint8 tmp = Data[i];
00209             Data[i]     = Data[i + 2];
00210             Data[i + 2] = tmp;
00211         }
00212     }
00213     
00214     if((Hdr.m_uImgDsc & 1 << 5) == 0) // LB origin
00215     {
00216         // flip horizontally
00217         const int uPxBytes = Hdr.m_uPxBits / 8;
00218         for(int y = 0, yn = Hdr.m_uH / 2; y < yn; ++y)
00219         {
00220             TgaHdr_t::uint8 *pSrc1 = &Data[0] + Hdr.m_uW * uPxBytes * y;
00221             TgaHdr_t::uint8 *pSrc2 = &Data[0] + Hdr.m_uW * uPxBytes *
00222              (Hdr.m_uH - y - 1);
00223                                     
00224             for(int x = 0, xn = Hdr.m_uW * uPxBytes; x < xn; ++x)
00225             {
00226                 TgaHdr_t::uint8 tmp = *pSrc1;
00227                 *pSrc1 = *pSrc2;
00228                 *pSrc2 = tmp;
00229                 ++pSrc1;
00230                 ++pSrc2;
00231             }
00232         }
00233     }
00234     
00235     //--- TRANSFER THE STATE ---
00236     
00237     m_nW = Hdr.m_uW;
00238     m_nH = Hdr.m_uH;
00239     m_nPxBits = Hdr.m_uPxBits;
00240     m_Data.swap(Data);
00241 }
00242 //---------------------------------------------------------------------------
00243 bool TgaLdrImpl_t::IsValid() const
00244 {
00245     return !m_Data.empty();
00246 }
00247 //---------------------------------------------------------------------------
00248 int TgaLdrImpl_t::GetW() const
00249 {
00250     FS_VERIFY_RETURN_VAL(IsValid(), 0);
00251     return m_nW;
00252 }
00253 //---------------------------------------------------------------------------
00254 int TgaLdrImpl_t::GetH() const
00255 {
00256     FS_VERIFY_RETURN_VAL(IsValid(), 0);
00257     return m_nH;
00258 }
00259 //---------------------------------------------------------------------------
00260 const TgaLdr_t::PxFmt888_t * TgaLdrImpl_t::GetData888() const
00261 {
00262     FS_VERIFY_RETURN_VAL(IsValid(), 0);
00263     FS_STATIC_ASSERT(sizeof(TgaLdr_t::PxFmt888_t) == 3);
00264     
00265     return m_nPxBits == 24 ?
00266      reinterpret_cast<const TgaLdr_t::PxFmt888_t *>(&m_Data[0]) : 0;
00267 }
00268 //---------------------------------------------------------------------------
00269 const TgaLdr_t::PxFmt8888_t * TgaLdrImpl_t::GetData8888() const
00270 {
00271     FS_VERIFY_RETURN_VAL(IsValid(), 0);
00272     FS_STATIC_ASSERT(sizeof(TgaLdr_t::PxFmt8888_t) == 4);
00273 
00274     return m_nPxBits == 32 ?
00275      reinterpret_cast<const TgaLdr_t::PxFmt8888_t *>(&m_Data[0]) : 0;
00276 }
00277 //---------------------------------------------------------------------------
00278 } // anonymous namespace
00279 //---------------------------------------------------------------------------
00280 //--- CLASS TgaLdr_t >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00281 //---------------------------------------------------------------------------
00282 TgaLdr_t::TgaLdr_t(const char *pszFile):
00283 m_pImpl(new TgaLdrImpl_t(pszFile))
00284 {
00285     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00286 }
00287 //---------------------------------------------------------------------------
00288 TgaLdr_t::~TgaLdr_t()
00289 {
00290     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00291     delete static_cast<TgaLdrImpl_t *>(m_pImpl);
00292 }
00293 //---------------------------------------------------------------------------
00294 bool TgaLdr_t::IsValid() const
00295 {
00296     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00297     return static_cast<TgaLdrImpl_t *>(m_pImpl)->IsValid();
00298 }
00299 //---------------------------------------------------------------------------
00300 int TgaLdr_t::GetW() const
00301 {
00302     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00303     return static_cast<TgaLdrImpl_t *>(m_pImpl)->GetW();
00304 }
00305 //---------------------------------------------------------------------------
00306 int TgaLdr_t::GetH() const
00307 {
00308     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00309     return static_cast<TgaLdrImpl_t *>(m_pImpl)->GetH();
00310 }
00311 //---------------------------------------------------------------------------
00312 const TgaLdr_t::PxFmt888_t * TgaLdr_t::GetData888() const
00313 {
00314     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00315     return static_cast<TgaLdrImpl_t *>(m_pImpl)->GetData888();
00316 }
00317 //---------------------------------------------------------------------------
00318 const TgaLdr_t::PxFmt8888_t * TgaLdr_t::GetData8888() const
00319 {
00320     FS_ASSERT_MSG(m_pImpl, "Invalid implementation pointer!");
00321     return static_cast<TgaLdrImpl_t *>(m_pImpl)->GetData8888();
00322 }
00323 //---------------------------------------------------------------------------

FipS' Code (Thu Feb 15 22:43:35 2007) - (c) Filip STOKLAS (FipS) - [ www ] [ Guest Book ]