From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/bitmap_8cpp-source.html | 3062 ++++++++++++++++++++++++++++++ 1 file changed, 3062 insertions(+) create mode 100644 docs/doxygen/nel/bitmap_8cpp-source.html (limited to 'docs/doxygen/nel/bitmap_8cpp-source.html') diff --git a/docs/doxygen/nel/bitmap_8cpp-source.html b/docs/doxygen/nel/bitmap_8cpp-source.html new file mode 100644 index 00000000..f05e0624 --- /dev/null +++ b/docs/doxygen/nel/bitmap_8cpp-source.html @@ -0,0 +1,3062 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

bitmap.cpp

Go to the documentation of this file.
00001 
+00009 /* Copyright, 2000 Nevrax Ltd.
+00010  *
+00011  * This file is part of NEVRAX NEL.
+00012  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00013  * it under the terms of the GNU General Public License as published by
+00014  * the Free Software Foundation; either version 2, or (at your option)
+00015  * any later version.
+00016 
+00017  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00018  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00020  * General Public License for more details.
+00021 
+00022  * You should have received a copy of the GNU General Public License
+00023  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00024  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00025  * MA 02111-1307, USA.
+00026  */
+00027 
+00028 #include "stdmisc.h"
+00029 
+00030 #include <memory>
+00031 #include <algorithm>
+00032 
+00033 /*extern "C"
+00034 {
+00035 #include <jpeglib.h>
+00036 }
+00037 */
+00038 
+00039 #include "nel/misc/bitmap.h"
+00040 #include "nel/misc/stream.h"
+00041 #include "nel/misc/file.h"
+00042 
+00043 
+00044 using namespace std;
+00045 
+00046 namespace NLMISC
+00047 {
+00048 
+00049 
+00050 struct EDDSBadHeader : public NLMISC::EStream
+00051 {
+00052         EDDSBadHeader() : EStream( "Bad or unrecognized DDS file header" ) {}
+00053 };
+00054 
+00055 struct ESeekFailed : public NLMISC::EStream
+00056 {
+00057         ESeekFailed() : EStream( "Seek failed" ) {}
+00058 };
+00059 
+00060 struct EAllocationFailure : public Exception
+00061 {
+00062         EAllocationFailure() : Exception( "Can't allocate memory" ) {}
+00063 };
+00064 
+00065 void blendFromui(NLMISC::CRGBA &c0, NLMISC::CRGBA &c1, uint coef);
+00066 uint32 blend(uint32 &n0, uint32 &n1, uint32 coef0);
+00067 
+00068 const uint32 CBitmap::bitPerPixels[ModeCount]=
+00069 {
+00070         32,             // RGBA
+00071         8,              // Luminance
+00072         8,              // Alpha
+00073         16,             // AlphaLuminance
+00074         4,              // DXTC1
+00075         4,              // DXTC1Alpha
+00076         8,              // DXTC3
+00077         8,              // DXTC5
+00078         16              // DsDt
+00079 };
+00080 
+00081 const uint32 CBitmap::DXTC1HEADER = NL_MAKEFOURCC('D','X', 'T', '1');
+00082 const uint32 CBitmap::DXTC3HEADER = NL_MAKEFOURCC('D','X', 'T', '3');
+00083 const uint32 CBitmap::DXTC5HEADER = NL_MAKEFOURCC('D','X', 'T', '5');
+00084 
+00085 // static data for jpeg compression (used by writeJPG())
+00086 NLMISC::IStream *JPGStream = NULL;
+00087 const uint32 JPGBufferSize = 1000;
+00088 char JPGBuffer[JPGBufferSize];
+00089 
+00090 
+00091 /*-------------------------------------------------------------------*\
+00092                                                                 load            
+00093 \*-------------------------------------------------------------------*/
+00094 uint8 CBitmap::load(NLMISC::IStream &f, uint mipMapSkip) 
+00095 {
+00096         nlassert(f.isReading()); 
+00097         
+00098         // testing if DDS
+00099         uint32 fileType = 0;;
+00100         f.serial(fileType);
+00101         if(fileType == DDS)
+00102         {
+00103                 return readDDS(f, mipMapSkip);
+00104         }
+00105         // assuming it's TGA
+00106         else 
+00107         {
+00108                 NLMISC::IStream::TSeekOrigin origin= f.begin;
+00109                 if(!f.seek (0, origin))
+00110                 {
+00111                         throw ESeekFailed();
+00112                 }
+00113 
+00114                 // Reading header, 
+00115                 // To make sure that the bitmap is TGA, we check imageType and imageDepth.
+00116                 uint8   lengthID;
+00117                 uint8   cMapType;
+00118                 uint8   imageType;
+00119                 uint16  tgaOrigin;
+00120                 uint16  length;
+00121                 uint8   depth;
+00122                 uint16  xOrg;
+00123                 uint16  yOrg;
+00124                 uint16  width;
+00125                 uint16  height;
+00126                 uint8   imageDepth;
+00127                 uint8   desc;
+00128                 
+00129                 f.serial(lengthID);
+00130                 f.serial(cMapType);
+00131                 f.serial(imageType);
+00132                 if(imageType!=2 && imageType!=3 && imageType!=10 && imageType!=11) return 0;
+00133                 f.serial(tgaOrigin);
+00134                 f.serial(length);
+00135                 f.serial(depth);
+00136                 f.serial(xOrg);
+00137                 f.serial(yOrg);
+00138                 f.serial(width);
+00139                 f.serial(height);
+00140                 f.serial(imageDepth);
+00141                 if(imageDepth!=8 && imageDepth!=16 && imageDepth!=24 && imageDepth!=32) return 0;
+00142                 f.serial(desc);
+00143 
+00144                 if(!f.seek (0, origin))
+00145                 {
+00146                         throw ESeekFailed();
+00147                 }
+00148                 return readTGA(f);
+00149         }       
+00150 }
+00151 
+00152 
+00153 /*-------------------------------------------------------------------*\
+00154                                                                 makeDummy               
+00155 \*-------------------------------------------------------------------*/
+00156 void    CBitmap::makeDummy()
+00157 {
+00158         static  const uint8     bitmap[1024]= {  
+00159                 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+00160                 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+00161                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00162                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00163                 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
+00164                 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
+00165                 0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
+00166                 0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
+00167                 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,
+00168                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00169                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00170                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00171                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00172                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00173                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00174                 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+00175                 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+00176                 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+00177                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00178                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00179                 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
+00180                 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
+00181                 0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
+00182                 0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
+00183                 0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,
+00184                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00185                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00186                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00187                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00188                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00189                 0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
+00190                 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+00191         }; 
+00192 
+00193         PixelFormat = RGBA;
+00194         _MipMapCount = 1;
+00195         _Width= 32;
+00196         _Height= 32;
+00197         _Data[0].resize(_Width*_Height*sizeof(NLMISC::CRGBA));
+00198         NLMISC::CRGBA   *pix= (NLMISC::CRGBA*)(&(*_Data[0].begin()));
+00199 
+00200         for(sint i=0;i<(sint)(_Width*_Height);i++)
+00201         {
+00202                 if(bitmap[i])
+00203                         pix[i].set(255,255,255,255);
+00204                 else
+00205                         pix[i].set(0,0,0,255);
+00206         }
+00207 
+00208 }
+00209 
+00210 
+00211 
+00212 
+00213 /*-------------------------------------------------------------------*\
+00214                                                                 readDDS         
+00215 \*-------------------------------------------------------------------*/
+00216 uint8 CBitmap::readDDS(NLMISC::IStream &f, uint mipMapSkip)
+00217 {
+00218         //------------------ Reading Header ------------------------
+00219 
+00220         //-------------- reading entire header
+00221         
+00222         uint32 size = 0;
+00223         f.serial(size); // size in Bytes of header(without "DDS")
+00224          uint32 * _DDSSurfaceDesc = new uint32[size]; 
+00225          std::auto_ptr<uint32> _DDSSurfaceDescAuto(_DDSSurfaceDesc);
+00226         _DDSSurfaceDesc[0]= size;
+00227 
+00228 #ifdef NL_LITTLE_ENDIAN
+00229         f.serialBuffer((uint8*)(_DDSSurfaceDesc+1), size-4);
+00230 #else
+00231         for(uint i= 0; i<size/4 - 1; i++)
+00232         {
+00233                 f.serial(_DDSSurfaceDesc[i+1]);
+00234         }
+00235 #endif
+00236         
+00237         // flags determines which members of the header structure contain valid data
+00238         uint32 flags = _DDSSurfaceDesc[1];
+00239 
+00240         //verify if file have linearsize set
+00241         if(!(flags & DDSD_LINEARSIZE)) 
+00242     {
+00243                 throw EDDSBadHeader();
+00244         }
+00245         
+00246         //-------------- extracting and testing useful info
+00247 
+00248         _Height = _DDSSurfaceDesc[2];
+00249         _Width  = _DDSSurfaceDesc[3];
+00250         _MipMapCount= (uint8) _DDSSurfaceDesc[6];
+00251         // If no mipmap.
+00252         if(_MipMapCount==0)
+00253                 _MipMapCount=1;
+00254         switch (_DDSSurfaceDesc[20])
+00255         {
+00256         case DXTC1HEADER:
+00257                 PixelFormat=DXTC1;
+00258                 break;
+00259         case DXTC3HEADER:
+00260                 PixelFormat=DXTC3;
+00261                 break;
+00262         case DXTC5HEADER:
+00263                 PixelFormat=DXTC5;
+00264                 break;
+00265         }
+00266         
+00267         flags = _DDSSurfaceDesc[19]; //PixelFormat flags
+00268         
+00269         if(PixelFormat==DXTC1 && _DDSSurfaceDesc[21]>0) //AlphaBitDepth
+00270         {
+00271                 PixelFormat = DXTC1Alpha;
+00272         }
+00273         
+00274         if(PixelFormat!= DXTC1 && PixelFormat!= DXTC1Alpha && PixelFormat!= DXTC3 && PixelFormat!= DXTC5)
+00275         {
+00276                 throw EDDSBadHeader();
+00277         }
+00278 
+00279         // compute the min power of 2 between width and height
+00280         uint    minSizeLevel= min(_Width, _Height);
+00281         minSizeLevel= getPowerOf2(minSizeLevel);
+00282 
+00283         //------------- manage mipMapSkip 
+00284         if(_MipMapCount>1 && mipMapSkip>0 && minSizeLevel>2)
+00285         {
+00286                 // Keep at least the level where width and height are at leat 4.
+00287                 mipMapSkip= min(mipMapSkip, minSizeLevel-2);
+00288                 // skip any mipmap
+00289                 uint    seekSize= 0;
+00290                 while(mipMapSkip>0)
+00291                 {
+00292                         uint32 mipMapSz;
+00293                         if(PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha)
+00294                                 mipMapSz = _Width*_Height/2;
+00295                         else
+00296                                 mipMapSz = _Width*_Height;
+00297 
+00298                         // add to how many to skip
+00299                         seekSize+= mipMapSz;
+00300 
+00301                         // Size of final bitmap is reduced.
+00302                         _Width>>=1;
+00303                         _Height>>=1;
+00304                         _MipMapCount--;
+00305                         mipMapSkip--;
+00306                 }
+00307                 // skip data in file
+00308                 if(seekSize>0)
+00309                 {
+00310                         if(!f.seek(seekSize, IStream::current))
+00311                         {
+00312                                 throw ESeekFailed();
+00313                         }
+00314                 }
+00315 
+00316         }
+00317 
+00318         //------------- preload all the mipmaps (one serialBuffer() is faster)
+00319         uint32 w = _Width;
+00320         uint32 h = _Height;
+00321         uint32  totalSize= 0;
+00322 
+00323         uint8   m;
+00324         for(m= 0; m<_MipMapCount; m++)
+00325         {
+00326                 uint32 wtmp, htmp;
+00327                 if(w<4)
+00328                         wtmp = 4;
+00329                 else
+00330                         wtmp = w;
+00331                 if(h < 4)
+00332                         htmp = 4;
+00333                 else
+00334                         htmp = h;
+00335                 
+00336                 uint32 mipMapSz;
+00337                 if(PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha)
+00338                         mipMapSz = wtmp*htmp/2;
+00339                 else
+00340                         mipMapSz = wtmp*htmp;
+00341 
+00342 
+00343                 _Data[m].resize(mipMapSz);
+00344                 totalSize+= mipMapSz;
+00345 
+00346                 w = (w+1)/2;
+00347                 h = (h+1)/2;
+00348         }
+00349 
+00350         // Read all the data in one block.
+00351         vector<uint8>   pixData;
+00352         pixData.resize(totalSize);
+00353         f.serialBuffer(&(*pixData.begin()), totalSize);
+00354 
+00355 
+00356         //------------- reading mipmap levels from pixData
+00357         
+00358         uint32 pixIndex= 0;
+00359 
+00360         for(m= 0; m<_MipMapCount; m++)
+00361         {
+00362                 uint32  mipMapSz= _Data[m].size();
+00363                 memcpy(&(*_Data[m].begin()), &(pixData[pixIndex]), mipMapSz);
+00364                 pixIndex+= mipMapSz;
+00365         }
+00366 
+00367         //------------- End
+00368 
+00369         switch(PixelFormat)
+00370         {
+00371                 case DXTC1  : return 24;
+00372                 case DXTC1Alpha : return 32;
+00373                 case DXTC3  : return 32;
+00374                 case DXTC5  : return 32;
+00375                 default  : break;
+00376         }
+00377 
+00378         return 0;
+00379 }
+00380 
+00381 
+00382 
+00383 
+00384 /*-------------------------------------------------------------------*\
+00385                                                         convertToDXTC5
+00386 \*-------------------------------------------------------------------*/
+00387 bool CBitmap::convertToDXTC5()
+00388 {
+00389         /* Yoyo: RGB encoding for DXTC1 and DXTC5/3 are actually different!!
+00390                 DXTC3/5 don't rely on sign of color0>color1 to setup special encoding (ie use a special compression for Black)
+00391                 Since this can arise if the src is DXTC1 , we can't simply compress it into DXTC5 without doing a 
+00392                 heavy compression...
+00393                 (the inverse is false: DXTC5 to DXTC1 is possible, with maybe swap color0/color1 and bits).
+00394         */
+00395 
+00396         return false;
+00397 
+00398 /*      uint32 i,j;
+00399 
+00400         if(PixelFormat!=DXTC1) return false;
+00401 
+00402         for(uint8 m= 0; m<_MipMapCount; m++)
+00403         {
+00404                 std::vector<uint8> dataTmp;
+00405                 dataTmp.reserve(2*_Data[m].size());
+00406 
+00407                 for(i=0; i<_Data[m].size(); i+=8)
+00408                 {
+00409                         //64 bits alpha
+00410                         for(j=0; j<8; j++)
+00411                         {
+00412                                 dataTmp.push_back(255);
+00413                         }
+00414 
+00415                         //64 bits RGB
+00416                         for(j=0; j<8; j++)
+00417                         {
+00418                                 dataTmp.push_back(_Data[m][i+j]);
+00419                         }
+00420                 }
+00421                 _Data[m] = dataTmp;
+00422         }
+00423         PixelFormat = DXTC5;
+00424         return true;
+00425 */
+00426 }
+00427 
+00428 
+00429 
+00430 /*-------------------------------------------------------------------*\
+00431                                                         luminanceToRGBA()
+00432 \*-------------------------------------------------------------------*/
+00433 bool CBitmap::luminanceToRGBA()
+00434 {
+00435         uint32 i;
+00436 
+00437         if(_Width*_Height == 0)  return false;
+00438         
+00439         for(uint8 m= 0; m<_MipMapCount; m++)
+00440         {
+00441                 std::vector<uint8> dataTmp;
+00442                 dataTmp.reserve(_Data[m].size()*4);
+00443 
+00444                 for(i=0; i<_Data[m].size(); i++)
+00445                 {
+00446                         dataTmp.push_back(_Data[m][i]);
+00447                         dataTmp.push_back(_Data[m][i]);
+00448                         dataTmp.push_back(_Data[m][i]);
+00449                         dataTmp.push_back(255);
+00450                 }
+00451                 _Data[m] = dataTmp;
+00452         }
+00453         PixelFormat = RGBA;
+00454         return true;
+00455 }
+00456 
+00457 /*-------------------------------------------------------------------*\
+00458                                                         alphaToRGBA()
+00459 \*-------------------------------------------------------------------*/
+00460 bool CBitmap::alphaToRGBA()
+00461 {
+00462         uint32 i;
+00463 
+00464         if(_Width*_Height == 0)  return false;
+00465         
+00466         for(uint8 m= 0; m<_MipMapCount; m++)
+00467         {
+00468                 std::vector<uint8> dataTmp;
+00469                 dataTmp.reserve(_Data[m].size()*4);
+00470 
+00471                 for(i=0; i<_Data[m].size(); i++)
+00472                 {
+00473                         dataTmp.push_back(255);
+00474                         dataTmp.push_back(255);
+00475                         dataTmp.push_back(255);
+00476                         dataTmp.push_back(_Data[m][i]);
+00477                 }
+00478                 _Data[m] = dataTmp;
+00479         }
+00480         PixelFormat = RGBA;
+00481         return true;
+00482 }
+00483 
+00484 
+00485 /*-------------------------------------------------------------------*\
+00486                                                         alphaLuminanceToRGBA()
+00487 \*-------------------------------------------------------------------*/
+00488 bool CBitmap::alphaLuminanceToRGBA()
+00489 {
+00490         uint32 i;
+00491 
+00492         if(_Width*_Height == 0)  return false;
+00493         
+00494         for(uint8 m= 0; m<_MipMapCount; m++)
+00495         {
+00496                 std::vector<uint8> dataTmp;
+00497                 dataTmp.reserve(_Data[m].size()*2);
+00498 
+00499                 for(i=0; i<_Data[m].size(); i+=2)
+00500                 {
+00501                         dataTmp.push_back(_Data[m][i]);
+00502                         dataTmp.push_back(_Data[m][i]);
+00503                         dataTmp.push_back(_Data[m][i]);
+00504                         dataTmp.push_back(_Data[m][i+1]);
+00505                 }
+00506                 _Data[m] = dataTmp;
+00507         }
+00508         PixelFormat = RGBA;
+00509         return true;
+00510 }
+00511 
+00512 
+00513 
+00514 
+00515 /*-------------------------------------------------------------------*\
+00516                                                         rgbaToAlphaLuminance
+00517 \*-------------------------------------------------------------------*/
+00518 bool CBitmap::rgbaToAlphaLuminance()
+00519 {
+00520         uint32 i;
+00521 
+00522         if(_Width*_Height == 0)  return false;
+00523         
+00524         for(uint8 m= 0; m<_MipMapCount; m++)
+00525         {
+00526                 std::vector<uint8> dataTmp;
+00527                 dataTmp.reserve(_Data[m].size()/2);
+00528 
+00529                 for(i=0; i<_Data[m].size(); i+=4)
+00530                 {
+00531                         dataTmp.push_back((_Data[m][i]*77 + _Data[m][i+1]*150 + _Data[m][i+2]*28)/255);
+00532                         dataTmp.push_back(_Data[m][i+3]);
+00533                 }
+00534                 NLMISC::contReset(_Data[m]); 
+00535                 _Data[m].resize(0);
+00536                 _Data[m] = dataTmp;
+00537         }
+00538         PixelFormat = AlphaLuminance;
+00539         return true;
+00540 }
+00541 
+00542 
+00543 /*-------------------------------------------------------------------*\
+00544                                                         luminanceToAlphaLuminance
+00545 \*-------------------------------------------------------------------*/
+00546 bool CBitmap::luminanceToAlphaLuminance()
+00547 {
+00548         uint32 i;
+00549 
+00550         if(_Width*_Height == 0)  return false;
+00551                 
+00552         for(uint8 m= 0; m<_MipMapCount; m++)
+00553         {
+00554                 std::vector<uint8> dataTmp;
+00555                 dataTmp.reserve(_Data[m].size()*2);
+00556 
+00557                 for(i=0; i<_Data[m].size(); i++)
+00558                 {
+00559                         dataTmp.push_back(_Data[m][i]);
+00560                         dataTmp.push_back(255);
+00561                 }
+00562                 _Data[m] = dataTmp;
+00563         }
+00564         PixelFormat = AlphaLuminance;
+00565         return true;
+00566 }
+00567 
+00568 
+00569 
+00570 /*-------------------------------------------------------------------*\
+00571                                                         alphaToAlphaLuminance
+00572 \*-------------------------------------------------------------------*/
+00573 bool CBitmap::alphaToAlphaLuminance()
+00574 {
+00575         uint32 i;
+00576 
+00577         if(_Width*_Height == 0)  return false;
+00578                 
+00579         for(uint8 m= 0; m<_MipMapCount; m++)
+00580         {
+00581                 std::vector<uint8> dataTmp;
+00582                 dataTmp.reserve(_Data[m].size()*2);
+00583 
+00584                 for(i=0; i<_Data[m].size(); i++)
+00585                 {
+00586                         dataTmp.push_back(0);
+00587                         dataTmp.push_back(_Data[m][i]);
+00588                 }
+00589                 _Data[m] = dataTmp;
+00590         }
+00591         PixelFormat = AlphaLuminance;
+00592         return true;
+00593 }
+00594 
+00595 
+00596 
+00597 /*-------------------------------------------------------------------*\
+00598                                                         rgbaToLuminance
+00599 \*-------------------------------------------------------------------*/
+00600 bool CBitmap::rgbaToLuminance()
+00601 {
+00602         uint32 i;
+00603 
+00604         if(_Width*_Height == 0)  return false;
+00605                 
+00606         for(uint8 m= 0; m<_MipMapCount; m++)
+00607         {
+00608                 std::vector<uint8> dataTmp;
+00609                 dataTmp.reserve(_Data[m].size()/4);
+00610 
+00611                 for(i=0; i<_Data[m].size(); i+=4)
+00612                 {
+00613                         dataTmp.push_back((_Data[m][i]*77 + _Data[m][i+1]*150 + _Data[m][i+2]*28)/255);
+00614                 }
+00615                 NLMISC::contReset(_Data[m]); 
+00616                 _Data[m].resize(0);
+00617                 _Data[m] = dataTmp;
+00618         }
+00619         PixelFormat = Luminance;
+00620         return true;
+00621 }
+00622 
+00623 
+00624 
+00625 /*-------------------------------------------------------------------*\
+00626                                                         alphaToLuminance
+00627 \*-------------------------------------------------------------------*/
+00628 bool CBitmap::alphaToLuminance()
+00629 {
+00630         if(_Width*_Height == 0)  return false;
+00631                 
+00632         PixelFormat = Luminance;
+00633         return true;
+00634 }
+00635 
+00636 
+00637 
+00638 /*-------------------------------------------------------------------*\
+00639                                                         alphaLuminanceToLuminance
+00640 \*-------------------------------------------------------------------*/
+00641 bool CBitmap::alphaLuminanceToLuminance()
+00642 {
+00643         uint32 i;
+00644 
+00645         if(_Width*_Height == 0)  return false;
+00646                 
+00647         for(uint8 m= 0; m<_MipMapCount; m++)
+00648         {
+00649                 std::vector<uint8> dataTmp;
+00650                 dataTmp.reserve(_Data[m].size()/2);
+00651 
+00652                 for(i=0; i<_Data[m].size(); i+=2)
+00653                 {
+00654                         dataTmp.push_back(0);
+00655                         dataTmp.push_back(0);
+00656                         dataTmp.push_back(0);
+00657                         dataTmp.push_back(_Data[m][i]);
+00658                 }
+00659                 NLMISC::contReset(_Data[m]); 
+00660                 _Data[m].resize(0);
+00661                 _Data[m] = dataTmp;
+00662         }
+00663         PixelFormat = Luminance;
+00664         return true;
+00665 }
+00666 
+00667 
+00668 /*-------------------------------------------------------------------*\
+00669                                                         rgbaToAlpha
+00670 \*-------------------------------------------------------------------*/
+00671 bool CBitmap::rgbaToAlpha()
+00672 {
+00673         uint32 i;
+00674 
+00675         if(_Width*_Height == 0)  return false;
+00676                 
+00677         for(uint8 m= 0; m<_MipMapCount; m++)
+00678         {
+00679                 std::vector<uint8> dataTmp;
+00680                 dataTmp.reserve(_Data[m].size()/4);
+00681 
+00682                 for(i=0; i<_Data[m].size(); i+=4)
+00683                 {
+00684                         dataTmp.push_back(0);
+00685                         dataTmp.push_back(0);
+00686                         dataTmp.push_back(0);
+00687                         dataTmp.push_back(_Data[m][i+3]);
+00688                 }
+00689                 NLMISC::contReset(_Data[m]); 
+00690                 _Data[m].resize(0);
+00691                 _Data[m] = dataTmp;
+00692         }
+00693         PixelFormat = Alpha;
+00694         return true;
+00695 }
+00696 
+00697 
+00698 /*-------------------------------------------------------------------*\
+00699                                                         luminanceToAlpha
+00700 \*-------------------------------------------------------------------*/
+00701 bool CBitmap::luminanceToAlpha()
+00702 {
+00703         uint32 i;
+00704 
+00705         if(_Width*_Height == 0)  return false;
+00706                 
+00707         for(uint8 m= 0; m<_MipMapCount; m++)
+00708         {
+00709                 std::vector<uint8> dataTmp;
+00710                 dataTmp.reserve(_Data[m].size());
+00711 
+00712                 for(i=0; i<_Data[m].size(); i++)
+00713                 {
+00714                         dataTmp.push_back(_Data[m][i]);
+00715                 }
+00716                 _Data[m] = dataTmp;
+00717         }
+00718         PixelFormat = Alpha;
+00719         return true;
+00720 }
+00721 
+00722 
+00723 /*-------------------------------------------------------------------*\
+00724                                                         alphaLuminanceToAlpha
+00725 \*-------------------------------------------------------------------*/
+00726 bool CBitmap::alphaLuminanceToAlpha()
+00727 {
+00728         uint32 i;
+00729 
+00730         if(_Width*_Height == 0)  return false;
+00731                 
+00732         for(uint8 m= 0; m<_MipMapCount; m++)
+00733         {
+00734                 std::vector<uint8> dataTmp;
+00735                 dataTmp.reserve(_Data[m].size()/2);
+00736 
+00737                 for(i=0; i<_Data[m].size(); i+=2)
+00738                 {
+00739                         dataTmp.push_back(_Data[m][i+1]);
+00740                 }
+00741                 NLMISC::contReset(_Data[m]); 
+00742                 _Data[m].resize(0);
+00743                 _Data[m] = dataTmp;
+00744         }
+00745         PixelFormat = Alpha;
+00746         return true;
+00747 }
+00748 
+00749 
+00750 /*-------------------------------------------------------------------*\
+00751                                                         convertToLuminance
+00752 \*-------------------------------------------------------------------*/
+00753 bool CBitmap::convertToLuminance()
+00754 {
+00755         switch(PixelFormat)
+00756         {
+00757                 case RGBA :
+00758                         return rgbaToLuminance();
+00759                         break;
+00760 
+00761                 case Luminance :
+00762                         return true;
+00763                         break;
+00764 
+00765                 case Alpha :
+00766                         return alphaToLuminance();
+00767                         break;
+00768 
+00769                 case AlphaLuminance :
+00770                         return alphaLuminanceToLuminance();
+00771                         break;
+00772 
+00773                 default:
+00774                         break;
+00775         }
+00776         return false;
+00777 }
+00778 
+00779 
+00780 
+00781 /*-------------------------------------------------------------------*\
+00782                                                         convertToAlpha
+00783 \*-------------------------------------------------------------------*/
+00784 bool CBitmap::convertToAlpha()
+00785 {
+00786         switch(PixelFormat)
+00787         {
+00788                 case RGBA :
+00789                         return rgbaToAlpha();
+00790                         break;
+00791 
+00792                 case Luminance :
+00793                         return luminanceToAlpha();
+00794                         break;
+00795 
+00796                 case Alpha :
+00797                         return true;
+00798                         break;
+00799 
+00800                 case AlphaLuminance :
+00801                         return alphaLuminanceToAlpha();
+00802                         break;
+00803 
+00804                 default:
+00805                         break;
+00806         }
+00807         return false;
+00808 }
+00809 
+00810 
+00811 
+00812 /*-------------------------------------------------------------------*\
+00813                                                         convertToAlphaLuminance
+00814 \*-------------------------------------------------------------------*/
+00815 bool CBitmap::convertToAlphaLuminance()
+00816 {
+00817         switch(PixelFormat)
+00818         {
+00819                 case RGBA :
+00820                         return rgbaToAlphaLuminance();
+00821                         break;
+00822 
+00823                 case Luminance :
+00824                         return luminanceToAlphaLuminance();
+00825                         break;
+00826 
+00827                 case Alpha :
+00828                         return alphaToAlphaLuminance();
+00829                         break;
+00830 
+00831                 case AlphaLuminance :
+00832                         return true;
+00833                         break;
+00834 
+00835                 default:
+00836                         break;
+00837         }
+00838         return false;
+00839 }
+00840 
+00841 
+00842 /*-------------------------------------------------------------------*\
+00843                                                         convertToRGBA
+00844 \*-------------------------------------------------------------------*/
+00845 bool CBitmap::convertToRGBA()
+00846 {
+00847         switch(PixelFormat)
+00848         {
+00849                 case DXTC1 :
+00850                         return decompressDXT1(false);
+00851                         break;
+00852 
+00853                 case DXTC1Alpha :
+00854                         return decompressDXT1(true);
+00855                         break;
+00856 
+00857                 case DXTC3 :
+00858                         return decompressDXT3();        
+00859                         break;
+00860 
+00861                 case DXTC5 :
+00862                         return decompressDXT5();                
+00863                         break;
+00864 
+00865                 case Luminance :
+00866                         return luminanceToRGBA();
+00867                         break;
+00868 
+00869                 case Alpha :
+00870                         return alphaToRGBA();
+00871                         break;
+00872 
+00873                 case AlphaLuminance :
+00874                         return alphaLuminanceToRGBA();
+00875                         break;
+00876                 case RGBA:
+00877                         return true;
+00878                 break;
+00879                 default:
+00880                         break;
+00881         }
+00882         return false;
+00883 }
+00884 
+00885 
+00886 /*-------------------------------------------------------------------*\
+00887                                                         convertToType
+00888 \*-------------------------------------------------------------------*/
+00889 bool CBitmap::convertToType(CBitmap::TType type)
+00890 {
+00891         if(PixelFormat==type) return true;
+00892 
+00893         switch(type)
+00894         {
+00895                 case RGBA :
+00896                         return convertToRGBA();
+00897                         break;
+00898 
+00899                 case DXTC5 :
+00900                         return convertToDXTC5();                
+00901                         break;
+00902 
+00903                 case Luminance :
+00904                         return convertToLuminance();
+00905                         break;
+00906 
+00907                 case Alpha :
+00908                         return convertToAlpha();
+00909                         break;
+00910 
+00911                 case AlphaLuminance :
+00912                         return convertToAlphaLuminance();
+00913                         break;
+00914 
+00915                 default:
+00916                         break;
+00917         }
+00918         
+00919         return false;
+00920 }
+00921 
+00922 
+00923 
+00924 
+00925 /*-------------------------------------------------------------------*\
+00926                                                         decompressDXT1
+00927 \*-------------------------------------------------------------------*/
+00928 bool CBitmap::decompressDXT1(bool alpha)
+00929 {
+00930         uint32 i,j,k;
+00931         NLMISC::CRGBA   c[4];
+00932         std::vector<uint8> dataTmp[MAX_MIPMAP];
+00933         
+00934         uint32 width= _Width;
+00935         uint32 height= _Height;
+00936 
+00937         for(uint8 m= 0; m<_MipMapCount; m++)
+00938         {
+00939                 uint32 wtmp, htmp;
+00940                 if(width<4)
+00941                         wtmp = 4;
+00942                 else
+00943                         wtmp = width;
+00944                 if(height < 4)
+00945                         htmp = 4;
+00946                 else
+00947                         htmp = height;
+00948                 uint32 mipMapSz = wtmp*htmp*4;
+00949                 dataTmp[m].resize(mipMapSz); 
+00950                 if(dataTmp[m].capacity()<mipMapSz)
+00951                 {
+00952                         throw EAllocationFailure();
+00953                 }
+00954                 uint32 wBlockCount= wtmp/4;
+00955                 
+00956 
+00957 
+00958                 for(i=0; i < _Data[m].size(); i+=8)
+00959                 {
+00960                         uint16 color0;
+00961                         uint16 color1;
+00962                         uint32 bits;
+00963                         memcpy(&color0,&_Data[m][i],2);
+00964                         memcpy(&color1,&_Data[m][i+2],2);
+00965                         memcpy(&bits,&_Data[m][i+4],4);
+00966 
+00967                         uncompress(color0,c[0]);
+00968                         uncompress(color1,c[1]);        
+00969                         
+00970                         c[0].A= 0;
+00971                         c[1].A= 0;
+00972                         c[2].A= 0;
+00973                         c[3].A= 0;
+00974                         
+00975                         if(color0>color1)
+00976                         {
+00977                                 c[2].blendFromui(c[0],c[1],85);
+00978                                 if(alpha) c[2].A= 255;
+00979 
+00980                                 c[3].blendFromui(c[0],c[1],171);        
+00981                                 if(alpha) c[3].A= 255;
+00982                         }
+00983                         else
+00984                         {
+00985                                 c[2].blendFromui(c[0],c[1],128);
+00986                                 if(alpha) c[2].A= 255;
+00987 
+00988                                 c[3].set(0,0,0,0);
+00989                         }
+00990 
+00991                         // computing the 16 RGBA of the block
+00992                         
+00993                         uint32 blockNum= i/8; //(64 bits)
+00994                         // <previous blocks in above lines> * 4 (rows) * _Width (columns) + 4pix*4rgba*<same line previous blocks>
+00995                         uint32 pixelsCount= 4*(blockNum/wBlockCount)*wtmp*4 + 4*4*(blockNum%wBlockCount);
+00996                         for(j=0; j<4; j++)
+00997                         {
+00998                                 for(k=0; k<4; k++)
+00999                                 {
+01000                                         dataTmp[m][pixelsCount + j*wtmp*4 + 4*k]= c[bits&3].R;
+01001                                         dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+1]= c[bits&3].G;
+01002                                         dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+2]= c[bits&3].B;
+01003                                         dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+3]= c[bits&3].A;
+01004                                         bits>>=2;
+01005                                 }
+01006                         }
+01007                 }
+01008 
+01009                 // Copy result into the mipmap level.
+01010                 if(wtmp==width && htmp==height)
+01011                 {
+01012                         // For mipmaps level >4 pixels.
+01013                         _Data[m]= dataTmp[m];
+01014                 }
+01015                 else
+01016                 {
+01017                         // For last mipmaps, level <4 pixels.
+01018                         _Data[m].resize(width*height*4);
+01019                         CRGBA   *src= (CRGBA*)&dataTmp[m][0];
+01020                         CRGBA   *dst= (CRGBA*)&_Data[m][0];
+01021                         uint    x,y;
+01022                         for(y=0;y<height;y++)
+01023                         {
+01024                                 for(x=0;x<width;x++)
+01025                                         dst[y*width+x]= src[y*wtmp+x];
+01026                         }
+01027                 }
+01028 
+01029                 // Next mipmap size.
+01030                 width = (width+1)/2;
+01031                 height = (height+1)/2;
+01032         }
+01033         PixelFormat = RGBA;
+01034         return true;
+01035 }
+01036 
+01037 
+01038 
+01039 
+01040 /*-------------------------------------------------------------------*\
+01041                                                         decompressDXT3
+01042 \*-------------------------------------------------------------------*/
+01043 bool CBitmap::decompressDXT3()
+01044 {
+01045         uint32 i,j,k;
+01046         NLMISC::CRGBA   c[4];
+01047         std::vector<uint8> dataTmp[MAX_MIPMAP];
+01048         
+01049         uint32 width= _Width;
+01050         uint32 height= _Height;
+01051 
+01052         for(uint8 m= 0; m<_MipMapCount; m++)
+01053         {
+01054                 uint32 wtmp, htmp;
+01055                 if(width<4)
+01056                         wtmp = 4;
+01057                 else
+01058                         wtmp = width;
+01059                 if(height < 4)
+01060                         htmp = 4;
+01061                 else
+01062                         htmp = height;
+01063                 uint32 mipMapSz = wtmp*htmp*4;
+01064                 dataTmp[m].resize(mipMapSz); 
+01065                 if(dataTmp[m].capacity()<mipMapSz)
+01066                 {
+01067                         throw EAllocationFailure();
+01068                 }
+01069                 uint32 wBlockCount= wtmp/4;
+01070                 
+01071 
+01072                 for(i=0; i < _Data[m].size(); i+=16)
+01073                 {
+01074                         uint8 alpha[16];
+01075                         uint64 alphatmp;
+01076                         memcpy(&alphatmp,&_Data[m][i],8);
+01077 
+01078                         for(j=0; j<16; j++)
+01079                         {
+01080                                 uint8   a= (uint8)(alphatmp&15);
+01081                                 // expand to 0-255.
+01082                                 alpha[j]= a+(a<<4);
+01083                                 alphatmp>>=4;
+01084                         }
+01085 
+01086 
+01087                         uint16 color0;
+01088                         uint16 color1;
+01089                         uint32 bits;
+01090                         memcpy(&color0,&_Data[m][i+8],2);
+01091                         memcpy(&color1,&_Data[m][i+10],2);
+01092                         memcpy(&bits,&_Data[m][i+12],4);
+01093 
+01094                         uncompress(color0,c[0]);
+01095                         uncompress(color1,c[1]);        
+01096                                                 
+01097                         // ignore color0>color1 for DXT3 and DXT5.
+01098                         c[2].blendFromui(c[0],c[1],85);
+01099                         c[3].blendFromui(c[0],c[1],171);        
+01100 
+01101                         // computing the 16 RGBA of the block
+01102                         
+01103                         uint32 blockNum= i/16; //(128 bits)
+01104                         // <previous blocks in above lines> * 4 (rows) * wtmp (columns) + 4pix*4rgba*<same line previous blocks>
+01105                         uint32 pixelsCount= 4*(blockNum/wBlockCount)*wtmp*4 + 4*4*(blockNum%wBlockCount);
+01106                         for(j=0; j<4; j++)
+01107                         {
+01108                                 for(k=0; k<4; k++)
+01109                                 {
+01110                                         dataTmp[m][pixelsCount + j*wtmp*4 + 4*k]= c[bits&3].R;
+01111                                         dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+1]= c[bits&3].G;
+01112                                         dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+2]= c[bits&3].B;
+01113                                         dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+3]= alpha[4*j+k];
+01114                                         bits>>=2;
+01115                                 }
+01116                         }
+01117                 }
+01118 
+01119                 // Copy result into the mipmap level.
+01120                 if(wtmp==width && htmp==height)
+01121                 {
+01122                         // For mipmaps level >4 pixels.
+01123                         _Data[m]= dataTmp[m];
+01124                 }
+01125                 else
+01126                 {
+01127                         // For last mipmaps, level <4 pixels.
+01128                         _Data[m].resize(width*height*4);
+01129                         CRGBA   *src= (CRGBA*)&dataTmp[m][0];
+01130                         CRGBA   *dst= (CRGBA*)&_Data[m][0];
+01131                         uint    x,y;
+01132                         for(y=0;y<height;y++)
+01133                         {
+01134                                 for(x=0;x<width;x++)
+01135                                         dst[y*width+x]= src[y*wtmp+x];
+01136                         }
+01137                 }
+01138 
+01139                 // Next mipmap size.
+01140                 width = (width+1)/2;
+01141                 height = (height+1)/2;
+01142         }
+01143         PixelFormat = RGBA;
+01144         return true;
+01145 }
+01146 
+01147 
+01148 
+01149 
+01150 /*-------------------------------------------------------------------*\
+01151                                                         decompressDXT5
+01152 \*-------------------------------------------------------------------*/
+01153 bool CBitmap::decompressDXT5()
+01154 {
+01155         uint32 i,j,k;
+01156         NLMISC::CRGBA   c[4];
+01157         std::vector<uint8> dataTmp[MAX_MIPMAP];
+01158         
+01159         uint32 width= _Width;
+01160         uint32 height= _Height;
+01161 
+01162         for(uint8 m= 0; m<_MipMapCount; m++)
+01163         {
+01164                 uint32 wtmp, htmp;
+01165                 if(width<4)
+01166                         wtmp = 4;
+01167                 else
+01168                         wtmp = width;
+01169                 if(height < 4)
+01170                         htmp = 4;
+01171                 else
+01172                         htmp = height;
+01173                 uint32 mipMapSz = wtmp*htmp*4;
+01174                 dataTmp[m].resize(mipMapSz); 
+01175                 if(dataTmp[m].capacity()<mipMapSz)
+01176                 {
+01177                         throw EAllocationFailure();
+01178                 }
+01179                 uint32 wBlockCount= wtmp/4;
+01180                 
+01181 
+01182 
+01183                 for(i=0; i < _Data[m].size(); i+=16)
+01184                 {
+01185                         uint64 bitsAlpha;
+01186                         memcpy(&bitsAlpha,&_Data[m][i],8);
+01187                         bitsAlpha>>= 16;
+01188 
+01189                         uint32 alpha[8];
+01190                         alpha[0]= _Data[m][i+0];
+01191                         alpha[1]= _Data[m][i+1];
+01192                         
+01193                         if(alpha[0]>alpha[1])
+01194                         {
+01195                                 alpha[2]= blend(alpha[0], alpha[1], 219);
+01196                                 alpha[3]= blend(alpha[0], alpha[1], 183);
+01197                                 alpha[4]= blend(alpha[0], alpha[1], 146);
+01198                                 alpha[5]= blend(alpha[0], alpha[1], 110);
+01199                                 alpha[6]= blend(alpha[0], alpha[1], 73);
+01200                                 alpha[7]= blend(alpha[0], alpha[1], 37);
+01201                         }
+01202                         else
+01203                         {
+01204                                 alpha[2]= blend(alpha[0], alpha[1], 204);
+01205                                 alpha[3]= blend(alpha[0], alpha[1], 154);
+01206                                 alpha[4]= blend(alpha[0], alpha[1], 102);
+01207                                 alpha[5]= blend(alpha[0], alpha[1], 51);
+01208                                 alpha[6]= 0;
+01209                                 alpha[7]= 255;
+01210                         }
+01211 
+01212                         uint8 codeAlpha[16];
+01213                         for(j=0; j<16; j++)
+01214                         {
+01215                                 codeAlpha[j] = (uint8)bitsAlpha & 7;
+01216                                 bitsAlpha>>=3;
+01217                         }
+01218 
+01219 
+01220                         uint16 color0;
+01221                         uint16 color1;
+01222                         uint32 bits;
+01223                         memcpy(&color0,&_Data[m][i+8],2);
+01224                         memcpy(&color1,&_Data[m][i+10],2);
+01225                         memcpy(&bits,&_Data[m][i+12],4);
+01226 
+01227                         uncompress(color0,c[0]);
+01228                         uncompress(color1,c[1]);        
+01229                         
+01230                         // ignore color0>color1 for DXT3 and DXT5.
+01231                         c[2].blendFromui(c[0],c[1],85);
+01232                         c[3].blendFromui(c[0],c[1],171);        
+01233 
+01234                         // computing the 16 RGBA of the block
+01235                         
+01236                         uint32 blockNum= i/16; //(128 bits)
+01237 
+01238                         // <previous blocks in above lines> * 4 (rows) * wtmp (columns) + 4pix*<same line previous blocks>
+01239                         uint32 pixelsCount= (blockNum/wBlockCount)*wtmp*4 + 4*(blockNum%wBlockCount);
+01240                         // *sizeof(RGBA)
+01241                         pixelsCount*=4;
+01242                         for(j=0; j<4; j++)
+01243                         {
+01244                                 for(k=0; k<4; k++)
+01245                                 {
+01246                                         dataTmp[m][pixelsCount + (j*wtmp+k)*4 +0]= c[bits&3].R;
+01247                                         dataTmp[m][pixelsCount + (j*wtmp+k)*4 +1]= c[bits&3].G;
+01248                                         dataTmp[m][pixelsCount + (j*wtmp+k)*4 +2]= c[bits&3].B;
+01249                                         dataTmp[m][pixelsCount + (j*wtmp+k)*4 +3]= (uint8) alpha[codeAlpha[4*j+k]];
+01250                                         bits>>=2;
+01251                                 }
+01252                         }
+01253 
+01254                 }
+01255 
+01256                 // Copy result into the mipmap level.
+01257                 if(wtmp==width && htmp==height)
+01258                 {
+01259                         // For mipmaps level >4 pixels.
+01260                         _Data[m]= dataTmp[m];
+01261                 }
+01262                 else
+01263                 {
+01264                         // For last mipmaps, level <4 pixels.
+01265                         _Data[m].resize(width*height*4);
+01266                         CRGBA   *src= (CRGBA*)&dataTmp[m][0];
+01267                         CRGBA   *dst= (CRGBA*)&_Data[m][0];
+01268                         uint    x,y;
+01269                         for(y=0;y<height;y++)
+01270                         {
+01271                                 for(x=0;x<width;x++)
+01272                                         dst[y*width+x]= src[y*wtmp+x];
+01273                         }
+01274                 }
+01275 
+01276                 // Next mipmap size.
+01277                 width = (width+1)/2;
+01278                 height = (height+1)/2;
+01279         }
+01280         PixelFormat = RGBA;
+01281         return true;
+01282 
+01283 }
+01284 
+01285 
+01286 
+01287 
+01288 /*-------------------------------------------------------------------*\
+01289                                                         blend
+01290 \*-------------------------------------------------------------------*/
+01291 uint32 CBitmap::blend(uint32 &n0, uint32 &n1, uint32 coef0) 
+01292 {
+01293         int     a0 = coef0;
+01294         int     a1 = 256-a0;
+01295         return ((n0*a0 + n1*a1) >>8);
+01296 }
+01297 
+01298 
+01299 
+01300 /*-------------------------------------------------------------------*\
+01301                                                         uncompress
+01302 \*-------------------------------------------------------------------*/
+01303 inline void CBitmap::uncompress(uint16 color, NLMISC::CRGBA &r)
+01304 {
+01305         r.A= 0;
+01306         r.R= ((color>>11)&31) << 3; r.R+= r.R>>5;
+01307         r.G= ((color>>5)&63) << 2;  r.G+= r.G>>6;
+01308         r.B= ((color)&31) << 3;     r.B+= r.B>>5;
+01309 }
+01310 
+01311 
+01312 
+01313 /*-------------------------------------------------------------------*\
+01314                                                         getWidth
+01315 \*-------------------------------------------------------------------*/
+01316 uint32 CBitmap::getWidth(uint32 mipMap) const
+01317 {
+01318         if(mipMap==0) return _Width;
+01319         
+01320         uint32 w = _Width;
+01321         uint32 h = _Height;
+01322         uint32 m = 0;
+01323         
+01324         do
+01325         {
+01326                 m++;
+01327                 w = (w+1)/2;
+01328                 h = (h+1)/2;
+01329                 if(m==mipMap) return w;
+01330         }
+01331         while(w!=1 || h!=1);
+01332 
+01333         return 0;
+01334 }
+01335 
+01336 
+01337 
+01338 /*-------------------------------------------------------------------*\
+01339                                                         getHeight
+01340 \*-------------------------------------------------------------------*/
+01341 uint32 CBitmap::getHeight(uint32 mipMap) const
+01342 {
+01343         if(mipMap==0) return _Height;
+01344         
+01345         uint32 w = _Width;
+01346         uint32 h = _Height;
+01347         uint32 m = 0;
+01348 
+01349         do
+01350         {
+01351                 m++;
+01352                 w = (w+1)/2;
+01353                 h = (h+1)/2;
+01354                 if(m==mipMap) return h;
+01355         }
+01356         while(w!=1 || h!=1);
+01357 
+01358         return 0;
+01359 }
+01360 
+01361 
+01362 /*-------------------------------------------------------------------*\
+01363                                                         getHeight
+01364 \*-------------------------------------------------------------------*/
+01365 uint32 CBitmap::getSize(uint32 numMipMap) const
+01366 {
+01367         return getHeight(numMipMap)*getWidth(numMipMap);
+01368 }
+01369 
+01370 
+01371 
+01372 /*-------------------------------------------------------------------*\
+01373                                                         buildMipMaps
+01374 \*-------------------------------------------------------------------*/
+01375 void CBitmap::buildMipMaps()
+01376 {
+01377         uint32 i,j;
+01378 
+01379         if(PixelFormat!=RGBA) return;
+01380         if(_MipMapCount!=1) return;
+01381         if(!NLMISC::isPowerOf2(_Width)) return;
+01382         if(!NLMISC::isPowerOf2(_Height)) return;
+01383         
+01384         uint32 w = _Width;
+01385         uint32 h = _Height;
+01386 
+01387         while(w>1 || h>1)
+01388         {
+01389                 uint32 precw = w;
+01390                 uint32 prech = h;
+01391                 w = (w+1)/2;
+01392                 h = (h+1)/2;
+01393                 uint32  mulw= precw/w;
+01394                 uint32  mulh= prech/h;
+01395 
+01396                 _Data[_MipMapCount].resize(w*h*4);
+01397                 
+01398         
+01399                 NLMISC::CRGBA *pRgba = (NLMISC::CRGBA*)&_Data[_MipMapCount][0];
+01400                 NLMISC::CRGBA *pRgbaPrev = (NLMISC::CRGBA*)&_Data[_MipMapCount-1][0];
+01401                 for(i=0; i<h; i++)
+01402                 {
+01403                         sint    i0= mulh*i;
+01404                         sint    i1= mulh*i+1;
+01405                         if(mulh==1)
+01406                                 i1=i0;
+01407                         i0*=precw;
+01408                         i1*=precw;
+01409                         for(j=0; j<w; j++)
+01410                         {
+01411                                 sint    j0= mulw*j;
+01412                                 sint    j1= mulw*j+1;
+01413                                 if(mulh==1)
+01414                                         j1=j0;
+01415                                 CRGBA   &c0= pRgbaPrev[i0+j0];
+01416                                 CRGBA   &c1= pRgbaPrev[i0+j1];
+01417                                 CRGBA   &c2= pRgbaPrev[i1+j0];
+01418                                 CRGBA   &c3= pRgbaPrev[i1+j1];
+01419                                 pRgba[i*w + j].R = (c0.R +
+01420                                                                         c1.R +
+01421                                                                         c2.R +
+01422                                                                         c3.R + 2 ) /4;
+01423                                 pRgba[i*w + j].G = (c0.G +
+01424                                                                         c1.G +
+01425                                                                         c2.G +
+01426                                                                         c3.G + 2 ) /4;
+01427                                 pRgba[i*w + j].B = (c0.B +
+01428                                                                         c1.B +
+01429                                                                         c2.B +
+01430                                                                         c3.B + 2 ) /4;
+01431                                 pRgba[i*w + j].A = (c0.A +
+01432                                                                         c1.A +
+01433                                                                         c2.A +
+01434                                                                         c3.A + 2 ) /4;
+01435                         }
+01436                 }
+01437 
+01438                 _MipMapCount++;
+01439         }
+01440 }
+01441 
+01442 
+01443 /*-------------------------------------------------------------------*\
+01444                                                         releaseMipMaps
+01445 \*-------------------------------------------------------------------*/
+01446 void CBitmap::releaseMipMaps()
+01447 {
+01448         if(_MipMapCount<=1) return;
+01449 
+01450         _MipMapCount=1;
+01451         for(sint i=1;i<MAX_MIPMAP;i++)
+01452         {
+01453                 NLMISC::contReset(_Data[i]); 
+01454         }
+01455 }
+01456 
+01457 
+01458 /*-------------------------------------------------------------------*\
+01459                                                         resample
+01460 \*-------------------------------------------------------------------*/
+01461 void CBitmap::resample(sint32 nNewWidth, sint32 nNewHeight)
+01462 {
+01463         nlassert(PixelFormat == RGBA);
+01464         bool needRebuild = false;
+01465 
+01466         // Deleting mipmaps
+01467         if(_MipMapCount>1)
+01468                 needRebuild = true;
+01469         releaseMipMaps();
+01470 
+01471         if(nNewWidth==0 || nNewHeight==0)
+01472         {
+01473                 _Width = _Height = 0;
+01474                 return;
+01475         }
+01476         
+01477         std::vector<uint8> pDestui;
+01478         pDestui.resize(nNewWidth*nNewHeight*4);
+01479         NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
+01480 
+01481         resamplePicture32 ((NLMISC::CRGBA*)&_Data[0][0], pDestRgba, _Width, _Height, nNewWidth, nNewHeight);
+01482         NLMISC::contReset(_Data[0]); // free memory
+01483         _Data[0] =  pDestui;
+01484         _Width= nNewWidth;
+01485         _Height= nNewHeight;
+01486 
+01487         // Rebuilding mipmaps
+01488         if(needRebuild)
+01489         {
+01490                 buildMipMaps();
+01491         }
+01492 }
+01493 
+01494 
+01495 /*-------------------------------------------------------------------*\
+01496                                                         resize
+01497 \*-------------------------------------------------------------------*/
+01498 void CBitmap::resize (sint32 nNewWidth, sint32 nNewHeight, TType newType)
+01499 {
+01500         // Deleting mipmaps
+01501         releaseMipMaps();
+01502 
+01503         // Change type of bitmap ?
+01504         if (newType!=DonTKnow)
+01505                 PixelFormat=newType;
+01506 
+01507         _Width = nNewWidth;
+01508         _Height = nNewHeight;
+01509 
+01510         // resize the level 0 only.
+01511         resizeMipMap(0, nNewWidth, nNewHeight);
+01512 }
+01513 
+01514 
+01515 /*-------------------------------------------------------------------*\
+01516                                                         resizeMipMap
+01517 \*-------------------------------------------------------------------*/
+01518 void CBitmap::resizeMipMap (uint32 numMipMap, sint32 nNewWidth, sint32 nNewHeight)
+01519 {
+01520         nlassert(numMipMap<MAX_MIPMAP);
+01521 
+01522         // free memory
+01523         NLMISC::contReset(_Data[numMipMap]);
+01524 
+01525         // DXTC compressed??
+01526         bool    isDXTC= PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha || PixelFormat==DXTC3 || PixelFormat==DXTC5;
+01527         // if yes, must round up width and height to 4, for allocation
+01528         nNewWidth= 4*((nNewWidth+3)/4);
+01529         nNewHeight= 4*((nNewHeight+3)/4);
+01530 
+01531         // resize the buffer
+01532         _Data[numMipMap].resize (((uint32)(nNewWidth*nNewHeight)*bitPerPixels[PixelFormat])/8);
+01533 }
+01534 
+01535 
+01536 /*-------------------------------------------------------------------*\
+01537                                                         reset
+01538 \*-------------------------------------------------------------------*/
+01539 void CBitmap::setMipMapCount(uint32 mmc)
+01540 {
+01541         _MipMapCount= uint8(mmc);
+01542 }
+01543 
+01544 
+01545 /*-------------------------------------------------------------------*\
+01546                                                         reset
+01547 \*-------------------------------------------------------------------*/
+01548 void CBitmap::reset(TType type)
+01549 {
+01550         for(uint i=0; i<_MipMapCount; i++)
+01551         {
+01552                 NLMISC::contReset(_Data[i]);
+01553                 _Data[i].resize(0);
+01554         }
+01555         _Width = _Height = 0;
+01556         _MipMapCount= 1;
+01557         
+01558         // Change pixel format
+01559         PixelFormat=type;
+01560 }
+01561 
+01562 
+01563 
+01564 /*-------------------------------------------------------------------*\
+01565                                                         resamplePicture32
+01566 \*-------------------------------------------------------------------*/
+01567 void CBitmap::resamplePicture32 (const NLMISC::CRGBA *pSrc, NLMISC::CRGBA *pDest, 
+01568                                                                  sint32 nSrcWidth, sint32 nSrcHeight, 
+01569                                                                  sint32 nDestWidth, sint32 nDestHeight)
+01570 {
+01571         if ((nSrcWidth<=0)||(nSrcHeight<=0)||(nDestHeight<=0)||(nDestHeight<=0))
+01572                 return;
+01573         bool bXMag=(nDestWidth>=nSrcWidth);
+01574         bool bYMag=(nDestHeight>=nSrcHeight);
+01575         bool bXEq=(nDestWidth==nSrcWidth);
+01576         bool bYEq=(nDestHeight==nSrcHeight);
+01577         std::vector<NLMISC::CRGBAF> pIterm (nDestWidth*nSrcHeight);
+01578         
+01579         if (bXMag)
+01580         {
+01581                 float fXdelta=(float)(nSrcWidth)/(float)(nDestWidth);
+01582                 NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
+01583                 sint32 nY;
+01584                 for (nY=0; nY<nSrcHeight; nY++)
+01585                 {
+01586                         const NLMISC::CRGBA *pSrcLine=pSrc;
+01587                         float fX=0.f;
+01588                         sint32 nX;
+01589                         for (nX=0; nX<nDestWidth; nX++)
+01590                         {
+01591                                 float fVirgule=fX-(float)floor(fX);
+01592                                 nlassert (fVirgule>=0.f);
+01593                                 NLMISC::CRGBAF vColor;
+01594                                 if (fVirgule>=0.5f)
+01595                                 {
+01596                                         if (fX<(float)(nSrcWidth-1))
+01597                                         {
+01598                                                 NLMISC::CRGBAF vColor1 (pSrcLine[(sint32)floor(fX)]);
+01599                                                 NLMISC::CRGBAF vColor2 (pSrcLine[(sint32)floor(fX)+1]);
+01600                                                 vColor=vColor1*(1.5f-fVirgule)+vColor2*(fVirgule-0.5f);
+01601                                         }
+01602                                         else
+01603                                                 vColor=NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
+01604                                 }
+01605                                 else
+01606                                 {
+01607                                         if (fX>=1.f)
+01608                                         {
+01609                                                 NLMISC::CRGBAF vColor1 (pSrcLine[(sint32)floor(fX)]);
+01610                                                 NLMISC::CRGBAF vColor2 (pSrcLine[(sint32)floor(fX)-1]);
+01611                                                 vColor=vColor1*(0.5f+fVirgule)+vColor2*(0.5f-fVirgule);
+01612                                         }
+01613                                         else
+01614                                                 vColor=NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
+01615                                 }
+01616                                 *(pItermPtr++)=vColor;
+01617                                 fX+=fXdelta;
+01618                         }
+01619                         pSrc+=nSrcWidth;
+01620                 }
+01621         }
+01622         else if (bXEq)
+01623         {
+01624                 NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
+01625                 for (sint32 nY=0; nY<nSrcHeight; nY++)
+01626                 {
+01627                         const NLMISC::CRGBA *pSrcLine=pSrc;
+01628                         sint32 nX;
+01629                         for (nX=0; nX<nDestWidth; nX++)
+01630                                 *(pItermPtr++)=NLMISC::CRGBAF (pSrcLine[nX]);
+01631                         pSrc+=nSrcWidth;
+01632                 }
+01633         }
+01634         else
+01635         {
+01636                 double fXdelta=(double)(nSrcWidth)/(double)(nDestWidth);
+01637                 nlassert (fXdelta>1.f);
+01638                 NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
+01639                 sint32 nY;
+01640                 for (nY=0; nY<nSrcHeight; nY++)
+01641                 {
+01642                         const NLMISC::CRGBA *pSrcLine=pSrc;
+01643                         double fX=0.f;
+01644                         sint32 nX;
+01645                         for (nX=0; nX<nDestWidth; nX++)
+01646                         {
+01647                                 NLMISC::CRGBAF vColor (0.f, 0.f, 0.f, 0.f);
+01648                                 double fFinal=fX+fXdelta;
+01649                                 while (fX<fFinal)
+01650                                 {
+01651                                         double fNext=(double)floor (fX)+1.f;
+01652                                         if (fNext>fFinal)
+01653                                                 fNext=fFinal;
+01654                                         vColor+=((float)(fNext-fX))*NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
+01655                                         fX=fNext;
+01656                                 }
+01657                                 nlassert (fX==fFinal);
+01658                                 vColor/=(float)fXdelta;
+01659                                 *(pItermPtr++)=vColor;
+01660                         }
+01661                         pSrc+=nSrcWidth;
+01662                 }
+01663         }
+01664                                 
+01665         if (bYMag)
+01666         {
+01667                 double fYdelta=(double)(nSrcHeight)/(double)(nDestHeight);
+01668                 sint32 nX;
+01669                 for (nX=0; nX<nDestWidth; nX++)
+01670                 {
+01671                         double fY=0.f;
+01672                         sint32 nY;
+01673                         for (nY=0; nY<nDestHeight; nY++)
+01674                         {
+01675                                 double fVirgule=fY-(double)floor(fY);
+01676                                 nlassert (fVirgule>=0.f);
+01677                                 NLMISC::CRGBAF vColor;
+01678                                 if (fVirgule>=0.5f)
+01679                                 {
+01680                                         if (fY<(double)(nSrcHeight-1))
+01681                                         {
+01682                                                 NLMISC::CRGBAF vColor1=pIterm[((sint32)floor(fY))*nDestWidth+nX];
+01683                                                 NLMISC::CRGBAF vColor2=pIterm[(((sint32)floor(fY))+1)*nDestWidth+nX];
+01684                                                 vColor=vColor1*(1.5f-(float)fVirgule)+vColor2*((float)fVirgule-0.5f);
+01685                                         }
+01686                                         else
+01687                                                 vColor=pIterm[((sint32)floor(fY))*nDestWidth+nX];
+01688                                 }
+01689                                 else
+01690                                 {
+01691                                         if (fY>=1.f)
+01692                                         {
+01693                                                 NLMISC::CRGBAF vColor1=pIterm[((sint32)floor(fY))*nDestWidth+nX];
+01694                                                 NLMISC::CRGBAF vColor2=pIterm[(((sint32)floor(fY))-1)*nDestWidth+nX];
+01695                                                 vColor=vColor1*(0.5f+(float)fVirgule)+vColor2*(0.5f-(float)fVirgule);
+01696                                         }
+01697                                         else
+01698                                                 vColor=pIterm[((sint32)floor(fY))*nDestWidth+nX];
+01699                                 }
+01700                                 pDest[nX+nY*nDestWidth]=vColor;
+01701                                 fY+=fYdelta;
+01702                         }
+01703                 }
+01704         }
+01705         else if (bYEq)
+01706         {
+01707                 for (sint32 nX=0; nX<nDestWidth; nX++)
+01708                 {
+01709                         sint32 nY;
+01710                         for (nY=0; nY<nDestHeight; nY++)
+01711                         {
+01712                                 pDest[nX+nY*nDestWidth]=pIterm[nY*nDestWidth+nX];
+01713                         }
+01714                 }
+01715         }
+01716         else
+01717         {
+01718                 double fYdelta=(double)(nSrcHeight)/(double)(nDestHeight);
+01719                 nlassert (fYdelta>1.f);
+01720                 sint32 nX;
+01721                 for (nX=0; nX<nDestWidth; nX++)
+01722                 {
+01723                         double fY=0.f;
+01724                         sint32 nY;
+01725                         for (nY=0; nY<nDestHeight; nY++)
+01726                         {
+01727                                 NLMISC::CRGBAF vColor (0.f, 0.f, 0.f, 0.f);
+01728                                 double fFinal=fY+fYdelta;
+01729                                 while ((fY<fFinal)&&((sint32)fY!=nSrcHeight))
+01730                                 {
+01731                                         double fNext=(double)floor (fY)+1.f;
+01732                                         if (fNext>fFinal)
+01733                                                 fNext=fFinal;
+01734                                         vColor+=((float)(fNext-fY))*pIterm[((sint32)floor(fY))*nDestWidth+nX];
+01735                                         fY=fNext;
+01736                                 }
+01737                                 vColor/=(float)fYdelta;
+01738                                 pDest[nX+nY*nDestWidth]=vColor;
+01739                         }
+01740                 }
+01741         }
+01742 }
+01743 
+01744 
+01745 
+01746 /*-------------------------------------------------------------------*\
+01747                                                         readTGA
+01748 \*-------------------------------------------------------------------*/
+01749 uint8 CBitmap::readTGA( NLMISC::IStream &f)
+01750 {
+01751         if(!f.isReading()) return 0;
+01752 
+01753         uint32                  size;
+01754         uint32                  x,y;
+01755         sint32                  slsize;
+01756         uint8                   *scanline;
+01757         uint8                   r,g,b;
+01758         sint32                  i,j,k;
+01759 
+01760         // TGA file header fields
+01761         uint8   lengthID;
+01762         uint8   cMapType;
+01763         uint8   imageType;
+01764         uint16  origin;
+01765         uint16  length;
+01766         uint8   depth;
+01767         uint16  xOrg;
+01768         uint16  yOrg;
+01769         uint16  width;
+01770         uint16  height;
+01771         uint8   imageDepth;
+01772         uint8   desc;
+01773 
+01774         // Image/Color map data
+01775         uint8 *imageID;
+01776         
+01777         
+01778         
+01779         // Determining whether file is in Original or New TGA format
+01780         
+01781         bool newTgaFormat;
+01782         uint32 extAreaOffset;
+01783         uint32 devDirectoryOffset;
+01784         char signature[16];
+01785 
+01786         f.seek (0, f.end);
+01787         newTgaFormat = false;
+01788         if (f.getPos() >= 26)
+01789         {
+01790                 f.seek (-26, f.end);
+01791                 f.serial(extAreaOffset);
+01792                 f.serial(devDirectoryOffset);
+01793                 for(i=0; i<16; i++)
+01794                 {
+01795                         f.serial(signature[i]);
+01796                 }
+01797                 if(strncmp(signature,"TRUEVISION-XFILE",16)==0)
+01798                         newTgaFormat = true;
+01799         }
+01800 
+01801 
+01802 
+01803         // Reading TGA file header
+01804         f.seek (0, f.begin);
+01805                 
+01806         f.serial(lengthID);
+01807         f.serial(cMapType);
+01808         f.serial(imageType);
+01809         f.serial(origin);
+01810         f.serial(length);
+01811         f.serial(depth);
+01812         f.serial(xOrg);
+01813         f.serial(yOrg);
+01814         f.serial(width);
+01815         f.serial(height);
+01816         f.serial(imageDepth);
+01817         f.serial(desc);
+01818 
+01819         if(cMapType!=0)
+01820         {
+01821                 nlinfo("readTga : color-map not supported");
+01822         }
+01823 
+01824         if(lengthID>0)
+01825         {
+01826                 imageID = new uint8[lengthID];
+01827                 for(i=0; i<lengthID; i++)
+01828                         f.serial(imageID[i]);
+01829         }
+01830 
+01831 
+01832 
+01833         // Reading TGA image data
+01834         
+01835         _Width = width;
+01836         _Height = height;
+01837         size = _Width * _Height * (imageDepth/8);
+01838         
+01839         switch(imageType)
+01840         {
+01841                 // Uncompressed RGB or RGBA
+01842                 case 2:
+01843                 {
+01844                         _Data[0].resize(_Width*_Height*4);
+01845                         uint8 upSideDown = ((desc & (1 << 5))==0);
+01846                         slsize = _Width * imageDepth / 8;
+01847 
+01848                         scanline = new uint8[slsize];
+01849                         if(!scanline)
+01850                         {
+01851                                 throw EAllocationFailure();
+01852                         }
+01853 
+01854                         for(y=0; y<_Height;y++)
+01855                         {
+01856                                 // Serial buffer: more efficient way to load.
+01857                                 f.serialBuffer (scanline, slsize);
+01858 
+01859                                 if(imageDepth==24 || imageDepth==32)
+01860                                 {
+01861                                         sint32 mult = 3;
+01862                                         if(imageDepth==16)
+01863                                         {
+01864                                                 mult = 2;
+01865                                         }
+01866                                         if(imageDepth==32)  
+01867                                         {
+01868                                                 mult = 4;
+01869                                         }
+01870                                         if(imageDepth!=16)
+01871                                         {
+01872                                                 for(x=0; x<_Width; x++)
+01873                                                 {
+01874                                                         // RGB(A)
+01875                                                         r = scanline[x*mult+0];
+01876                                                         g = scanline[x*mult+1];
+01877                                                         b = scanline[x*mult+2];
+01878                                                         // Switching to BGR(A)
+01879                                                         scanline[x*mult+0] = b;
+01880                                                         scanline[x*mult+1] = g;
+01881                                                         scanline[x*mult+2] = r;
+01882                                                 }
+01883                                         }
+01884                                 }
+01885                                 
+01886                                 k=0;
+01887                                 for(i=0; i<width; i++) 
+01888                                 {
+01889                                         if(upSideDown)
+01890                                         {
+01891                                                 if(imageDepth==16)
+01892                                                 {
+01893                                                         uint16 toto = (uint16)scanline[k++];
+01894                                                         toto |= scanline[k++]<<8;
+01895                                                         uint r = toto>>10;
+01896                                                         uint g = (toto>>5)&0x1f;
+01897                                                         uint b = toto&0x1f;
+01898                                                         _Data[0][(height-y-1)*width*4 + 4*i] = (r<<3) | (r>>2);
+01899                                                         _Data[0][(height-y-1)*width*4 + 4*i + 1] = (g<<3) | (g>>2);
+01900                                                         _Data[0][(height-y-1)*width*4 + 4*i + 2] = (b<<3) | (b>>2);
+01901                                                         _Data[0][(height-y-1)*width*4 + 4*i + 3] = 255;
+01902                                                 }
+01903                                                 else
+01904                                                 {
+01905                                                         _Data[0][(height-y-1)*width*4 + 4*i] = scanline[k++];
+01906                                                         _Data[0][(height-y-1)*width*4 + 4*i + 1] = scanline[k++];
+01907                                                         _Data[0][(height-y-1)*width*4 + 4*i + 2] = scanline[k++];
+01908                                                         if(imageDepth==32)
+01909                                                                 _Data[0][(height-y-1)*width*4 + 4*i + 3] = scanline[k++];
+01910                                                         else
+01911                                                                 _Data[0][(height-y-1)*width*4 + 4*i + 3] = 255;
+01912                                                 }
+01913                                         }
+01914                                         else
+01915                                         {
+01916                                                 if(imageDepth==16)
+01917                                                 {
+01918                                                         uint16 toto = (uint16)scanline[k++];
+01919                                                         toto |= scanline[k++]<<8;
+01920                                                         int r = toto>>10;
+01921                                                         int g = toto&(0x3e0)>>5;
+01922                                                         int b = toto&0x1f;
+01923                                                         _Data[0][y*width*4 + 4*i] = (r<<3) | (r>>2);
+01924                                                         _Data[0][y*width*4 + 4*i + 1] = (g<<3) | (g>>2);
+01925                                                         _Data[0][y*width*4 + 4*i + 2] = (b<<3) | (b>>2);
+01926                                                         _Data[0][y*width*4 + 4*i + 3] = 255;
+01927                                                 }
+01928                                                 else
+01929                                                 {
+01930                                                         _Data[0][y*width*4 + 4*i] = scanline[k++];
+01931                                                         _Data[0][y*width*4 + 4*i + 1] = scanline[k++];
+01932                                                         _Data[0][y*width*4 + 4*i + 2] = scanline[k++];
+01933                                                         if(imageDepth==32)
+01934                                                                 _Data[0][y*width*4 + 4*i + 3] = scanline[k++];
+01935                                                         else
+01936                                                                 _Data[0][y*width*4 + 4*i + 3] = 255;
+01937                                                 }
+01938                                         }       
+01939                                 }
+01940                         }
+01941 
+01942                         PixelFormat = RGBA;
+01943                         delete scanline;
+01944                 };
+01945                 break;
+01946                 
+01947                 // Uncompressed Grayscale bitmap
+01948                 case 3:
+01949                 {
+01950                         _Data[0].resize(_Width*_Height);
+01951                         uint8 upSideDown = ((desc & (1 << 5))==0);
+01952                         slsize = _Width;
+01953 
+01954                         scanline = new uint8[slsize];
+01955                         if(!scanline)
+01956                         {
+01957                                 throw EAllocationFailure();
+01958                         }
+01959 
+01960                         for(y=0; y<_Height;y++)
+01961                         {
+01962                                 // Serial buffer: more efficient way to load.
+01963                                 f.serialBuffer (scanline, slsize);
+01964 
+01965                                 k=0;
+01966                                 for(i=0; i<width; i++) 
+01967                                 {
+01968                                         if(upSideDown)
+01969                                                 _Data[0][(height-y-1)*width + i] = scanline[k++];
+01970                                         else
+01971                                                 _Data[0][y*width + i] = scanline[k++];
+01972                                 }
+01973                         }
+01974 
+01975                         PixelFormat = _LoadGrayscaleAsAlpha?Alpha:Luminance;
+01976                         delete scanline;
+01977                 };
+01978                 break;
+01979 
+01980                 // Compressed RGB or RGBA
+01981                 case 10:
+01982                 {
+01983                         uint8 packet;
+01984                         uint8 pixel[4];
+01985                         uint32 imageSize = width*height;
+01986                         uint32 readSize = 0;
+01987                         _Data[0].reserve(_Width*_Height*4);
+01988 
+01989                         while(readSize < imageSize)
+01990                         {
+01991                                 f.serial(packet);
+01992                                 if((packet & 0x80) > 0) // packet RLE 
+01993                                 { 
+01994                                         for(i=0; i<imageDepth/8; i++)
+01995                                         {
+01996                                                 f.serial(pixel[i]);
+01997                                         }
+01998                                         for (i=0; i < (packet & 0x7F) + 1; i++)
+01999                                         {
+02000                                                 for(j=0; j<imageDepth/8; j++)
+02001                                                 {
+02002                                                         _Data[0].push_back(pixel[j]);
+02003                                                 }
+02004                                                 if(imageDepth==24)
+02005                                                 {
+02006                                                         _Data[0].push_back(0);
+02007                                                 }
+02008                                         }
+02009                                 }
+02010                                 else    // packet Raw 
+02011                                 { 
+02012                                         for(i=0; i<((packet & 0x7F) + 1); i++)
+02013                                         {
+02014                                                 for(j=0; j<imageDepth/8; j++)
+02015                                                 {
+02016                                                         f.serial(pixel[j]);
+02017                                                 }
+02018                                                 if(imageDepth==32)
+02019                                                 {
+02020                                                         _Data[0].push_back(pixel[2]);
+02021                                                         _Data[0].push_back(pixel[1]);
+02022                                                         _Data[0].push_back(pixel[0]);
+02023                                                         _Data[0].push_back(pixel[3]);
+02024                                                 }
+02025                                                 if(imageDepth==24)
+02026                                                 {
+02027                                                         _Data[0].push_back(pixel[2]);
+02028                                                         _Data[0].push_back(pixel[1]);
+02029                                                         _Data[0].push_back(pixel[0]);
+02030                                                         _Data[0].push_back(0);
+02031                                                 }
+02032                                         }
+02033                                 }
+02034                                 readSize += (packet & 0x7F) + 1;
+02035                         }
+02036                         PixelFormat = RGBA;
+02037                 };
+02038                 break;
+02039 
+02040                 // Compressed Grayscale bitmap (not tested)
+02041                 case 11:
+02042                 {
+02043                         uint8 packet;
+02044                         uint8 pixel[4];
+02045                         uint32 imageSize = width*height;
+02046                         uint32 readSize = 0;
+02047                         _Data[0].reserve(_Width*_Height);
+02048 
+02049                         while(readSize < imageSize)
+02050                         {
+02051                                 f.serial(packet);
+02052                                 if((packet & 0x80) > 0) // packet RLE 
+02053                                 { 
+02054                                         f.serial(pixel[0]);
+02055                                         for (i=0; i < (packet & 0x7F) + 1; i++)
+02056                                         {
+02057                                                 _Data[0].push_back(pixel[0]);
+02058                                         }
+02059                                 }
+02060                                 else    // packet Raw 
+02061                                 { 
+02062                                         for(i=0; i<((packet & 0x7F) + 1); i++)
+02063                                         {
+02064                                                 f.serial(pixel[0]);
+02065                                                 _Data[0].push_back(pixel[0]);
+02066                                         }
+02067                                 }
+02068                                 readSize += (packet & 0x7F) + 1;
+02069                         }
+02070                         PixelFormat = _LoadGrayscaleAsAlpha?Alpha:Luminance;
+02071                 };
+02072                 break;
+02073 
+02074                 default:
+02075                         return 0;
+02076         }
+02077 
+02078         _MipMapCount = 1;
+02079         return(imageDepth);
+02080 
+02081 }
+02082 
+02083 /*-------------------------------------------------------------------*\
+02084                                                         writeTGA
+02085 \*-------------------------------------------------------------------*/
+02086 bool CBitmap::writeTGA( NLMISC::IStream &f, uint32 d, bool upsideDown)
+02087 {
+02088         if(f.isReading()) return false;
+02089         if(d!=24 && d!=32 && d!=16 && d!=8) return false;
+02090         if ((PixelFormat != RGBA)&&(PixelFormat != Alpha)) return false;
+02091         if ((PixelFormat == Alpha) && (d != 8)) return false;
+02092 
+02093         sint32  i,j,x,y;
+02094         uint8   * scanline;
+02095         uint8   r,g,b,a;
+02096 
+02097         uint8   lengthID = 0;
+02098         uint8   cMapType = 0;
+02099         uint8   imageType = 2;
+02100         uint16  origin = 0;
+02101         uint16  length = 0;
+02102         uint8   depth = 0;
+02103         uint16  xOrg = 0;
+02104         uint16  yOrg = 0;
+02105         uint16  width = (uint16)_Width;
+02106         uint16  height = (uint16)_Height;
+02107         uint8   imageDepth = (uint8)d;
+02108         uint8   desc = 0;
+02109         if (upsideDown)
+02110                 desc |= 1<<5;
+02111 
+02112         if (PixelFormat == Alpha)
+02113                 imageType = 3; // Uncompressed grayscale
+02114 
+02115         f.serial(lengthID);
+02116         f.serial(cMapType);
+02117         f.serial(imageType);
+02118         f.serial(origin);
+02119         f.serial(length);
+02120         f.serial(depth);
+02121         f.serial(xOrg);
+02122         f.serial(yOrg);
+02123         f.serial(width);
+02124         f.serial(height);
+02125         f.serial(imageDepth);
+02126         f.serial(desc);
+02127 
+02128         if (PixelFormat == Alpha)
+02129                 scanline = new uint8[width];
+02130         else
+02131                 scanline = new uint8[width*4];
+02132         if(!scanline)
+02133         {
+02134                 throw EAllocationFailure();
+02135         }
+02136 
+02137         for(y=0; y<(sint32)height; y++)
+02138         {
+02139                 
+02140                 uint32 k=0;
+02141                 if (PixelFormat == Alpha)
+02142                 for(i=0; i<width; ++i) // Alpha
+02143                 {
+02144                         scanline[k++] = _Data[0][(height-y-1)*width + i];
+02145                 }
+02146                 else
+02147                 for(i=0; i<width*4; i+=4) // 4:RGBA
+02148                 {
+02149                         if(d==16)
+02150                         {
+02151                                 for(j=0; j<(sint32)4; j++)
+02152                                 {
+02153                                         scanline[k++] = _Data[0][(height-y-1)*width*4 + i + j];
+02154                                 }
+02155                         }
+02156                         else
+02157                         {
+02158                                 for(j=0; j<(sint32)d/8; j++)
+02159                                 {
+02160                                         scanline[k++] = _Data[0][(height-y-1)*width*4 + i + j];
+02161                                 }
+02162                         }
+02163                 }
+02164                 
+02165                 if(d==16)
+02166                 {
+02167                         for(x=0; x<(sint32)width; x++)
+02168                         {
+02169                                 r = scanline[x*4+0];
+02170                                 g = scanline[x*4+1];
+02171                                 b = scanline[x*4+2];
+02172                                 int rr = r >>3;
+02173                                 int gg = g >>3;
+02174                                 int bb = b >>3;
+02175                                 uint16 c16 = (rr<<10) | (gg<<5) | bb;
+02176                                 scanline[x*2+0] = c16&0xff;
+02177                                 scanline[x*2+1] = c16>>8;
+02178                         }
+02179                 }
+02180                 if(d==24)
+02181                 {
+02182                         for(x=0; x<(sint32)width; x++)
+02183                         {
+02184                                 r = scanline[x*3+0];
+02185                                 g = scanline[x*3+1];
+02186                                 b = scanline[x*3+2];
+02187                                 scanline[x*3+0] = b;
+02188                                 scanline[x*3+1] = g;
+02189                                 scanline[x*3+2] = r;
+02190                         }
+02191                 }
+02192                 if(d==32)
+02193                 {
+02194                         for(x=0; x<(sint32)width; x++)
+02195                         {
+02196                                 r = scanline[x*4+0];
+02197                                 g = scanline[x*4+1];
+02198                                 b = scanline[x*4+2];
+02199                                 a= scanline[x*4+3];
+02200                                 scanline[x*4+0] = b;
+02201                                 scanline[x*4+1] = g;
+02202                                 scanline[x*4+2] = r;                            
+02203                                 scanline[x*4+3] = a;
+02204                         }
+02205                 }
+02206                 
+02207                 int finaleSize=width*d/8;
+02208                 for(i=0; i<finaleSize; i++)
+02209                 {
+02210                         f.serial(scanline[i]);
+02211                 }               
+02212         }
+02213         delete scanline;
+02214         return true;
+02215 }
+02216 
+02217 template<class T>
+02218 void rotateCCW (const T* src, T* dst, uint srcWidth, uint srcHeight)
+02219 {
+02220         for (uint y=0; y<srcHeight; y++)
+02221         for (uint x=0; x<srcWidth; x++)
+02222         {
+02223                 uint dstX=y;
+02224                 uint dstY=srcWidth-x-1;
+02225                 dst[dstX+dstY*srcHeight]=src[x+y*srcWidth];
+02226         }
+02227 }
+02228 
+02229 /*template<class T>
+02230 void rotateCCW (const vector<T>& src, vector<T>& dst, uint srcWidth, uint srcHeight)
+02231 {
+02232         for (uint y=0; y<srcHeight; y++)
+02233         for (uint x=0; x<srcWidth; x++)
+02234         {
+02235                 uint dstX=y;
+02236                 uint dstY=srcWidth-x;
+02237                 dst[dstX+dstY*srcHeight]=src[x+y*srcWidth];
+02238         }
+02239 }
+02240 */
+02241 void CBitmap::rotateCCW()
+02242 {
+02243         // Copy the array
+02244         std::vector<uint8> copy=_Data[0];
+02245 
+02246         switch (PixelFormat)
+02247         {
+02248         case RGBA:
+02249                 NLMISC::rotateCCW ((uint32*)&(_Data[0][0]), (uint32*)&(copy[0]), _Width, _Height);
+02250                 break;
+02251         case Luminance:
+02252         case Alpha:
+02253                 NLMISC::rotateCCW (&_Data[0][0], &copy[0], _Width, _Height);
+02254                 break;
+02255         case AlphaLuminance:
+02256                 NLMISC::rotateCCW ((uint16*)&(_Data[0][0]), (uint16*)&(copy[0]), _Width, _Height);;
+02257                 break;
+02258         default: break;
+02259         }
+02260 
+02261         uint32 tmp=_Width;
+02262         _Width=_Height;
+02263         _Height=tmp;
+02264         _Data[0]=copy;
+02265 }
+02266 
+02267 bool CBitmap::blit(const CBitmap *src, sint32 x, sint32 y)
+02268 {
+02269         
+02270         nlassert(this->PixelFormat == src->PixelFormat);
+02271         if (this->PixelFormat != src->PixelFormat)
+02272         {
+02273                 return false;
+02274         }
+02275 
+02276 
+02277         // check for dxtc use
+02278 
+02279         const bool useDXTC   =  PixelFormat == DXTC1 || PixelFormat == DXTC1Alpha || PixelFormat == DXTC3 || PixelFormat ==     DXTC5;
+02280 
+02281         // number of bits for a 4x4 pix block
+02282         const uint dxtcNumBits  =  PixelFormat == DXTC1 || PixelFormat == DXTC1Alpha ? 64 : 128;
+02283         
+02284 
+02285         if (useDXTC)
+02286         {
+02287                 // blit pos must be multiple of 4
+02288 
+02289                 nlassert(! (x & 3 || y & 3) );
+02290                 if (x & 3 || y & 3) return false;
+02291 
+02292         }
+02293 
+02294         nlassert(PixelFormat != DonTKnow);
+02295 
+02296         // the width to copy
+02297         sint width = src->_Width;
+02298         // the height to copy
+02299         sint height = src->_Height;
+02300 
+02301         uint destStartX, destStartY;
+02302         uint srcStartX, srcStartY;
+02303 
+02304 
+02305         // clip against left
+02306         if (x < 0)
+02307         {
+02308                 width += x;
+02309                 if (width <= 0) return true;
+02310                 destStartX = 0;
+02311                 srcStartX = -x;
+02312         }
+02313         else
+02314         {
+02315                 destStartX = x;
+02316                 srcStartX = 0;
+02317         }
+02318 
+02319         // clip against top
+02320         if (y < 0)
+02321         {
+02322                 height += y;
+02323                 if (height <= 0) return true;
+02324                 srcStartY = -y;
+02325                 destStartY = 0;
+02326         }
+02327         else
+02328         {
+02329                 destStartY = y;
+02330                 srcStartY = 0;
+02331         }
+02332 
+02333         // clip against right
+02334         if ((destStartX + width - 1) >= _Width)
+02335         {
+02336                 width = _Width - destStartX;
+02337                 if (width <= 0) return true;
+02338         }
+02339 
+02340         // clip against bottom
+02341         if ((destStartY + height - 1) >= _Height)
+02342         {
+02343                 height = _Height - destStartY;
+02344                 if (width <= 0) return true;
+02345         }
+02346 
+02347 
+02348         // divide all distance by 4 when using DXTC
+02349         if (useDXTC)
+02350         {
+02351                 destStartX >>= 2;
+02352                 destStartY >>= 2;
+02353                 srcStartX >>= 2;
+02354                 srcStartY >>= 2;
+02355                 width >>= 2;
+02356                 height >>= 2;
+02357         }
+02358         
+02359 
+02360         // bytes per pixs is for either one pixel or 16 (a 4x4 block in DXTC)
+02361         const uint bytePerPixs = ( useDXTC ? dxtcNumBits : bitPerPixels[PixelFormat] ) >> 3 /* divide by 8 to get the number of bytes */;
+02362 
+02363 
+02364         const uint destRealWidth = useDXTC ? (_Width >> 2) : _Width;
+02365         const uint srcRealWidth = useDXTC ? (src->_Width >> 2) : src->_Width;
+02366         
+02367 
+02368         // size to go to the next line in the destination
+02369         const uint destStride = destRealWidth * bytePerPixs;
+02370 
+02371         // size to go to the next line in the source
+02372         const uint srcStride = srcRealWidth * bytePerPixs;
+02373         
+02374         // length in bytes of a line to copy
+02375         const uint lineLength = width * bytePerPixs;
+02376 
+02377 
+02378         uint8  *destPos = &(_Data[0][0]) + destStride * destStartY + bytePerPixs * destStartX;
+02379         const uint8 *srcPos = &(src->_Data[0][0]) + srcStride * srcStartY + bytePerPixs * srcStartX;
+02380 
+02381         // copy each hline
+02382         for (sint k = 0; k < height; ++k)
+02383         {
+02384                 ::memcpy(destPos, srcPos, lineLength);
+02385                 destPos += destStride;
+02386                 srcPos += srcStride;
+02387         }
+02388 
+02389         
+02390         return true;
+02391 }
+02392 
+02393 // Private :
+02394 float CBitmap::getColorInterp (float x, float y, float colorInXY00, float colorInXY10, float colorInXY01, float colorInXY11) const
+02395 {
+02396         float res =     colorInXY00*(1.0f-x)*(1.0f-y) +
+02397                                 colorInXY10*(     x)*(1.0f-y) +
+02398                                 colorInXY01*(1.0f-x)*(     y) +
+02399                                 colorInXY11*(     x)*(     y);
+02400         clamp (res, 0.0f, 255.0f);
+02401         return res;
+02402 }
+02403 
+02404 // Public:
+02405 CRGBAF CBitmap::getColor (float x, float y) const
+02406 {
+02407         if (x < 0.0f) x = 0.0f;
+02408         if (x > 1.0f) x = 1.0f;
+02409         if (y < 0.0f) y = 0.0f;
+02410         if (y > 1.0f) y = 1.0f;
+02411 
+02412         sint32 nWidth = getWidth(0);
+02413         sint32 nHeight = getHeight(0);
+02414 
+02415         if (nWidth == 0 || nHeight == 0) return CRGBAF(0, 0, 0, 0);
+02416 
+02417         const std::vector<uint8> &rBitmap = getPixels(0);
+02418         sint32 nX[4], nY[4];
+02419 
+02420         x *= nWidth-1;
+02421         y *= nHeight-1;
+02422 
+02423         // Integer part of (x,y)
+02424         //nX[0] = ((sint32)floor(x-0.5f));
+02425         //nY[0] = ((sint32)floor(y-0.5f));
+02426         nX[0] = ((sint32)floor(x));
+02427         nY[0] = ((sint32)floor(y));
+02428 
+02429         nX[1] = (nX[0] < (nWidth-1) ? nX[0]+1 : nX[0]);
+02430         nY[1] = nY[0];
+02431 
+02432         nX[2] = nX[0];
+02433         nY[2] = (nY[0] < (nHeight-1) ? nY[0]+1 : nY[0]);
+02434 
+02435         nX[3] = nX[1];
+02436         nY[3] = nY[2];
+02437 
+02438         uint32 i;
+02439 
+02440         for (i = 0; i < 4; ++i)
+02441         {
+02442                 nlassert (nX[i] >= 0);
+02443                 nlassert (nY[i] >= 0 );
+02444                 nlassert (nX[i] < nWidth);
+02445                 nlassert (nY[i] < nHeight);
+02446         }
+02447 
+02448         // Decimal part of (x,y)
+02449         x = x - (float)nX[0]; 
+02450         y = y - (float)nY[0];
+02451 
+02452         switch (this->PixelFormat)
+02453         {
+02454                 case RGBA:
+02455                 case DXTC1:
+02456                 case DXTC1Alpha:
+02457                 case DXTC3:
+02458                 case DXTC5:
+02459                 {                                                                       
+02460                         CRGBAF finalVal;
+02461                         CRGBA val[4];
+02462 
+02463                         if (this->PixelFormat == RGBA)
+02464                         {
+02465                                 for (i = 0; i < 4; ++i)
+02466                                 {
+02467                                         val[i] = CRGBA (rBitmap[(nX[i]+nY[i]*nWidth)*4+0],
+02468                                                                         rBitmap[(nX[i]+nY[i]*nWidth)*4+1],
+02469                                                                         rBitmap[(nX[i]+nY[i]*nWidth)*4+2],
+02470                                                                         rBitmap[(nX[i]+nY[i]*nWidth)*4+3]);
+02471                                 }
+02472                         }
+02473                         else
+02474                         {
+02475                                 // slower version : get from DXT
+02476                                 for (i = 0; i < 4; ++i)
+02477                                 {
+02478                                         val[i] = getPixelColor(nX[i], nY[i]);
+02479                                 }
+02480                         }
+02481 
+02482                         finalVal.R = getColorInterp (x, y, val[0].R, val[1].R, val[2].R, val[3].R);
+02483                         finalVal.G = getColorInterp (x, y, val[0].G, val[1].G, val[2].G, val[3].G);
+02484                         finalVal.B = getColorInterp (x, y, val[0].B, val[1].B, val[2].B, val[3].B);
+02485                         finalVal.A = getColorInterp (x, y, val[0].A, val[1].A, val[2].A, val[3].A);
+02486 
+02487                         return finalVal;                        
+02488                 }
+02489                 break;
+02490                 case Alpha:
+02491                 case Luminance:
+02492                 {
+02493                         
+02494                         float finalVal;
+02495                         float val[4];
+02496 
+02497                         for (i = 0; i < 4; ++i)
+02498                                 val[i] = rBitmap[(nX[i]+nY[i]*nWidth)];
+02499 
+02500                         finalVal = getColorInterp (x, y, val[0], val[1], val[2], val[3]);
+02501 
+02502                         if (this->PixelFormat == Alpha)
+02503                                 return CRGBAF (255.0f, 255.0f, 255.0f, finalVal);
+02504                         else // Luminance
+02505                                 return CRGBAF (finalVal, finalVal, finalVal, 255.0f);
+02506                 }
+02507                 break;
+02508                 default: break;
+02509         }
+02510 
+02511         return CRGBAF (0.0f, 0.0f, 0.0f, 0.0f);
+02512 }
+02513 
+02514 
+02515 void    CBitmap::loadSize(NLMISC::IStream &f, uint32 &retWidth, uint32 &retHeight)
+02516 {
+02517         retWidth= 0;
+02518         retHeight= 0;
+02519 
+02520 
+02521         nlassert(f.isReading()); 
+02522         
+02523         // testing if DDS
+02524         uint32 fileType = 0;
+02525         f.serial(fileType);
+02526         if(fileType == DDS)
+02527         {
+02528                 // read entire DDS header.
+02529                 uint32 size = 0;
+02530                 f.serial(size); // size in Bytes of header(without "DDS")
+02531                 uint32 * _DDSSurfaceDesc = new uint32[size]; 
+02532                 std::auto_ptr<uint32> _DDSSurfaceDescAuto(_DDSSurfaceDesc);
+02533                 _DDSSurfaceDesc[0]= size;
+02534 
+02535                 for(uint i= 0; i<size/4 - 1; i++)
+02536                 {
+02537                         f.serial(_DDSSurfaceDesc[i+1]);
+02538                 }
+02539                 
+02540                 // flags determines which members of the header structure contain valid data
+02541                 uint32 flags = _DDSSurfaceDesc[1];
+02542 
+02543                 //verify if file have linearsize set
+02544                 if(!(flags & DDSD_LINEARSIZE)) 
+02545                 {
+02546                         throw EDDSBadHeader();
+02547                 }
+02548                 
+02549                 //-------------- extracting and testing useful info
+02550                 retWidth = _DDSSurfaceDesc[2];
+02551                 retHeight  = _DDSSurfaceDesc[3];
+02552         }
+02553         // assuming it's TGA
+02554         else 
+02555         {
+02556                 if(!f.seek (0, NLMISC::IStream::begin))
+02557                 {
+02558                         throw ESeekFailed();
+02559                 }
+02560 
+02561                 // Reading header, 
+02562                 // To make sure that the bitmap is TGA, we check imageType and imageDepth.
+02563                 uint8   lengthID;
+02564                 uint8   cMapType;
+02565                 uint8   imageType;
+02566                 uint16  tgaOrigin;
+02567                 uint16  length;
+02568                 uint8   depth;
+02569                 uint16  xOrg;
+02570                 uint16  yOrg;
+02571                 uint16  width;
+02572                 uint16  height;
+02573                 uint8   imageDepth;
+02574                 uint8   desc;
+02575                 
+02576                 f.serial(lengthID);
+02577                 f.serial(cMapType);
+02578                 f.serial(imageType);
+02579                 if(imageType!=2 && imageType!=3 && imageType!=10 && imageType!=11) return;
+02580                 f.serial(tgaOrigin);
+02581                 f.serial(length);
+02582                 f.serial(depth);
+02583                 f.serial(xOrg);
+02584                 f.serial(yOrg);
+02585                 f.serial(width);
+02586                 f.serial(height);
+02587                 f.serial(imageDepth);
+02588                 if(imageDepth!=8 && imageDepth!=24 && imageDepth!=32) return;
+02589                 f.serial(desc);
+02590 
+02591                 // Ok, we have width and height.
+02592                 retWidth= width;
+02593                 retHeight= height;
+02594         }
+02595 
+02596         // reset stream.
+02597         if(!f.seek (0, NLMISC::IStream::begin))
+02598         {
+02599                 throw ESeekFailed();
+02600         }
+02601 }
+02602 
+02603 
+02604 void    CBitmap::loadSize(const std::string &path, uint32 &retWidth, uint32 &retHeight)
+02605 {
+02606         retWidth= 0;
+02607         retHeight= 0;
+02608 
+02609         CIFile          f(path);
+02610         if(f.open(path))
+02611                 loadSize(f, retWidth, retHeight);
+02612 }
+02613 
+02614 
+02615 void    CBitmap::flipH()
+02616 {
+02617         if (PixelFormat != RGBA)
+02618                 return;
+02619 
+02620         sint32 nWidth = getWidth(0);
+02621         sint32 nHeight = getHeight(0);
+02622         sint32 i, j;
+02623         NLMISC::CRGBA *pBitmap = (NLMISC::CRGBA*)&_Data[0][0];
+02624         bool needRebuild = false;
+02625         CRGBA temp;
+02626 
+02627         if(_MipMapCount>1)
+02628                 needRebuild = true;
+02629         releaseMipMaps();
+02630 
+02631         for( i = 0; i < nHeight; ++i )
+02632                 for( j = 0; j < nWidth/2; ++j )
+02633                 {
+02634                         temp = pBitmap[i*nWidth+j];
+02635                         pBitmap[i*nWidth+j] = pBitmap[i*nWidth+nWidth-j-1];
+02636                         pBitmap[i*nWidth+nWidth-j-1] = temp;
+02637                 }
+02638 
+02639         // Rebuilding mipmaps
+02640         if(needRebuild)
+02641         {
+02642                 buildMipMaps();
+02643         }
+02644 }
+02645 
+02646 
+02647 void    CBitmap::flipV()
+02648 {
+02649         if (PixelFormat != RGBA)
+02650                 return;
+02651 
+02652         sint32 nWidth = getWidth(0);
+02653         sint32 nHeight = getHeight(0);
+02654         sint32 i, j;
+02655         NLMISC::CRGBA *pBitmap = (NLMISC::CRGBA*)&_Data[0][0];
+02656         bool needRebuild = false;
+02657         CRGBA temp;
+02658 
+02659         if(_MipMapCount>1)
+02660                 needRebuild = true;
+02661         releaseMipMaps();
+02662 
+02663         for( j = 0; j < nHeight/2; ++j )
+02664                 for( i = 0; i < nWidth; ++i )
+02665                 {
+02666                         temp = pBitmap[j*nWidth+i];
+02667                         pBitmap[j*nWidth+i] = pBitmap[(nHeight-j-1)*nWidth+i];
+02668                         pBitmap[(nHeight-j-1)*nWidth+i] = temp;
+02669                 }
+02670 
+02671         // Rebuilding mipmaps
+02672         if(needRebuild)
+02673         {
+02674                 buildMipMaps();
+02675         }
+02676 }
+02677 
+02678 
+02679 void    CBitmap::rot90CW()
+02680 {
+02681         if (PixelFormat != RGBA)
+02682                 return;
+02683         sint32 nWidth = getWidth(0);
+02684         sint32 nHeight = getHeight(0);
+02685         sint32 i, j;
+02686         NLMISC::CRGBA *pSrcRgba = (NLMISC::CRGBA*)&_Data[0][0];
+02687         bool needRebuild = false;
+02688 
+02689         if(_MipMapCount>1)
+02690                 needRebuild = true;
+02691         releaseMipMaps();
+02692 
+02693         std::vector<uint8> pDestui;
+02694         pDestui.resize(nWidth*nHeight*4);
+02695         NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
+02696 
+02697         for( j = 0; j < nHeight; ++j )
+02698         for( i = 0; i < nWidth;  ++i )
+02699                 pDestRgba[j+i*nHeight] = pSrcRgba[i+(nHeight-1-j)*nWidth];
+02700 
+02701         uint32 nTemp = _Width;
+02702         _Width = _Height;
+02703         _Height = nTemp;
+02704 
+02705         NLMISC::contReset(_Data[0]); // free memory
+02706         _Data[0] =  pDestui;
+02707         // Rebuilding mipmaps
+02708         if(needRebuild)
+02709         {
+02710                 buildMipMaps();
+02711         }
+02712 }
+02713 
+02714 void    CBitmap::rot90CCW()
+02715 {
+02716         if (PixelFormat != RGBA)
+02717                 return;
+02718         sint32 nWidth = getWidth(0);
+02719         sint32 nHeight = getHeight(0);
+02720         sint32 i, j;
+02721         NLMISC::CRGBA *pSrcRgba = (NLMISC::CRGBA*)&_Data[0][0];
+02722         bool needRebuild = false;
+02723 
+02724         if(_MipMapCount>1)
+02725                 needRebuild = true;
+02726         releaseMipMaps();
+02727 
+02728         std::vector<uint8> pDestui;
+02729         pDestui.resize(nWidth*nHeight*4);
+02730         NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
+02731 
+02732         for( j = 0; j < nHeight; ++j )
+02733         for( i = 0; i < nWidth;  ++i )
+02734                 pDestRgba[j+i*nHeight] = pSrcRgba[nWidth-1-i+j*nWidth];
+02735 
+02736         uint32 nTemp = _Width;
+02737         _Width = _Height;
+02738         _Height = nTemp;
+02739 
+02740         NLMISC::contReset(_Data[0]); // free memory
+02741         _Data[0] =  pDestui;
+02742         // Rebuilding mipmaps
+02743         if(needRebuild)
+02744         {
+02745                 buildMipMaps();
+02746         }
+02747 }
+02748 
+02749 //===========================================================================
+02750 
+02751 void CBitmap::blend(const CBitmap &Bm0, const CBitmap &Bm1, uint16 factor)
+02752 {
+02753         nlassert(factor <= 256);
+02754 
+02755         nlassert(Bm0._Width != 0 && Bm0._Height != 0
+02756                          && Bm1._Width != 0 && Bm1._Height != 0);
+02757 
+02758         nlassert(Bm0._Width  == Bm1._Width);    // the bitmap should have the same size
+02759         nlassert(Bm0._Height == Bm1._Height);
+02760 
+02761         const CBitmap *nBm0, *nBm1; // pointer to the bitmap that is used for blending, or to a copy is a conversion wa required
+02762 
+02763         CBitmap cp0, cp1; // these bitmap are copies of Bm1 and Bm0 if a conversion was needed
+02764 
+02765         if (Bm0.PixelFormat != RGBA)
+02766         {
+02767                 cp0 = Bm0;
+02768                 cp0.convertToRGBA();
+02769                 nBm0 = &cp0;
+02770         }
+02771         else
+02772         {
+02773                 nBm0 = &Bm0;
+02774         }
+02775 
+02776 
+02777         if (Bm1.PixelFormat != RGBA)
+02778         {
+02779                 cp1 = Bm1;
+02780                 cp1.convertToRGBA();
+02781                 nBm1 = &cp1;
+02782         }
+02783         else
+02784         {
+02785                 nBm1 = &Bm1;
+02786         }
+02787 
+02788         this->resize(Bm0._Width, Bm0._Height, RGBA);
+02789 
+02790         const  uint numPix = _Width * _Height; // 4 component per pixels
+02791 
+02792 
+02793         const uint8 *src0               = &(nBm0->_Data[0][0]);
+02794         const uint8 *src1               = &(nBm1->_Data[0][0]);
+02795         uint8 *dest                             = &(this->_Data[0][0]);
+02796         uint8 *endPix                   = dest + (numPix << 2);
+02797 
+02798 
+02799         uint blendFact    = (uint) factor;
+02800         uint invblendFact = 256 - blendFact;
+02801 
+02802         do
+02803         {
+02805                 *dest = (uint8) (((blendFact * *src1)           + (invblendFact * *src0)) >> 8);
+02806                 *(dest + 1) = (uint8) (((blendFact * *(src1 + 1)) + (invblendFact * *(src0 + 1))) >> 8);
+02807                 *(dest + 2) = (uint8) (((blendFact * *(src1 + 2)) + (invblendFact * *(src0 + 2))) >> 8);
+02808                 *(dest + 3)  = (uint8) (((blendFact * *(src1 + 3)) + (invblendFact * *(src0 + 3))) >> 8);
+02809 
+02810                 src0 = src0 + 4;
+02811                 src1 = src1 + 4;
+02812                 dest = dest + 4;        
+02813         }
+02814         while (dest != endPix);
+02815 }
+02816 
+02817 
+02818 
+02819 //-----------------------------------------------
+02820 CRGBA CBitmap::getRGBAPixel(sint x, sint y, uint32 numMipMap /*=0*/) const
+02821 {
+02822         uint w = getWidth(numMipMap);
+02823         uint h = getHeight(numMipMap);
+02824         if (w == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
+02825         const uint8 *pix = &getPixels(numMipMap)[(x + y * w) << 2];
+02826         return CRGBA(pix[0], pix[1], pix[2], pix[3]);
+02827 }
+02828 
+02829 //-----------------------------------------------
+02830 CRGBA CBitmap::getDXTCColorFromBlock(const uint8 *block, sint x, sint y)
+02831 {
+02832         uint16  col0;
+02833         uint16  col1;
+02834         memcpy(&col0, block, sizeof(uint16));
+02835         memcpy(&col1, block + 2, sizeof(uint16));
+02836         uint    colIndex = (block[4 + (y & 3)] >> ((x & 3) << 1)) & 3;
+02837         CRGBA   result, c0, c1;
+02838         if (col0 > col1)
+02839         {       
+02840                 switch(colIndex)
+02841                 {
+02842                         case 0:
+02843                                 uncompress(col0, result);                               
+02844                         break;
+02845                         case 1:
+02846                                 uncompress(col1, result);
+02847                         break;
+02848                         case 2:
+02849                                 uncompress(col0, c0);
+02850                                 uncompress(col1, c1);
+02851                                 result.blendFromui(c0, c1, 85);
+02852                         break;
+02853                         case 3:
+02854                                 uncompress(col0, c0);
+02855                                 uncompress(col1, c1);
+02856                                 result.blendFromui(c0, c1, 171);
+02857                         break;
+02858                 }
+02859                 result.A = 255;
+02860         }
+02861         else
+02862         {
+02863                 switch(colIndex)
+02864                 {
+02865                         case 0:
+02866                                 uncompress(col0, result);
+02867                                 result.A = 255;
+02868                         break;
+02869                         case 1:
+02870                                 uncompress(col1, result);
+02871                                 result.A = 255;
+02872                         break;
+02873                         case 2:
+02874                                 uncompress(col0, c0);
+02875                                 uncompress(col1, c1);
+02876                                 result.blendFromui(c0, c1, 128);
+02877                                 result.A = 255;
+02878                         break;
+02879                         case 3:
+02880                                 result.set(0, 0, 0, 0);                         
+02881                         break;
+02882                 }
+02883         }       
+02884         return result;
+02885 }
+02886 
+02887 //-----------------------------------------------
+02888 CRGBA CBitmap::getDXTC1Texel(sint x, sint y, uint32 numMipMap) const
+02889 {
+02890         uint w = getWidth(numMipMap);
+02891         uint h = getHeight(numMipMap);
+02892         if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases  
+02893         uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
+02894         const uint8 *pix    = &getPixels(numMipMap)[0];
+02895         const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 3) + ((x >> 2) << 3)); 
+02896         return getDXTCColorFromBlock(block, x, y);
+02897 }
+02898 
+02899 
+02900 //-----------------------------------------------
+02901 CRGBA CBitmap::getDXTC3Texel(sint x, sint y, uint32 numMipMap) const
+02902 {
+02903         uint w = getWidth(numMipMap);
+02904         uint h = getHeight(numMipMap);
+02905         if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases  
+02906         uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
+02907         const uint8 *pix    = &getPixels(numMipMap)[0];
+02908         const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 4) + ((x >> 2) << 4)); 
+02909         CRGBA result = getDXTCColorFromBlock(block + 8, x, y);
+02910         // get alpha part
+02911         uint8 alphaByte = block[((y & 3) << 1) + ((x & 2) >> 1)];
+02912         result.A = (x & 1) ?  (alphaByte & 0xf0) : (alphaByte << 4);
+02913         return result;
+02914 }
+02915 
+02916 //-----------------------------------------------
+02917 CRGBA CBitmap::getDXTC5Texel(sint x, sint y, uint32 numMipMap) const
+02918 {
+02919         uint w = getWidth(numMipMap);
+02920         uint h = getHeight(numMipMap);
+02921         if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases  
+02922         uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
+02923         const uint8 *pix    = &getPixels(numMipMap)[0];
+02924         const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 4) + ((x >> 2) << 4)); 
+02925         CRGBA result = getDXTCColorFromBlock(block + 8, x, y);
+02926         // get alpha part
+02927         uint8 alpha0 = block[0];
+02928         uint8 alpha1 = block[1];
+02929         
+02930         uint alphaIndex;
+02931         uint tripletIndex = (x & 3) + ((y & 3) << 2);
+02932         if (tripletIndex < 8)
+02933         {
+02934                 alphaIndex = (((uint32 &) block[2]) >> (tripletIndex * 3)) & 7;
+02935         }
+02936         else
+02937         {
+02938                 alphaIndex = (((uint32 &) block[5]) >> ((tripletIndex - 8) * 3)) & 7; // we can read a dword there because there are color datas following he alpha datas
+02939         }
+02940 
+02941         if (alpha0 > alpha1)
+02942         {
+02943                 switch (alphaIndex)
+02944                 {
+02945                         case 0: result.A = alpha0; break;
+02946                         case 1: result.A = alpha1; break;
+02947                         case 2: result.A = (uint8) ((6 * (uint) alpha0 + (uint) alpha1) / 7); break;
+02948                         case 3: result.A = (uint8) ((5 * (uint) alpha0 + 2 * (uint) alpha1) / 7); break;
+02949                         case 4: result.A = (uint8) ((4 * (uint) alpha0 + 3 * (uint) alpha1) / 7); break;
+02950                         case 5: result.A = (uint8) ((3 * (uint) alpha0 + 4 * (uint) alpha1) / 7); break;
+02951                         case 6: result.A = (uint8) ((2 * (uint) alpha0 + 5 * (uint) alpha1) / 7); break;
+02952                         case 7: result.A = (uint8) (((uint) alpha0 + (uint) 6 * alpha1) / 7); break;
+02953                 }
+02954         }
+02955         else
+02956         {
+02957                 switch (alphaIndex)
+02958                 {
+02959                         case 0: result.A = alpha0; break;
+02960                         case 1: result.A = alpha1; break;
+02961                         case 2: result.A = (uint8) ((4 * (uint) alpha0 + (uint) alpha1) / 5); break;
+02962                         case 3: result.A = (uint8) ((3 * (uint) alpha0 + 2 * (uint) alpha1) / 5); break;
+02963                         case 4: result.A = (uint8) ((2 * (uint) alpha0 + 3 * (uint) alpha1) / 5); break;
+02964                         case 5: result.A = (uint8) (((uint) alpha0 + 4 * (uint) alpha1) / 5); break;
+02965                         case 6: result.A = 0;   break;
+02966                         case 7: result.A = 255; break;
+02967                 }
+02968         }
+02969         return result;  
+02970 }
+02971 
+02972 
+02973 //-----------------------------------------------
+02974 CRGBA CBitmap::getPixelColor(sint x, sint y, uint32 numMipMap /*=0*/) const
+02975 {
+02976         
+02977         switch (PixelFormat)
+02978         {
+02979                 case RGBA:      
+02980                         return getRGBAPixel(x, y, numMipMap);           
+02981                 case DXTC1:
+02982                 case DXTC1Alpha: 
+02983                         return getDXTC1Texel(x, y, numMipMap);
+02984                 case DXTC3:
+02985                         return getDXTC3Texel(x, y, numMipMap);
+02986                 case DXTC5:
+02987                         return getDXTC5Texel(x, y, numMipMap);
+02988                 default:
+02989                         nlstop;
+02990                 break;
+02991         }
+02992         return CRGBA::Black;
+02993 }
+02994 
+02995 
+02996 } // NLMISC
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1