Back to index

nux  3.0.0
ImageSurface.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "NuxCore/NuxCore.h"
00024 #include "NuxCore/Logger.h"
00025 #include "NuxCore/Math/MathFunctions.h"
00026 
00027 #include "BitmapFormats.h"
00028 #include "GdkGraphics.h"
00029 
00030 #if defined(NUX_OS_WINDOWS)
00031   #include "GdiImageLoader.h"
00032   #include "DDS.h"
00033 #endif
00034 
00035 #include "ImageSurface.h"
00036 
00037 namespace nux
00038 {
00039 namespace
00040 {
00041 logging::Logger logger("nux.image");
00042 }
00043 
00044   extern PixelFormatInfo GPixelFormats[];
00045 
00046   NBitmapData *LoadGdkPixbuf(GdkPixbuf *pixbuf)
00047   {
00048     unsigned int width = gdk_pixbuf_get_width(pixbuf);
00049     unsigned int height = gdk_pixbuf_get_height(pixbuf);
00050     unsigned int row_bytes = gdk_pixbuf_get_rowstride(pixbuf);
00051 
00052     NTextureData *Texture = new NTextureData(BITFMT_R8G8B8A8, width, height, 1);
00053 
00054     guchar *img = gdk_pixbuf_get_pixels(pixbuf);
00055 
00056     for (unsigned int i = 0; i < width; i++)
00057       for (unsigned int j = 0; j < height; j++)
00058       {
00059         guchar *pixels = img + ( j * row_bytes + i * 4);
00060         UINT value =
00061           (* (pixels + 3) << 24) |  // a
00062           (* (pixels + 2) << 16) |  // b
00063           (* (pixels + 1) << 8)  |  // g
00064           * (pixels + 0);           // r
00065 
00066         Texture->GetSurface(0).Write32b(i, j, value);
00067       }
00068 
00069     return Texture;
00070   }
00071 
00072   NBitmapData *LoadImageFile(const TCHAR *filename)
00073   {
00074     if (!GFileManager.FileExist(filename))
00075     {
00076       nuxAssertMsg(0, "[LoadImageFile] Can't find file: %s", filename);
00077       return 0;
00078     }
00079 
00080     NBitmapData *BitmapData = 0;
00081 
00082 #if defined(NUX_OS_WINDOWS)
00083     BitmapData = GdiLoadImageFile(filename);
00084     if (BitmapData) return BitmapData;
00085 
00086     BitmapData = read_tga_file(filename);
00087     if (BitmapData) return BitmapData;
00088 
00089     BitmapData = LoadFileFormat_DDS(filename);
00090     if (BitmapData) return BitmapData;
00091 
00092 #elif defined(NUX_OS_LINUX)
00093     GdkGraphics gdkgraphics;
00094     gdkgraphics.LoadImage(filename);
00095     BitmapData = gdkgraphics.GetBitmap();
00096     if (BitmapData) return BitmapData;
00097 #endif
00098 
00099     // Unsupported format
00100     LOG_DEBUG(logger) << "Unknown file format: " << filename;
00101     return 0;
00102   }
00103 
00104   bool HasOpenEXRSupport()
00105   {
00106 #ifdef NUX_OPENEXR_SUPPORT
00107     return true;
00108 #else
00109     return false;
00110 #endif
00111   }
00112 
00113   void MakeCheckBoardImage(ImageSurface &Image,
00114                             int width, int height,
00115                             Color const& dark,
00116                             Color const& light,
00117                             int TileWidth,
00118                             int TileHeight)
00119   {
00120     Image.Allocate(BITFMT_R8G8B8A8, width, height);
00121 
00122     if (TileWidth <= 0)
00123       TileWidth = 4;
00124 
00125     if (TileHeight <= 0)
00126       TileHeight = 4;
00127 
00128     for (int j = 0; j < height; ++j)
00129     {
00130       for (int i = 0; i < width; ++i)
00131       {
00132         /*every 8 bits, change color from black to white or vice versa */
00133         bool even_column = ((i / TileWidth) % 2) == 0;
00134         bool even_row = ((j / TileHeight ) % 2) == 0;
00135         bool is_dark = even_column ^ even_row;
00136         Color const& c = is_dark ? dark : light;
00137         Image.Write(i, j,
00138                     c.red * 255,
00139                     c.green * 255,
00140                     c.blue * 255,
00141                     c.alpha * 255);
00142       }
00143     }
00144 
00145     Image.FlipVertical();
00146   }
00147 
00148 
00149   NBitmapData::NBitmapData()
00150     :   m_TotalMemorySize(0)
00151   {
00152 
00153   }
00154 
00155   NBitmapData::~NBitmapData()
00156   {
00157   }
00158 
00159 
00160   ImageSurface::ImageSurface()
00161     :   width_(0)
00162     ,   height_(0)
00163     ,   format_(BITFMT_UNKNOWN)
00164     ,   m_Pitch(0)
00165     ,   bpe_(0)
00166     ,   Alignment_(4)
00167     ,   RawData_(0)
00168   {
00169     Allocate(format_, width_, height_);
00170   }
00171 
00172   ImageSurface::~ImageSurface()
00173   {
00174     delete [] RawData_;
00175   }
00176 
00177   ImageSurface::ImageSurface(BitmapFormat format, unsigned int width, unsigned int height)
00178     :   width_(0)
00179     ,   height_(0)
00180     ,   format_(BITFMT_UNKNOWN)
00181     ,   m_Pitch(0)
00182     ,   bpe_(0)
00183     ,   Alignment_(4)
00184     ,   RawData_(0)
00185   {
00186     Allocate(format, width, height);
00187   }
00188 
00189   ImageSurface::ImageSurface(const ImageSurface &surface)
00190   {
00191     width_ = surface.width_;
00192     height_ = surface.height_;
00193     bpe_ = surface.bpe_;
00194     format_ = surface.format_;
00195     m_Pitch = surface.m_Pitch;
00196     Alignment_ = surface.Alignment_;
00197 
00198     RawData_ = new unsigned char[surface.GetSize()];
00199     Memcpy(RawData_, surface.RawData_, surface.GetSize());
00200   }
00201 
00202   ImageSurface &ImageSurface::operator = (const ImageSurface &surface)
00203   {
00204     if (this == &surface)
00205       return *this;   // Handle self assignment
00206 
00207     width_ = surface.width_;
00208     height_ = surface.height_;
00209     bpe_ = surface.bpe_;
00210     format_ = surface.format_;
00211     m_Pitch = surface.m_Pitch;
00212     Alignment_ = surface.Alignment_;
00213 
00214     delete [] RawData_;
00215 
00216     RawData_ = new unsigned char[surface.GetSize() ];
00217     Memcpy(RawData_, surface.RawData_, surface.GetSize());
00218     return *this;
00219   }
00220 
00221   int ImageSurface::GetPitch() const
00222   {
00223     return m_Pitch;
00224   }
00225 
00226   int ImageSurface::GetBlockHeight() const
00227   {
00228     unsigned int block = GPixelFormats[format_].BlockSizeY;
00229     unsigned int HeightInBlocks = Align(GetHeight(), block) / block;
00230     return HeightInBlocks;
00231   }
00232 
00233   BitmapFormat ImageSurface::GetFormat() const
00234   {
00235     return format_;
00236   }
00237 
00238   int ImageSurface::GetAlignment() const
00239   {
00240     return Alignment_;
00241   }
00242 
00243   void ImageSurface::Allocate(BitmapFormat format, int width, int height)
00244   {
00245     nuxAssert(format < BITFMT_END_GFX_FORMATS);
00246     nuxAssert(width >= 0);
00247     nuxAssert(height >= 0);
00248 
00249     if (width < 0)
00250       width = 0;
00251 
00252     if (height < 0)
00253       height = 0;
00254 
00255     if ((format_ == format) &&
00256          (width_ == width) &&
00257          (height_ == height))
00258     {
00259       // no need to recreate
00260       Clear();
00261       return;
00262     }
00263 
00264     delete [] RawData_;
00265 
00266     if ((width == 0) || (height == 0))
00267     {
00268       width_ = 0;
00269       height_ = 0;
00270       Alignment_ = 1;
00271       bpe_ = 0;
00272       format_ = BITFMT_UNKNOWN;
00273       m_Pitch = 0;
00274       return;
00275     }
00276 
00277     width_ = width;
00278     height_ = height;
00279 
00280 
00281     Alignment_ = GPixelFormats[format].RowMemoryAlignment;
00282 
00283     bpe_ = GPixelFormats[format].BlockBytes;
00284     format_ = format;
00285 
00286     if ((format_ == BITFMT_DXT1) ||
00287          (format_ == BITFMT_DXT2) ||
00288          (format_ == BITFMT_DXT3) ||
00289          (format_ == BITFMT_DXT4) ||
00290          (format_ == BITFMT_DXT5))
00291     {
00292       // For DXT, width and height are rounded up to a multiple of 4 in order
00293       // to create 4x4 blocks of pixels; And in this context, byte alignment
00294       // is 1 ie. data is densely packed.
00295       unsigned int block = GPixelFormats[format].BlockSizeX;
00296       unsigned int shift = Log2(GPixelFormats[format].BlockSizeX);
00297       m_Pitch = Align((bpe_ * ((width_ + (block - 1)) >> shift)), Alignment_);
00298 
00299       block = GPixelFormats[format].BlockSizeY;
00300       shift = Log2(GPixelFormats[format].BlockSizeY);
00301       RawData_ = new unsigned char[m_Pitch * Align((height + (block-1)) >> shift, block) ];
00302     }
00303     else
00304     {
00305       unsigned int block = GPixelFormats[format].BlockSizeX;
00306       unsigned int shift = Log2(GPixelFormats[format].BlockSizeX);
00307       m_Pitch = Align((bpe_ * ((width_ + (block - 1)) >> shift)),  Alignment_);
00308 
00309       block = GPixelFormats[format].BlockSizeY;
00310       shift = Log2(GPixelFormats[format].BlockSizeY);
00311       RawData_ = new unsigned char[m_Pitch * Align((height + (block-1)) >> shift, block) ];
00312     }
00313 
00314     Clear();
00315   }
00316 
00317 // This computes the correct pitch of a line. For instance if the unpack
00318 // alignment is 4, the pitch must have a number of pixel multiple of 4.  See
00319 // Avoiding 16 Common OpenGL Pitfalls
00320 // http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
00321 // 7. Watch Your Pixel Store Alignment
00322   int ImageSurface::GetLevelPitch(BitmapFormat format, int width,
00323                                      int height, int miplevel)
00324   {
00325     int levelwidth = ImageSurface::GetLevelDim(format, width, miplevel);
00326 
00327     int bpe = GPixelFormats[format].BlockBytes;
00328     int memalignment = GPixelFormats[format].RowMemoryAlignment;
00329     int block = GPixelFormats[format].BlockSizeX;
00330     int shift = Log2(GPixelFormats[format].BlockSizeX);
00331     int pitch = Align((bpe * ((levelwidth + (block - 1)) >> shift)), memalignment);
00332 
00333     return pitch;
00334   }
00335 
00336   int ImageSurface::GetLevelPitchNoMemAlignment(BitmapFormat format, int width, int height, int miplevel)
00337   {
00338     int levelwidth = ImageSurface::GetLevelDim(format, width, miplevel);
00339 
00340     int bpe = GPixelFormats[format].BlockBytes;
00341     int block = GPixelFormats[format].BlockSizeX;
00342     int shift = Log2(GPixelFormats[format].BlockSizeX);
00343     int pitch = Align((bpe * ((levelwidth + (block - 1)) >> shift)), 1);
00344 
00345     return pitch;
00346   }
00347 
00348   int ImageSurface::GetLevelSize(BitmapFormat format, int width, int height, int miplevel)
00349   {
00350     int pitch = ImageSurface::GetLevelPitch(format, width, height, miplevel);
00351     int levelheight = ImageSurface::GetLevelDim(format, height, miplevel);
00352 
00353     int block = GPixelFormats[format].BlockSizeY;
00354     int HeightInBlocks = Align(levelheight, block) / block;
00355 
00356     int size = pitch * HeightInBlocks;
00357     return size;
00358   }
00359 
00360   int ImageSurface::GetLevelSize(BitmapFormat format, int width, int height, int depth, int miplevel)
00361   {
00362     int pitch = ImageSurface::GetLevelPitch(format, width, height, miplevel);
00363     int levelheight = ImageSurface::GetLevelDim(format, height, miplevel);
00364     int leveldepth = ImageSurface::GetLevelDim(format, depth, miplevel);
00365 
00366     int block = GPixelFormats[format].BlockSizeY;
00367     int HeightInBlocks = Align(levelheight, block) / block;
00368 
00369     int size = pitch * HeightInBlocks;
00370     return leveldepth * size;
00371   }
00372 
00373   int ImageSurface::GetLevelWidth(BitmapFormat format, int width, int miplevel)
00374   {
00375     // return 1 if the mip level does not exist.
00376     return Max<int> (1, width >> miplevel);
00377   }
00378 
00379   int ImageSurface::GetLevelHeight(BitmapFormat format, int height, int miplevel)
00380   {
00381     // return 1 if the mip level does not exist.
00382     return Max<int> (1, height >> miplevel);
00383   }
00384 
00385   int ImageSurface::GetLevelDim(BitmapFormat format, int length, int miplevel)
00386   {
00387     // return 1 if the mip level does not exist.
00388     return Max<int> (1, length >> miplevel);
00389   }
00390 
00391   int ImageSurface::GetNumMipLevel(BitmapFormat format, int width, int height)
00392   {
00393     int NumTotalMipLevel    = 1 + floorf(Log2(Max(width, height)));
00394     return NumTotalMipLevel;
00395   }
00396 
00397   int ImageSurface::GetMemAlignment(BitmapFormat format)
00398   {
00399     return GPixelFormats[format].RowMemoryAlignment;
00400   }
00401 
00402   int ImageSurface::GetLevelBlockWidth(BitmapFormat format, int width, int miplevel)
00403   {
00404     int block = GPixelFormats[format].BlockSizeX;
00405     int WidthInBlocks = Align(GetLevelDim(format, width, miplevel), block) / block;
00406     return WidthInBlocks;
00407   }
00408 
00409   int ImageSurface::GetLevelBlockHeight(BitmapFormat format, int height, int miplevel)
00410   {
00411     int block = GPixelFormats[format].BlockSizeY;
00412     int HeightInBlocks = Align(GetLevelDim(format, height, miplevel), block) / block;
00413     return HeightInBlocks;
00414   }
00415 
00416   bool ImageSurface::IsNull() const
00417   {
00418     if ((width_ == 0) || (height_ == 0) || (format_ == BITFMT_UNKNOWN))
00419       return true;
00420 
00421     return false;
00422   }
00423 
00424   void ImageSurface::Write32b(int i, int j, unsigned int value)
00425   {
00426     nuxAssert(i < width_);
00427     nuxAssert(j < height_);
00428     nuxAssert(bpe_ >= 4);
00429 
00430     if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2)  || (format_ == BITFMT_DXT3)  || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5))
00431       return;
00432 
00433     RawData_[j *m_Pitch + i *bpe_ + 0] = (unsigned char) (value & 0xff);
00434     RawData_[j *m_Pitch + i *bpe_ + 1] = (unsigned char) ((value & 0xff00) >> 8);
00435     RawData_[j *m_Pitch + i *bpe_ + 2] = (unsigned char) ((value & 0xff0000) >> 16);
00436     RawData_[j *m_Pitch + i *bpe_ + 3] = (unsigned char) ((value & 0xff000000) >> 24);
00437   }
00438 
00439   void ImageSurface::Write24b(int i, int j, unsigned int value)
00440   {
00441     nuxAssert(i < width_);
00442     nuxAssert(j < height_);
00443     nuxAssert(bpe_ >= 3);
00444 
00445     if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2)  || (format_ == BITFMT_DXT3)  || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5))
00446       return;
00447 
00448     RawData_[j *m_Pitch + i *bpe_ + 0] = (unsigned char) (value & 0xff);
00449     RawData_[j *m_Pitch + i *bpe_ + 1] = (unsigned char) ((value & 0xff00) >> 8);
00450     RawData_[j *m_Pitch + i *bpe_ + 2] = (unsigned char) ((value & 0xff0000) >> 16);
00451   }
00452 
00453   void ImageSurface::Write16b(int i, int j, unsigned short value)
00454   {
00455     nuxAssert(i < width_);
00456     nuxAssert(j < height_);
00457     nuxAssert(bpe_ >= 2);
00458 
00459     if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2)  || (format_ == BITFMT_DXT3)  || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5))
00460       return;
00461 
00462     RawData_[j *m_Pitch + i *bpe_ + 0] = (unsigned char) (value & 0xff);
00463     RawData_[j *m_Pitch + i *bpe_ + 1] = (unsigned char) ((value & 0xff00) >> 8);
00464   }
00465 
00466   void ImageSurface::Write8b(int i, int j, unsigned char value)
00467   {
00468     nuxAssert(i < width_);
00469     nuxAssert(j < height_);
00470     nuxAssert(bpe_ >= 1);
00471 
00472     if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2)  || (format_ == BITFMT_DXT3)  || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5))
00473       return;
00474 
00475     RawData_[j *m_Pitch + i *bpe_ + 0] = (unsigned char) (value & 0xff);
00476   }
00477 
00478   void ImageSurface::Write(int i, int j, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
00479   {
00480     nuxAssert(i < width_);
00481     nuxAssert(j < height_);
00482     nuxAssert(bpe_ == 4);
00483 
00484     if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2)  || (format_ == BITFMT_DXT3)  || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5))
00485       return;
00486 
00487     if ((i < 0) || (i > width_))
00488       return;
00489 
00490     if ((j < 0) || (j > height_))
00491       return;
00492 
00493     if (bpe_ != 4)
00494       return;
00495 
00496     RawData_[j *m_Pitch + i *bpe_ + 0] = r;
00497     RawData_[j *m_Pitch + i *bpe_ + 1] = g;
00498     RawData_[j *m_Pitch + i *bpe_ + 2] = b;
00499     RawData_[j *m_Pitch + i *bpe_ + 3] = a;
00500   }
00501 
00502   unsigned int ImageSurface::Read(int i, int j)
00503   {
00504     nuxAssert(i < width_);
00505     nuxAssert(j < height_);
00506     nuxAssert(bpe_);
00507 
00508     if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2)  || (format_ == BITFMT_DXT3)  || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5))
00509       return 0x00000000;
00510 
00511     if (bpe_ == 4)
00512     {
00513       return  ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 3] << 24)   |
00514               ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 2] << 16)   |
00515               ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 1] << 8)    |
00516               ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 0] << 0);
00517     }
00518 
00519     if (bpe_ == 3)
00520     {
00521       return  ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 2] << 16)   |
00522               ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 1] << 8)    |
00523               ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 0] << 0);
00524     }
00525 
00526     if (bpe_ == 2)
00527     {
00528       return  ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 1] << 8)    |
00529               ((unsigned int) RawData_[j * m_Pitch + i * bpe_ + 0] << 0);
00530     }
00531 
00532     if (bpe_ == 1)
00533     {
00534       return  (unsigned int) RawData_[j * m_Pitch + i * bpe_ + 0];
00535     }
00536 
00537     return 0x0000000;
00538   }
00539 
00540   void ImageSurface::Clear()
00541   {
00542     if (RawData_ == 0)
00543       return;
00544 
00545     if ((width_ == 0) || (height_ == 0))
00546       return;
00547 
00548     auto size = GetSize();
00549     memset(RawData_, 0, size);
00550   }
00551 
00552   void ImageSurface::FlipHorizontal()
00553   {
00554     if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2)  || (format_ == BITFMT_DXT3)  || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5))
00555       return;
00556 
00557     int i, j, k;
00558     unsigned char *flip_data;
00559 
00560     if (RawData_ == 0)
00561       return;
00562 
00563     if (width_ == 0 || height_ == 0)
00564       return;
00565 
00566     flip_data =  new unsigned char[m_Pitch*height_];
00567 
00568     for (j = 0; j < height_; j++)
00569     {
00570       for (i = 0; i < width_; i++)
00571       {
00572         for (k = 0; k < bpe_; k++)
00573         {
00574           flip_data[ (j*m_Pitch) + i *bpe_ + k] = RawData_[ (j*m_Pitch) + (width_-i-1) * bpe_ + k];
00575         }
00576       }
00577     }
00578 
00579     delete [] RawData_;
00580     RawData_ = flip_data;
00581   }
00582 
00583   void ImageSurface::FlipVertical()
00584   {
00585 
00586     int i, j, k;
00587     unsigned char *flip_data;
00588 
00589     if (RawData_ == 0)
00590       return;
00591 
00592     if (width_ == 0 || height_ == 0)
00593       return;
00594 
00595     if ((format_ == BITFMT_DXT1) || (format_ == BITFMT_DXT2) || (format_ == BITFMT_DXT3) || (format_ == BITFMT_DXT4) || (format_ == BITFMT_DXT5))
00596     {
00597       FlipDXTVertical();
00598     }
00599     else
00600     {
00601       flip_data =  new unsigned char[m_Pitch*height_];
00602 
00603       for (j = 0; j < height_; j++)
00604       {
00605         for (i = 0; i < width_; i++)
00606         {
00607           for (k = 0; k < bpe_; k++)
00608           {
00609             flip_data[ (j*m_Pitch) + i *bpe_ + k] = RawData_[ (height_-j-1) *m_Pitch + i * bpe_ + k];
00610           }
00611         }
00612       }
00613 
00614       delete [] RawData_;
00615       RawData_ = flip_data;
00616     }
00617 
00618   }
00619 
00620   void ImageSurface::FlipDXTVertical()
00621   {
00622     //void(CDDSImage::*flipblocks)(DXTColBlock*, unsigned int);
00623     int xblocks = (width_ + 3) / 4;
00624     int yblocks = (height_ + 3) / 4;
00625     int blocksize;
00626     int linesize;
00627 
00628     switch(format_)
00629     {
00630       case BITFMT_DXT1:
00631         blocksize = 8;
00632         //flipblocks = &CDDSImage::flip_blocks_dxtc1;
00633         break;
00634       case BITFMT_DXT2:
00635         blocksize = 16;
00636         //flipblocks = &CDDSImage::flip_blocks_dxtc2;
00637         break;
00638       case BITFMT_DXT3:
00639         blocksize = 16;
00640         //flipblocks = &CDDSImage::flip_blocks_dxtc3;
00641         break;
00642       case BITFMT_DXT4:
00643         blocksize = 16;
00644         //flipblocks = &CDDSImage::flip_blocks_dxtc4;
00645         break;
00646       case BITFMT_DXT5:
00647         blocksize = 16;
00648         //flipblocks = &CDDSImage::flip_blocks_dxtc5;
00649         break;
00650       default:
00651         return;
00652     }
00653 
00654     linesize = xblocks * blocksize;
00655 
00656     DXTColBlock *top;
00657     DXTColBlock *bottom;
00658 
00659     for (int j = 0; j < (yblocks >> 1); j++)
00660     {
00661       top = (DXTColBlock *) ((unsigned char *) RawData_ + j * linesize);
00662       bottom = (DXTColBlock *) ((unsigned char *) RawData_ + (((yblocks - j) - 1) * linesize));
00663 
00664       switch(format_)
00665       {
00666         case BITFMT_DXT1:
00667           FlipBlocksDXT1(top, xblocks);
00668           FlipBlocksDXT1(bottom, xblocks);
00669           break;
00670         case BITFMT_DXT2:
00671           FlipBlocksDXT3(top, xblocks);
00672           FlipBlocksDXT3(bottom, xblocks);
00673           break;
00674         case BITFMT_DXT3:
00675           FlipBlocksDXT3(top, xblocks);
00676           FlipBlocksDXT3(bottom, xblocks);
00677           break;
00678         case BITFMT_DXT4:
00679           FlipBlocksDXT5(top, xblocks);
00680           FlipBlocksDXT5(bottom, xblocks);
00681           break;
00682         case BITFMT_DXT5:
00683           FlipBlocksDXT5(top, xblocks);
00684           FlipBlocksDXT5(bottom, xblocks);
00685           break;
00686         default:
00687           nuxAssert("[ImageSurface::FlipDXTVertical] Invalid Switch option.");
00688           break;
00689       }
00690 
00691       SwapBlocks(bottom, top, linesize);
00692     }
00693   }
00694 
00695   void ImageSurface::SwapBlocks(void *byte1, void *byte2, int size)
00696   {
00697     unsigned char *tmp = new unsigned char[size];
00698 
00699     memcpy(tmp, byte1, size);
00700     memcpy(byte1, byte2, size);
00701     memcpy(byte2, tmp, size);
00702 
00703     delete [] tmp;
00704   }
00705 
00706   void ImageSurface::FlipBlocksDXT1(DXTColBlock *line, int numBlocks)
00707   {
00708     DXTColBlock *curblock = line;
00709 
00710     for (int i = 0; i < numBlocks; i++)
00711     {
00712       SwapBlocks(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
00713       SwapBlocks(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
00714 
00715       curblock++;
00716     }
00717   }
00718 
00719   void ImageSurface::FlipBlocksDXT3(DXTColBlock *line, int numBlocks)
00720   {
00721     DXTColBlock *curblock = line;
00722     DXT3AlphaBlock *alphablock;
00723 
00724     for (int i = 0; i < numBlocks; i++)
00725     {
00726       alphablock = (DXT3AlphaBlock *) curblock;
00727 
00728       SwapBlocks(&alphablock->row[0], &alphablock->row[3], sizeof(unsigned short));
00729       SwapBlocks(&alphablock->row[1], &alphablock->row[2], sizeof(unsigned short));
00730 
00731       curblock++;
00732 
00733       SwapBlocks(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
00734       SwapBlocks(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
00735 
00736       curblock++;
00737     }
00738   }
00739 
00740   void ImageSurface::FlipBlocksDXT5(DXTColBlock *line, int numBlocks)
00741   {
00742     DXTColBlock *curblock = line;
00743     DXT5AlphaBlock *alphablock;
00744 
00745     for (int i = 0; i < numBlocks; i++)
00746     {
00747       alphablock = (DXT5AlphaBlock *) curblock;
00748 
00749       FlipDXT5Alpha(alphablock);
00750 
00751       curblock++;
00752 
00753       SwapBlocks(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
00754       SwapBlocks(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
00755 
00756       curblock++;
00757     }
00758   }
00759 
00760   void ImageSurface::FlipDXT5Alpha(DXT5AlphaBlock *block)
00761   {
00762     unsigned char gBits[4][4];
00763 
00764     const unsigned long mask = 0x00000007;          // bits = 00 00 01 11
00765     unsigned long bits = 0;
00766     memcpy(&bits, &block->row[0], sizeof(unsigned char) * 3);
00767 
00768     gBits[0][0] = (unsigned char) (bits & mask);
00769     bits >>= 3;
00770     gBits[0][1] = (unsigned char) (bits & mask);
00771     bits >>= 3;
00772     gBits[0][2] = (unsigned char) (bits & mask);
00773     bits >>= 3;
00774     gBits[0][3] = (unsigned char) (bits & mask);
00775     bits >>= 3;
00776     gBits[1][0] = (unsigned char) (bits & mask);
00777     bits >>= 3;
00778     gBits[1][1] = (unsigned char) (bits & mask);
00779     bits >>= 3;
00780     gBits[1][2] = (unsigned char) (bits & mask);
00781     bits >>= 3;
00782     gBits[1][3] = (unsigned char) (bits & mask);
00783 
00784     bits = 0;
00785     memcpy(&bits, &block->row[3], sizeof(unsigned char) * 3);
00786 
00787     gBits[2][0] = (unsigned char) (bits & mask);
00788     bits >>= 3;
00789     gBits[2][1] = (unsigned char) (bits & mask);
00790     bits >>= 3;
00791     gBits[2][2] = (unsigned char) (bits & mask);
00792     bits >>= 3;
00793     gBits[2][3] = (unsigned char) (bits & mask);
00794     bits >>= 3;
00795     gBits[3][0] = (unsigned char) (bits & mask);
00796     bits >>= 3;
00797     gBits[3][1] = (unsigned char) (bits & mask);
00798     bits >>= 3;
00799     gBits[3][2] = (unsigned char) (bits & mask);
00800     bits >>= 3;
00801     gBits[3][3] = (unsigned char) (bits & mask);
00802 
00803     unsigned long *pBits = ((unsigned long *) & (block->row[0]));
00804 
00805     *pBits = *pBits | (gBits[3][0] << 0);
00806     *pBits = *pBits | (gBits[3][1] << 3);
00807     *pBits = *pBits | (gBits[3][2] << 6);
00808     *pBits = *pBits | (gBits[3][3] << 9);
00809 
00810     *pBits = *pBits | (gBits[2][0] << 12);
00811     *pBits = *pBits | (gBits[2][1] << 15);
00812     *pBits = *pBits | (gBits[2][2] << 18);
00813     *pBits = *pBits | (gBits[2][3] << 21);
00814 
00815     pBits = ((unsigned long *) & (block->row[3]));
00816 
00817 #ifdef __APPLE__
00818     *pBits &= 0x000000ff;
00819 #else
00820     *pBits &= 0xff000000;
00821 #endif
00822 
00823     *pBits = *pBits | (gBits[1][0] << 0);
00824     *pBits = *pBits | (gBits[1][1] << 3);
00825     *pBits = *pBits | (gBits[1][2] << 6);
00826     *pBits = *pBits | (gBits[1][3] << 9);
00827 
00828     *pBits = *pBits | (gBits[0][0] << 12);
00829     *pBits = *pBits | (gBits[0][1] << 15);
00830     *pBits = *pBits | (gBits[0][2] << 18);
00831     *pBits = *pBits | (gBits[0][3] << 21);
00832   }
00833 
00834   const unsigned char *ImageSurface::GetPtrRawData() const
00835   {
00836     return RawData_;
00837   }
00838 
00839   unsigned char *ImageSurface::GetPtrRawData()
00840   {
00841     return RawData_;
00842   }
00843 
00844   int ImageSurface::GetSize() const
00845   {
00846     if ((format_ == BITFMT_DXT1) ||
00847          (format_ == BITFMT_DXT2) ||
00848          (format_ == BITFMT_DXT3) ||
00849          (format_ == BITFMT_DXT4) ||
00850          (format_ == BITFMT_DXT5))
00851     {
00852       return m_Pitch * ((height_ + 3) >> 2);
00853     }
00854     else
00855     {
00856       return m_Pitch * height_;
00857     }
00858   }
00859 
00860   Color ImageSurface::AverageColor()
00861   {
00862     if (width_ == 0 || height_ == 0)
00863       return Color(0.f, 0.f, 0.f, 0.f);
00864 
00865     float r, g, b, a;
00866     r = g = b = a = 0;
00867 
00868     if (bpe_ == 8)
00869     {
00870       for (int j = 0; j < height_; j++)
00871       {
00872         for (int i = 0; i < width_; i++)
00873         {
00874           unsigned int v = Read(i, j);
00875           r += (v & 0x000000FF);
00876           g += (v & 0x0000FF00) >> 1;
00877           b += (v & 0x00FF0000) >> 2;
00878           a += (v & 0xFF000000) >> 3;
00879         }
00880       }
00881     }
00882 
00883     unsigned int num_pixels = width_ * height_;
00884     return Color(r / num_pixels, g / num_pixels, b / num_pixels, a / num_pixels);
00885   }
00886 
00887 
00889   NTextureData::NTextureData(BitmapFormat f, int width, int height, int NumMipmap)
00890     :   m_NumMipmap(0)
00891   {
00892     Allocate(f, width, height, NumMipmap);
00893   }
00894 
00895   NTextureData::~NTextureData()
00896   {
00897     ClearData();
00898   }
00899 
00900   void NTextureData::ClearData()
00901   {
00902     for (int i = 0; i < (int) m_MipSurfaceArray.size(); i++)
00903       delete m_MipSurfaceArray[i];
00904 
00905     m_MipSurfaceArray.clear();
00906   }
00907 
00909   NTextureData::NTextureData(const NTextureData &object)
00910   {
00911     for (int i = 0; i < object.GetNumMipmap(); i++)
00912       m_MipSurfaceArray.push_back(new ImageSurface(object.GetSurface(i)));
00913   }
00914 
00916   NTextureData &NTextureData::operator = (const NTextureData &copy)
00917   {
00918     ClearData();
00919     m_NumMipmap = copy.m_NumMipmap;
00920     m_TotalMemorySize = copy.m_TotalMemorySize;
00921 
00922     for (int i = 0; i < copy.GetNumMipmap(); i++)
00923       m_MipSurfaceArray.push_back(new ImageSurface(copy.GetSurface(i)));
00924 
00925     return *this;
00926   }
00927 
00928   void NTextureData::Allocate(BitmapFormat format, int width, int height, int NumMipmapRequested)
00929   {
00930     nuxAssertMsg(width >= 0, "[NTextureData::Allocate] Error: Negative texture width.");
00931     nuxAssertMsg(height >= 0, "[NTextureData::Allocate] Error: Negative texture height.");
00932     nuxAssert(NumMipmapRequested >= 0);
00933 
00934     int NumTotalMipLevel    = 1 + (int) Floor(Log2(Max(width, height)));
00935     m_NumMipmap = NumMipmapRequested;
00936 
00937     if (NumMipmapRequested == 0)
00938       m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1;
00939 
00940     if (NumMipmapRequested > NumTotalMipLevel)
00941       m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1;
00942 
00943     m_TotalMemorySize = 0;
00944     ClearData();
00945 
00946     for (int i = 0; i < m_NumMipmap; i++)
00947     {
00948       int w = width >> i;
00949       int h = height >> i;
00950       m_MipSurfaceArray.push_back(new ImageSurface(format, w, h));
00951       m_TotalMemorySize += m_MipSurfaceArray[i]->GetSize();
00952     }
00953   }
00954 
00955   void NTextureData::AllocateCheckBoardTexture(int width, int height, int NumMipmap, Color color0, Color color1, int TileWidth, int TileHeight)
00956   {
00957     Allocate(BITFMT_R8G8B8A8, width, height, NumMipmap);
00958 
00959     for (int i = 0; i < m_NumMipmap; i++)
00960     {
00961       int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), i);
00962       int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), i);
00963       MakeCheckBoardImage(*m_MipSurfaceArray[i], w, h, color0, color1, TileWidth, TileHeight);
00964     }
00965   }
00966 
00967   void NTextureData::AllocateColorTexture(int width, int height, int NumMipmap, Color color0)
00968   {
00969     Allocate(BITFMT_R8G8B8A8, width, height, NumMipmap);
00970 
00971     for (int i = 0; i < m_NumMipmap; i++)
00972     {
00973       int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), i);
00974       int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), i);
00975       MakeCheckBoardImage(*m_MipSurfaceArray[i], w, h, color0, color0);
00976     }
00977   }
00978 
00979   int NTextureData::GetNumMipmap() const
00980   {
00981     return m_MipSurfaceArray.size();
00982   }
00983 
00984   bool NTextureData::SetSurface(int MipLevel, const ImageSurface &targetsurface)
00985   {
00986     nuxAssert(MipLevel >= 0);
00987     nuxAssert(MipLevel < m_NumMipmap);
00988 
00989     ImageSurface &surface = GetSurface(MipLevel);
00990 
00991     if (surface.GetFormat() != targetsurface.GetFormat())
00992       return false;
00993 
00994     if (surface.GetWidth() != targetsurface.GetWidth())
00995       return false;
00996 
00997     if (surface.GetHeight() != targetsurface.GetHeight())
00998       return false;
00999 
01000     surface = targetsurface;
01001     return true;
01002   }
01003 
01005   NCubemapData::NCubemapData(BitmapFormat format, int width, int height, int NumMipmap)
01006     :   m_NumMipmap(0)
01007   {
01008     Allocate(format, width, height, NumMipmap);
01009   }
01010 
01011   NCubemapData::~NCubemapData()
01012   {
01013     ClearData();
01014   }
01015 
01016   void NCubemapData::ClearData()
01017   {
01018     int n = (int) m_MipSurfaceArray[0].size();
01019 
01020     for (int i = 0; i < n; i++)
01021     {
01022       delete m_MipSurfaceArray[0][i];
01023       delete m_MipSurfaceArray[1][i];
01024       delete m_MipSurfaceArray[2][i];
01025       delete m_MipSurfaceArray[3][i];
01026       delete m_MipSurfaceArray[4][i];
01027       delete m_MipSurfaceArray[5][i];
01028     }
01029 
01030     m_MipSurfaceArray[0].clear();
01031     m_MipSurfaceArray[1].clear();
01032     m_MipSurfaceArray[2].clear();
01033     m_MipSurfaceArray[3].clear();
01034     m_MipSurfaceArray[4].clear();
01035     m_MipSurfaceArray[5].clear();
01036   }
01037 
01039   NCubemapData::NCubemapData(const NCubemapData &object)
01040   {
01041     for (int face = 0; face < 6; face++)
01042       for (int i = 0; i < object.GetNumMipmap(); i++)
01043         m_MipSurfaceArray[face].push_back(new ImageSurface(object.GetSurface(face, i)));
01044   }
01045 
01047   NCubemapData &NCubemapData::operator = (const NCubemapData &copy)
01048   {
01049     ClearData();
01050     m_NumMipmap = copy.m_NumMipmap;
01051     m_TotalMemorySize = copy.m_TotalMemorySize;
01052 
01053     for (int face = 0; face < 6; face++)
01054       for (int i = 0; i < copy.GetNumMipmap(); i++)
01055         m_MipSurfaceArray[face].push_back(new ImageSurface(copy.GetSurface(face, i)));
01056 
01057     return *this;
01058   }
01059 
01060   void NCubemapData::Allocate(BitmapFormat format, int width, int height, int NumMipmapRequested)
01061   {
01062     nuxAssertMsg(width >= 0, "[NCubemapData::Allocate] Error: Negative texture width.");
01063     nuxAssertMsg(height >= 0, "[NCubemapData::Allocate] Error: Negative texture height.");
01064     nuxAssert(NumMipmapRequested >= 0);
01065 
01066     ClearData();
01067 
01068     int NumTotalMipLevel    = 1 + (int) Floor(Log2(Max(width, height)));
01069     m_NumMipmap = NumMipmapRequested;
01070 
01071     if (NumMipmapRequested == 0)
01072       m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1;
01073 
01074     if (NumMipmapRequested > NumTotalMipLevel)
01075       m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1;
01076 
01077     m_TotalMemorySize = 0;
01078 
01079     for (int face = 0; face < 6; face++)
01080     {
01081       for (int i = 0; i < m_NumMipmap; i++)
01082       {
01083         int w = width >> i;
01084         int h = height >> i;
01085         m_MipSurfaceArray[face].push_back(new ImageSurface(format, w, h));
01086         m_TotalMemorySize += m_MipSurfaceArray[face][i]->GetSize();
01087       }
01088     }
01089   }
01090 
01091   void NCubemapData::AllocateCheckBoardTexture(int width, int height, int NumMipmap, Color color0, Color color1, int TileWidth, int TileHeight)
01092   {
01093     Allocate(BITFMT_R8G8B8A8, width, height, NumMipmap);
01094 
01095     for (int face = 0; face < 6; face++)
01096     {
01097       for (int i = 0; i < m_NumMipmap; i++)
01098       {
01099         int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), i);
01100         int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), i);
01101         MakeCheckBoardImage(*m_MipSurfaceArray[face][i], w, h, color0, color1, TileWidth, TileHeight);
01102       }
01103     }
01104   }
01105 
01106   void NCubemapData::AllocateColorTexture(int width, int height, int NumMipmap, Color color0)
01107   {
01108     Allocate(BITFMT_R8G8B8A8, width, height, NumMipmap);
01109 
01110     for (int face = 0; face < 6; face++)
01111     {
01112       for (int i = 0; i < m_NumMipmap; i++)
01113       {
01114         int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), i);
01115         int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), i);
01116         MakeCheckBoardImage(*m_MipSurfaceArray[face][i], w, h, color0, color0);
01117       }
01118     }
01119   }
01120 
01121   int NCubemapData::GetNumMipmap() const
01122   {
01123     return m_MipSurfaceArray[0].size();
01124   }
01125 
01126   bool NCubemapData::SetSurface(int face, int MipLevel, const ImageSurface &targetsurface)
01127   {
01128     nuxAssert(face >= 0);
01129     nuxAssert(face < 6);
01130     nuxAssert(MipLevel >= 0);
01131     nuxAssert(MipLevel < m_NumMipmap);
01132 
01133     ImageSurface &surface = GetSurface(face, MipLevel);
01134 
01135     if (surface.GetFormat() != targetsurface.GetFormat())
01136       return false;
01137 
01138     if (surface.GetWidth() != targetsurface.GetWidth())
01139       return false;
01140 
01141     if (surface.GetHeight() != targetsurface.GetHeight())
01142       return false;
01143 
01144     surface = targetsurface;
01145     return true;
01146   }
01147 
01149   NVolumeData::NVolumeData(BitmapFormat format, int width, int height, int depth, int NumMipmap)
01150     :   m_NumMipmap(0)
01151     ,   m_Depth(0)
01152     ,   m_MipSurfaceArray(0)
01153   {
01154     Allocate(format, width, height, depth, NumMipmap);
01155   }
01156 
01157   NVolumeData::~NVolumeData()
01158   {
01159     ClearData();
01160   }
01161 
01162   void NVolumeData::ClearData()
01163   {
01164     for (int mip = 0; mip < GetNumMipmap(); mip++)
01165     {
01166       for (int s = 0; s < ImageSurface::GetLevelDim(GetFormat(), GetDepth(), mip); s++)
01167       {
01168         delete m_MipSurfaceArray[mip][s];
01169       }
01170 
01171       m_MipSurfaceArray[mip].clear();
01172     }
01173 
01174     delete [] m_MipSurfaceArray;
01175   }
01176 
01178   NVolumeData::NVolumeData(const NVolumeData &object)
01179   {
01180     for (int mip = 0; mip < object.GetNumMipmap(); mip++)
01181     {
01182       for (int s = 0; s < ImageSurface::GetLevelDim(object.GetFormat(), object.GetDepth(), mip); s++)
01183       {
01184         m_MipSurfaceArray[mip].push_back(new ImageSurface(object.GetSurface(mip, s)));
01185       }
01186     }
01187   }
01188 
01190   NVolumeData &NVolumeData::operator = (const NVolumeData &copy)
01191   {
01192     ClearData();
01193     m_Depth = copy.m_Depth;
01194     m_NumMipmap = copy.m_NumMipmap;
01195     m_TotalMemorySize = copy.m_TotalMemorySize;
01196 
01197     m_MipSurfaceArray = new std::vector<ImageSurface *>[m_NumMipmap];
01198 
01199     for (int mip = 0; mip < copy.GetNumMipmap(); mip++)
01200     {
01201       for (int s = 0; s < ImageSurface::GetLevelDim(copy.GetFormat(), copy.GetDepth(), mip); s++)
01202       {
01203         m_MipSurfaceArray[mip].push_back(new ImageSurface(copy.GetSurface(mip, s)));
01204       }
01205     }
01206 
01207     return *this;
01208   }
01209 
01210   void NVolumeData::Allocate(BitmapFormat format, int width, int height, int depth, int NumMipmapRequested)
01211   {
01212     nuxAssertMsg(depth >= 0, "[NVolumeData::Allocate] Error: Negative number of slice.");
01213     nuxAssertMsg(width >= 0, "[NVolumeData::Allocate] Error: Negative texture width.");
01214     nuxAssertMsg(height >= 0, "[NVolumeData::Allocate] Error: Negative texture height.");
01215     nuxAssert(NumMipmapRequested >= 0);
01216 
01217     ClearData();
01218 
01219     int NumTotalMipLevel    = 1 + (int) Floor(Log2(Max(width, height)));
01220     m_NumMipmap = NumMipmapRequested;
01221 
01222     if (NumMipmapRequested == 0)
01223       m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1;
01224 
01225     if (NumMipmapRequested > NumTotalMipLevel)
01226       m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1;
01227 
01228     m_Depth = depth;
01229 
01230     m_MipSurfaceArray = new std::vector<ImageSurface *>[m_NumMipmap];
01231     m_TotalMemorySize = 0;
01232 
01233     for (int mip = 0; mip < m_NumMipmap; mip++)
01234     {
01235       for (int s = 0; s < ImageSurface::GetLevelDim(format, depth, mip); s++)
01236       {
01237         int w = ImageSurface::GetLevelDim(format, width, mip);
01238         int h = ImageSurface::GetLevelDim(format, height, mip);
01239         m_MipSurfaceArray[mip].push_back(new ImageSurface(format, w, h));
01240         m_TotalMemorySize += m_MipSurfaceArray[mip][s]->GetSize();
01241       }
01242     }
01243   }
01244 
01245   void NVolumeData::AllocateCheckBoardTexture(int width, int height, int slice, int NumMipmap, Color color0, Color color1, int TileWidth, int TileHeight)
01246   {
01247     Allocate(BITFMT_R8G8B8A8, width, height, slice, NumMipmap);
01248 
01249     for (int mip = 0; mip < m_NumMipmap; mip++)
01250     {
01251       for (int s = 0; s < ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetDepth(), mip); s++)
01252       {
01253         int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), mip);
01254         int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), mip);
01255         MakeCheckBoardImage(* (m_MipSurfaceArray[mip][s]), w, h, color0, color1, TileWidth, TileHeight);
01256       }
01257     }
01258   }
01259 
01260   void NVolumeData::AllocateColorTexture(int width, int height, int slice, int NumMipmap, Color color0)
01261   {
01262     Allocate(BITFMT_R8G8B8A8, width, height, slice, NumMipmap);
01263 
01264     for (int mip = 0; mip < m_NumMipmap; mip++)
01265     {
01266       for (int s = 0; s < ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetDepth(), mip); s++)
01267       {
01268         int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), mip);
01269         int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), mip);
01270         MakeCheckBoardImage(* (m_MipSurfaceArray[mip][s]), w, h, color0, color0);
01271       }
01272     }
01273   }
01274 
01275   int NVolumeData::GetNumMipmap() const
01276   {
01277     return m_NumMipmap;
01278   }
01279 
01280   bool NVolumeData::SetSurface(int Slice, int MipLevel, const ImageSurface &targetsurface)
01281   {
01282     nuxAssert(Slice >= 0);
01283     nuxAssert(Slice < m_Depth);
01284     nuxAssert(MipLevel >= 0);
01285     nuxAssert(MipLevel < m_NumMipmap);
01286 
01287     ImageSurface &surface = GetSurface(Slice, MipLevel);
01288 
01289     if (surface.GetFormat() != targetsurface.GetFormat())
01290       return false;
01291 
01292     if (surface.GetWidth() != targetsurface.GetWidth())
01293       return false;
01294 
01295     if (surface.GetHeight() != targetsurface.GetHeight())
01296       return false;
01297 
01298     surface = targetsurface;
01299     return true;
01300   }
01301 
01303   NAnimatedTextureData::NAnimatedTextureData(BitmapFormat format, int width, int height, int depth)
01304     :   m_NumMipmap(0)
01305     ,   m_Depth(0)
01306     ,   m_MipSurfaceArray(0)
01307   {
01308     Allocate(format, width, height, depth, 1);
01309   }
01310 
01311   NAnimatedTextureData::~NAnimatedTextureData()
01312   {
01313     ClearData();
01314   }
01315 
01316   void NAnimatedTextureData::ClearData()
01317   {
01318     for (int mip = 0; mip < GetNumMipmap(); mip++)
01319     {
01320       for (int s = 0; s < ImageSurface::GetLevelDim(GetFormat(), GetDepth(), mip); s++)
01321       {
01322         delete m_MipSurfaceArray[mip][s];
01323       }
01324 
01325       m_MipSurfaceArray[mip].clear();
01326     }
01327 
01328     m_FrameTimeArray.clear();
01329     delete [] m_MipSurfaceArray;
01330   }
01331 
01333   NAnimatedTextureData::NAnimatedTextureData(const NAnimatedTextureData &object)
01334   {
01335     for (int mip = 0; mip < object.GetNumMipmap(); mip++)
01336     {
01337       for (int s = 0; s < ImageSurface::GetLevelDim(object.GetFormat(), object.GetDepth(), mip); s++)
01338       {
01339         m_MipSurfaceArray[mip].push_back(new ImageSurface(object.GetSurface(mip, s)));
01340       }
01341     }
01342 
01343     for (int frame = 0; frame < object.GetDepth(); frame++)
01344     {
01345       m_FrameTimeArray.push_back(object.GetFrameTime(frame));
01346     }
01347   }
01348 
01350   NAnimatedTextureData &NAnimatedTextureData::operator = (const NAnimatedTextureData &copy)
01351   {
01352     ClearData();
01353     m_Depth = copy.GetDepth();
01354     m_NumMipmap = copy.m_NumMipmap;
01355     m_TotalMemorySize = copy.m_TotalMemorySize;
01356 
01357     m_MipSurfaceArray = new std::vector<ImageSurface *>[m_NumMipmap];
01358 
01359     for (int mip = 0; mip < copy.GetNumMipmap(); mip++)
01360     {
01361       for (int s = 0; s < ImageSurface::GetLevelDim(copy.GetFormat(), copy.GetDepth(), mip); s++)
01362       {
01363         m_MipSurfaceArray[mip].push_back(new ImageSurface(copy.GetSurface(s)));
01364       }
01365     }
01366 
01367     for (int frame = 0; frame < copy.GetDepth(); frame++)
01368     {
01369       m_FrameTimeArray.push_back(copy.GetFrameTime(frame));
01370     }
01371 
01372     return *this;
01373   }
01374 
01375   void NAnimatedTextureData::Allocate(BitmapFormat format, int width, int height, int depth, int NumMipmapRequested)
01376   {
01377     nuxAssertMsg(depth >= 0, "[NAnimatedTextureData::Allocate] Error: Negative number of slice.");
01378     nuxAssertMsg(width >= 0, "[NAnimatedTextureData::Allocate] Error: Negative texture width.");
01379     nuxAssertMsg(height >= 0, "[NAnimatedTextureData::Allocate] Error: Negative texture height.");
01380     nuxAssert(NumMipmapRequested >= 0);
01381 
01382     ClearData();
01383 
01384     int NumTotalMipLevel    = 1 + (int) Floor(Log2(Max(width, height)));
01385     m_NumMipmap = NumMipmapRequested;
01386 
01387     if (NumMipmapRequested == 0)
01388       m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1;
01389 
01390     if (NumMipmapRequested > NumTotalMipLevel)
01391       m_NumMipmap = NumTotalMipLevel ? NumTotalMipLevel : 1;
01392 
01393     m_Depth = depth;
01394 
01395     m_MipSurfaceArray = new std::vector<ImageSurface *>[m_NumMipmap];
01396     m_TotalMemorySize = 0;
01397 
01398     for (int mip = 0; mip < m_NumMipmap; mip++)
01399     {
01400       for (int s = 0; s < ImageSurface::GetLevelDim(format, depth, mip); s++)
01401       {
01402         int w = ImageSurface::GetLevelDim(format, width, mip);
01403         int h = ImageSurface::GetLevelDim(format, height, mip);
01404         m_MipSurfaceArray[mip].push_back(new ImageSurface(format, w, h));
01405         m_TotalMemorySize += m_MipSurfaceArray[mip][s]->GetSize();
01406       }
01407     }
01408   }
01409 
01410   void NAnimatedTextureData::AllocateCheckBoardTexture(int width, int height, int slice, int NumMipmap, Color color0, Color color1, int TileWidth, int TileHeight)
01411   {
01412     Allocate(BITFMT_R8G8B8A8, width, height, slice, NumMipmap);
01413 
01414     for (int mip = 0; mip < m_NumMipmap; mip++)
01415     {
01416       for (int s = 0; s < ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetDepth(), mip); s++)
01417       {
01418         int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), mip);
01419         int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), mip);
01420         MakeCheckBoardImage(* (m_MipSurfaceArray[mip][s]), w, h, color0, color1, TileWidth, TileHeight);
01421       }
01422     }
01423   }
01424 
01425   void NAnimatedTextureData::AllocateColorTexture(int width, int height, int slice, int NumMipmap, Color color0)
01426   {
01427     Allocate(BITFMT_R8G8B8A8, width, height, slice, NumMipmap);
01428 
01429     for (int mip = 0; mip < m_NumMipmap; mip++)
01430     {
01431       for (int s = 0; s < ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetDepth(), mip); s++)
01432       {
01433         int w = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetWidth(), mip);
01434         int h = ImageSurface::GetLevelDim(BITFMT_R8G8B8A8, GetHeight(), mip);
01435         MakeCheckBoardImage(* (m_MipSurfaceArray[mip][s]), w, h, color0, color0);
01436       }
01437     }
01438   }
01439 
01440   int NAnimatedTextureData::GetNumMipmap() const
01441   {
01442     return m_NumMipmap;
01443   }
01444 
01445   bool NAnimatedTextureData::SetSurface(int Slice, int MipLevel, const ImageSurface &targetsurface)
01446   {
01447     nuxAssert(Slice >= 0);
01448     nuxAssert(Slice < m_Depth);
01449     nuxAssert(MipLevel >= 0);
01450     nuxAssert(MipLevel < m_NumMipmap);
01451 
01452     ImageSurface &surface = GetSurface(Slice, MipLevel);
01453 
01454     if (surface.GetFormat() != targetsurface.GetFormat())
01455       return false;
01456 
01457     if (surface.GetWidth() != targetsurface.GetWidth())
01458       return false;
01459 
01460     if (surface.GetHeight() != targetsurface.GetHeight())
01461       return false;
01462 
01463     surface = targetsurface;
01464     return true;
01465   }
01466 
01467 }
01468