# Visualization Library

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

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

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.com                                               */
    00005 /*                                                                                    */
    00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
    00007 /*  All rights reserved.                                                              */
    00008 /*                                                                                    */
    00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
    00010 /*  are permitted provided that the following conditions are met:                     */
    00011 /*                                                                                    */
    00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
    00013 /*  list of conditions and the following disclaimer.                                  */
    00014 /*                                                                                    */
    00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
    00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
    00017 /*  other materials provided with the distribution.                                   */
    00018 /*                                                                                    */
    00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
    00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
    00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
    00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
    00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
    00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
    00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
    00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
    00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
    00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
    00029 /*                                                                                    */
    00030 /**************************************************************************************/
    00031
    00032 #include <vlCore/Image.hpp>
    00033 #include <vlCore/checks.hpp>
    00034 #include <vlCore/Say.hpp>
    00035 #include <vlCore/Log.hpp>
    00036 #include <vlCore/VisualizationLibrary.hpp>
    00037 #include <vlCore/FileSystem.hpp>
    00038 #include <vlCore/VirtualFile.hpp>
    00039 #include <vlCore/GLSLmath.hpp>
    00040 #include <vlCore/ResourceDatabase.hpp>
    00041 #include <vlCore/LoadWriterManager.hpp>
    00042
    00043 #include <map>
    00044 #include <cmath>
    00045
    00046 using namespace vl;
    00047
    00048 //-----------------------------------------------------------------------------
    00049 // Image
    00050 //-----------------------------------------------------------------------------
    00051 Image::~Image()
    00052 {
    00053   clear();
    00054 }
    00055 //-----------------------------------------------------------------------------
    00056 Image::Image()
    00057 {
    00058   VL_DEBUG_SET_OBJECT_NAME()
    00059   mPixels = new Buffer;
    00060   clear();
    00061 }
    00062 //-----------------------------------------------------------------------------
    00063 Image::Image(const String& path)
    00064 {
    00065   VL_DEBUG_SET_OBJECT_NAME()
    00066   mPixels = new Buffer;
    00067   clear();
    00068   setObjectName(path.toStdString());
    00069   ref<Image> img = loadImage(path);
    00070   if (!img)
    00071     return;
    00072   // quicker than *this = *img;
    00073   mPixels->swap(*img->mPixels);
    00074   mMipmaps.swap(img->mMipmaps);
    00075   mWidth = img->mWidth;
    00076   mHeight = img->mHeight;
    00077   mDepth = img->mDepth;
    00078   mPitch = img->mPitch;
    00079   mByteAlign = img->mByteAlign;
    00080   mFormat    = img->mFormat;
    00081   mType      = img->mType;
    00082   mIsCubemap = img->mIsCubemap;
    00083 }
    00084 //-----------------------------------------------------------------------------
    00086 Image::Image(int x, int y, int z, int bytealign, EImageFormat format, EImageType type):
    00087   mWidth(x), mHeight(y), mDepth(z), mPitch(0), mByteAlign(1), mFormat(format), mType(type), mIsCubemap(false)
    00088 {
    00089   VL_DEBUG_SET_OBJECT_NAME()
    00090   mPixels = new Buffer;
    00091   setByteAlignment(bytealign);
    00092
    00093   if (x && y && z)
    00094     allocate3D(x,y,z,bytealign,format,type);
    00095   else
    00096   if (x && y)
    00097     allocate2D(x,y,bytealign,format,type);
    00098   else
    00099   if (x)
    00100     allocate1D(x,format,type);
    00101 }
    00102 //-----------------------------------------------------------------------------
    00112 bool Image::isValid() const
    00113 {
    00114   // size check
    00115
    00116   bool x = mWidth > 0 && mHeight == 0 && mDepth == 0;
    00117   bool y = mWidth > 0 && mHeight > 0 && mDepth == 0;
    00118   bool z = mWidth > 0 && mHeight > 0 && mDepth > 0;
    00119
    00120   // format check
    00121
    00122   bool okformat = false;
    00123
    00124   // these go well with all but compressed formats
    00125
    00126   switch(type())
    00127   {
    00128     default:
    00129     break;
    00130
    00131     case IT_UNSIGNED_BYTE:
    00132     case IT_BYTE:
    00133     case IT_UNSIGNED_SHORT:
    00134     case IT_SHORT:
    00135     case IT_UNSIGNED_INT:
    00136     case IT_INT:
    00137     case IT_FLOAT:
    00138     {
    00139       switch(format())
    00140       {
    00141         case IF_COMPRESSED_RGB_S3TC_DXT1:
    00142         case IF_COMPRESSED_RGBA_S3TC_DXT1:
    00143         case IF_COMPRESSED_RGBA_S3TC_DXT3:
    00144         case IF_COMPRESSED_RGBA_S3TC_DXT5:
    00145         {
    00146           break;
    00147         }
    00148
    00149         default:
    00150         {
    00151           okformat = true;
    00152         }
    00153       }
    00154     }
    00155   }
    00156
    00157   // compressed type go well only with compressed formats
    00158
    00159   switch(type())
    00160   {
    00161     default:
    00162     break;
    00163
    00164     case IT_IMPLICIT_TYPE:
    00165     {
    00166       switch(format())
    00167       {
    00168         case IF_COMPRESSED_RGB_S3TC_DXT1:
    00169         case IF_COMPRESSED_RGBA_S3TC_DXT1:
    00170         case IF_COMPRESSED_RGBA_S3TC_DXT3:
    00171         case IF_COMPRESSED_RGBA_S3TC_DXT5:
    00172         {
    00173           okformat = true;
    00174           break;
    00175         }
    00176
    00177         default:
    00178         {
    00179           break;
    00180         }
    00181       }
    00182     }
    00183   }
    00184
    00185   switch(format())
    00186   {
    00187     default:
    00188     break;
    00189
    00190     // depth stencil
    00191     case IF_DEPTH_STENCIL:
    00192     {
    00193       switch(type())
    00194       {
    00195         case IT_FLOAT_32_UNSIGNED_INT_24_8_REV:
    00196         case IT_UNSIGNED_INT_24_8:
    00197           okformat = true;
    00198         default:
    00199         break;
    00200       }
    00201     }
    00202     break;
    00203
    00204     // three components types
    00205
    00206     case IF_RGB:
    00207     case IF_BGR:
    00208     {
    00209       switch(type())
    00210       {
    00211         case IT_UNSIGNED_BYTE_3_3_2:
    00212         case IT_UNSIGNED_BYTE_2_3_3_REV:
    00213         case IT_UNSIGNED_SHORT_5_6_5:
    00214         case IT_UNSIGNED_SHORT_5_6_5_REV:
    00215         case IT_UNSIGNED_INT_5_9_9_9_REV: /* EXT_texture_shared_exponent, support only GL_RGB */
    00216         case IT_UNSIGNED_INT_10F_11F_11F_REV: /* EXT_packed_float, supports only GL_RGB */
    00217         {
    00218           okformat = true;
    00219           break;
    00220         }
    00221
    00222         default:
    00223         {
    00224           break;
    00225         }
    00226       }
    00227       break;
    00228     }
    00229
    00230     // four components types
    00231
    00232     case IF_RGBA:
    00233     case IF_BGRA:
    00234     {
    00235       switch(type())
    00236       {
    00237         case IT_UNSIGNED_SHORT_4_4_4_4:
    00238         case IT_UNSIGNED_SHORT_4_4_4_4_REV:
    00239         case IT_UNSIGNED_SHORT_5_5_5_1:
    00240         case IT_UNSIGNED_SHORT_1_5_5_5_REV:
    00241         case IT_UNSIGNED_INT_8_8_8_8:
    00242         case IT_UNSIGNED_INT_8_8_8_8_REV:
    00243         case IT_UNSIGNED_INT_10_10_10_2:
    00244         case IT_UNSIGNED_INT_2_10_10_10_REV:
    00245         {
    00246           okformat = true;
    00247           break;
    00248         }
    00249
    00250         default:
    00251         {
    00252           break;
    00253         }
    00254       }
    00255     }
    00256   }
    00257
    00258   #ifndef NDEBUG
    00259     bool isvalid = okformat && (x|y|z) && (pitch() % mByteAlign == 0);
    00260     Log::debug( isvalid ? "" : ( okformat ? "Image::isValid(): invalid dimensions or pitch/bytealign combination:\n" : "Image::isValid() reported an invalid format/type combination:\n") + print() );
    00261   #endif
    00262
    00263   return okformat && (x|y|z) && (pitch() % mByteAlign == 0);
    00264 }
    00265 //-----------------------------------------------------------------------------
    00266 String Image::printType() const
    00267 {
    00268   std::map<int, const char*> ty;
    00269
    00270   ty[IT_IMPLICIT_TYPE] = "IT_IMPLICIT_TYPE";
    00271   ty[IT_UNSIGNED_BYTE] = "IT_UNSIGNED_BYTE";
    00272   ty[IT_BYTE] = "IT_BYTE";
    00273   ty[IT_UNSIGNED_SHORT] = "IT_UNSIGNED_SHORT";
    00274   ty[IT_SHORT] = "IT_SHORT";
    00275   ty[IT_UNSIGNED_INT] = "IT_UNSIGNED_INT";
    00276   ty[IT_INT] = "IT_INT";
    00277   ty[IT_FLOAT] = "IT_FLOAT";
    00278   ty[IT_UNSIGNED_BYTE_3_3_2] = "IT_UNSIGNED_BYTE_3_3_2";
    00279   ty[IT_UNSIGNED_BYTE_2_3_3_REV] = "IT_UNSIGNED_BYTE_2_3_3_REV";
    00280   ty[IT_UNSIGNED_SHORT_5_6_5] = "IT_UNSIGNED_SHORT_5_6_5";
    00281   ty[IT_UNSIGNED_SHORT_5_6_5_REV] = "IT_UNSIGNED_SHORT_5_6_5_REV";
    00282   ty[IT_UNSIGNED_SHORT_4_4_4_4] = "IT_UNSIGNED_SHORT_4_4_4_4";
    00283   ty[IT_UNSIGNED_SHORT_4_4_4_4_REV] = "IT_UNSIGNED_SHORT_4_4_4_4_REV";
    00284   ty[IT_UNSIGNED_SHORT_5_5_5_1] = "IT_UNSIGNED_SHORT_5_5_5_1";
    00285   ty[IT_UNSIGNED_SHORT_1_5_5_5_REV] = "IT_UNSIGNED_SHORT_1_5_5_5_REV";
    00286   ty[IT_UNSIGNED_INT_8_8_8_8] = "IT_UNSIGNED_INT_8_8_8_8";
    00287   ty[IT_UNSIGNED_INT_8_8_8_8_REV] = "IT_UNSIGNED_INT_8_8_8_8_REV";
    00288   ty[IT_UNSIGNED_INT_10_10_10_2] = "IT_UNSIGNED_INT_10_10_10_2";
    00289   ty[IT_UNSIGNED_INT_2_10_10_10_REV] = "IT_UNSIGNED_INT_2_10_10_10_REV";
    00290   ty[IT_UNSIGNED_INT_5_9_9_9_REV] = "IT_UNSIGNED_INT_5_9_9_9_REV";
    00291   ty[IT_UNSIGNED_INT_10F_11F_11F_REV] = "IT_UNSIGNED_INT_10F_11F_11F_REV";
    00292   ty[IT_UNSIGNED_INT_24_8] = "IT_UNSIGNED_INT_24_8";
    00293   ty[IT_FLOAT_32_UNSIGNED_INT_24_8_REV] = "IT_FLOAT_32_UNSIGNED_INT_24_8_REV";
    00294
    00295   VL_CHECK(ty[type()] != NULL)
    00296
    00297   return ty[type()];
    00298 }
    00299 //-----------------------------------------------------------------------------
    00300 String Image::printFormat() const
    00301 {
    00302   std::map<int, const char*> fo;
    00303
    00304   fo[IF_RGB] = "IF_RGB";
    00305   fo[IF_RGBA] = "IF_RGBA";
    00306   fo[IF_BGR] = "IF_BGR";
    00307   fo[IF_BGRA] = "IF_BGRA";
    00308   fo[IF_RED] = "IF_RED";
    00309   fo[IF_GREEN] = "IF_GREEN";
    00310   fo[IF_BLUE] = "IF_BLUE";
    00311   fo[IF_ALPHA] = "IF_ALPHA";
    00312   fo[IF_LUMINANCE] = "IF_LUMINANCE";
    00313   fo[IF_LUMINANCE_ALPHA] = "IF_LUMINANCE_ALPHA";
    00314   fo[IF_DEPTH_COMPONENT] = "IF_DEPTH_COMPONENT";
    00315   fo[IF_STENCIL_INDEX] = "IF_STENCIL_INDEX";
    00316   fo[IF_DEPTH_STENCIL] = "IF_DEPTH_STENCIL";
    00317   fo[IF_COMPRESSED_RGB_S3TC_DXT1] = "IF_COMPRESSED_RGB_S3TC_DXT1";
    00318   fo[IF_COMPRESSED_RGBA_S3TC_DXT1] = "IF_COMPRESSED_RGBA_S3TC_DXT1";
    00319   fo[IF_COMPRESSED_RGBA_S3TC_DXT3] = "IF_COMPRESSED_RGBA_S3TC_DXT3";
    00320   fo[IF_COMPRESSED_RGBA_S3TC_DXT5] = "IF_COMPRESSED_RGBA_S3TC_DXT5";
    00321
    00322   VL_CHECK( fo[format()] != NULL );
    00323
    00324   return fo[format()];
    00325 }
    00326 //-----------------------------------------------------------------------------
    00327 String Image::print() const
    00328 {
    00329   return Say(
    00330   "name   = %s\n"
    00331   "width  = %n\n"
    00332   "height = %n\n"
    00333   "depth  = %n\n"
    00334   "format = %s\n"
    00335   "type   = %s\n"
    00336   "pitch  = %n\n"
    00337   "bytealign = %n\n"
    00338   )
    00339   << objectName().c_str()
    00340   << width()
    00341   << height()
    00342   << depth()
    00343   << printFormat()
    00344   << printType()
    00345   << pitch()
    00346   << byteAlignment();
    00347 }
    00348 //-----------------------------------------------------------------------------
    00349 EImageDimension Image::dimension() const
    00350 {
    00351   if(mWidth > 0 && mHeight == 0 && mDepth == 0 && !mIsCubemap) return ID_1D;
    00352   if(mWidth > 0 && mHeight > 0  && mDepth == 0 && !mIsCubemap) return ID_2D;
    00353   if(mWidth > 0 && mHeight > 0  && mDepth >  0 && !mIsCubemap) return ID_3D;
    00354   if(mWidth > 0 && mHeight > 0  && mDepth == 0 &&  mIsCubemap) return ID_Cubemap;
    00355   return ID_Error;
    00356 }
    00357 //-----------------------------------------------------------------------------
    00359 int Image::bitsPerPixel(EImageType type, EImageFormat format)
    00360 {
    00361   int comp_size = 0;
    00362
    00363   switch(type)
    00364   {
    00365     default:
    00366     break;
    00367
    00368     case IT_UNSIGNED_BYTE:  comp_size = sizeof(unsigned char)  * 8; break;
    00369     case IT_BYTE:           comp_size = sizeof(GLbyte)   * 8; break;
    00370     case IT_UNSIGNED_SHORT: comp_size = sizeof(GLushort) * 8; break;
    00371     case IT_SHORT:          comp_size = sizeof(GLshort)  * 8; break;
    00372     case IT_UNSIGNED_INT:   comp_size = sizeof(unsigned int)   * 8; break;
    00373     case IT_INT:            comp_size = sizeof(int)    * 8; break;
    00374     case IT_FLOAT:          comp_size = sizeof(float)  * 8; break;
    00375
    00376     case IT_UNSIGNED_BYTE_3_3_2:          return 8;
    00377     case IT_UNSIGNED_BYTE_2_3_3_REV:      return 8;
    00378     case IT_UNSIGNED_SHORT_5_6_5:         return 16;
    00379     case IT_UNSIGNED_SHORT_5_6_5_REV:     return 16;
    00380     case IT_UNSIGNED_SHORT_4_4_4_4:       return 16;
    00381     case IT_UNSIGNED_SHORT_4_4_4_4_REV:   return 16;
    00382     case IT_UNSIGNED_SHORT_5_5_5_1:       return 16;
    00383     case IT_UNSIGNED_SHORT_1_5_5_5_REV:   return 16;
    00384     case IT_UNSIGNED_INT_8_8_8_8:         return 32;
    00385     case IT_UNSIGNED_INT_8_8_8_8_REV:     return 32;
    00386     case IT_UNSIGNED_INT_10_10_10_2:      return 32;
    00387     case IT_UNSIGNED_INT_2_10_10_10_REV:  return 32;
    00388     case IT_UNSIGNED_INT_5_9_9_9_REV:     return 32; /* EXT_texture_shared_exponent, support only IF_RGB */
    00389     case IT_UNSIGNED_INT_10F_11F_11F_REV: return 32; /* EXT_packed_float, supports only IF_RGB */
    00390     case IT_UNSIGNED_INT_24_8:            return 32; /* EXT_packed_depth_stencil, supports only IF_DEPTH_STENCIL */
    00391     case IT_FLOAT_32_UNSIGNED_INT_24_8_REV: return 64; /* EXT_depth_buffer_float, supports only IF_DEPTH_STENCIL */
    00392   }
    00393
    00394   switch(format)
    00395   {
    00396     case IF_RED:             return comp_size * 1;
    00397     case IF_GREEN:           return comp_size * 1;
    00398     case IF_BLUE:            return comp_size * 1;
    00399     case IF_ALPHA:           return comp_size * 1;
    00400     case IF_DEPTH_COMPONENT: return comp_size * 1;
    00401     case IF_STENCIL_INDEX:   return comp_size * 1;
    00402     case IF_LUMINANCE:       return comp_size * 1;
    00403     case IF_LUMINANCE_ALPHA: return comp_size * 2;
    00404     case IF_DEPTH_STENCIL:   return comp_size * 0;
    00405     case IF_RGB:             return comp_size * 3;
    00406     case IF_BGR:             return comp_size * 3;
    00407     case IF_RGBA:            return comp_size * 4;
    00408     case IF_BGRA:            return comp_size * 4;
    00409
    00410      // compressed formats
    00411
    00412     case IF_COMPRESSED_RGB_S3TC_DXT1:  return 4; // 8 bytes (64 bits) per block per 16 pixels
    00413     case IF_COMPRESSED_RGBA_S3TC_DXT1: return 4; // 8 bytes (64 bits) per block per 16 pixels
    00414     case IF_COMPRESSED_RGBA_S3TC_DXT3: return 8; // 16 bytes (128 bits) per block per 16 pixels
    00415     case IF_COMPRESSED_RGBA_S3TC_DXT5: return 8; // 16 bytes (128 bits) per block per 16 pixels
    00416     default:
    00417       break;
    00418   }
    00419
    00420   VL_TRAP()
    00421   return 0;
    00422 }
    00423 //-----------------------------------------------------------------------------
    00425 int Image::alphaBits() const
    00426 {
    00427   int comp_size = 0;
    00428
    00429   switch(format())
    00430   {
    00431     case IF_RED:             return comp_size * 0;
    00432     case IF_GREEN:           return comp_size * 0;
    00433     case IF_BLUE:            return comp_size * 0;
    00434     case IF_ALPHA:           return comp_size * 1;
    00435     case IF_DEPTH_COMPONENT: return comp_size * 0;
    00436     case IF_STENCIL_INDEX:   return comp_size * 0;
    00437     case IF_LUMINANCE:       return comp_size * 0;
    00438     case IF_LUMINANCE_ALPHA: return comp_size * 1;
    00439     case IF_DEPTH_STENCIL:   return comp_size * 0;
    00440     case IF_RGB:             return comp_size * 0;
    00441     case IF_BGR:             return comp_size * 0;
    00442     case IF_RGBA:            return comp_size * 1;
    00443     case IF_BGRA:            return comp_size * 1;
    00444
    00445      // compressed formats
    00446
    00447     case IF_COMPRESSED_RGB_S3TC_DXT1:  return 0; // 8 bytes (64 bits) per block per 16 pixels
    00448     case IF_COMPRESSED_RGBA_S3TC_DXT1: return 1; // 8 bytes (64 bits) per block per 16 pixels
    00449     case IF_COMPRESSED_RGBA_S3TC_DXT3: return 4; // 16 bytes (64 bits for uncompressed alpha + 64 bits for RGB) per block per 16 pixels
    00450     case IF_COMPRESSED_RGBA_S3TC_DXT5: return 4; // 16 bytes (64 bits for   compressed alpha + 64 bits for RGB) per block per 16 pixels
    00451     default:
    00452       break;
    00453   }
    00454
    00455   switch(type())
    00456   {
    00457     default:
    00458     break;
    00459
    00460     case IT_UNSIGNED_BYTE:  comp_size = sizeof(unsigned char)  * 8; break;
    00461     case IT_BYTE:           comp_size = sizeof(GLbyte)   * 8; break;
    00462     case IT_UNSIGNED_SHORT: comp_size = sizeof(GLushort) * 8; break;
    00463     case IT_SHORT:          comp_size = sizeof(GLshort)  * 8; break;
    00464     case IT_UNSIGNED_INT:   comp_size = sizeof(unsigned int)   * 8; break;
    00465     case IT_INT:            comp_size = sizeof(int)    * 8; break;
    00466     case IT_FLOAT:          comp_size = sizeof(float)  * 8; break;
    00467
    00468     case IT_UNSIGNED_BYTE_3_3_2:          return 0;
    00469     case IT_UNSIGNED_BYTE_2_3_3_REV:      return 0;
    00470     case IT_UNSIGNED_SHORT_5_6_5:         return 0;
    00471     case IT_UNSIGNED_SHORT_5_6_5_REV:     return 0;
    00472     case IT_UNSIGNED_SHORT_4_4_4_4:       return 4;
    00473     case IT_UNSIGNED_SHORT_4_4_4_4_REV:   return 4;
    00474     case IT_UNSIGNED_SHORT_5_5_5_1:       return 1;
    00475     case IT_UNSIGNED_SHORT_1_5_5_5_REV:   return 1;
    00476     case IT_UNSIGNED_INT_8_8_8_8:         return 8;
    00477     case IT_UNSIGNED_INT_8_8_8_8_REV:     return 8;
    00478     case IT_UNSIGNED_INT_10_10_10_2:      return 2;
    00479     case IT_UNSIGNED_INT_2_10_10_10_REV:  return 2;
    00480     case IT_UNSIGNED_INT_5_9_9_9_REV:     return 0; /* EXT_texture_shared_exponent, support only GL_RGB */
    00481     case IT_UNSIGNED_INT_10F_11F_11F_REV: return 0; /* EXT_packed_float, supports only GL_RGB */
    00482     case IT_UNSIGNED_INT_24_8:            return 0; /* EXT_packed_depth_stencil, supports only GL_DEPTH_STENCIL */
    00483     case IT_FLOAT_32_UNSIGNED_INT_24_8_REV: return 0; /* EXT_depth_buffer_float, supports only IF_DEPTH_STENCIL */
    00484   }
    00485
    00486   VL_TRAP()
    00487
    00488   return 0;
    00489 }
    00490 //-----------------------------------------------------------------------------
    00491 int Image::isCompressedFormat(EImageFormat fmt)
    00492 {
    00493   switch(fmt)
    00494   {
    00495   case IF_COMPRESSED_RGB_S3TC_DXT1:
    00496   case IF_COMPRESSED_RGBA_S3TC_DXT1:
    00497   case IF_COMPRESSED_RGBA_S3TC_DXT3:
    00498   case IF_COMPRESSED_RGBA_S3TC_DXT5:
    00499     return true;
    00500
    00501   default:
    00502     return false;
    00503   }
    00504 }
    00505 //-----------------------------------------------------------------------------
    00508 int Image::requiredMemory() const
    00509 {
    00510   VL_CHECK( isValid() )
    00511   return requiredMemory(width(), height(), depth(), byteAlignment(), format(), type(), isCubemap());
    00512 }
    00513 //-----------------------------------------------------------------------------
    00516 int Image::byteAlignment() const
    00517 {
    00518   return mByteAlign;
    00519 }
    00520 //-----------------------------------------------------------------------------
    00526 void Image::setByteAlignment(int bytealign)
    00527 {
    00528   // cannot change the alignment when an image is already allocated
    00529
    00530   VL_CHECK(mPixels->empty());
    00531
    00532   if (!mPixels->empty())
    00533     return;
    00534
    00535   switch(bytealign)
    00536   {
    00537   case 0:
    00538     bytealign = sizeof(unsigned char*);
    00539   case 1:
    00540   case 2:
    00541   case 4:
    00542   case 8:
    00543     break;
    00544   default:
    00545     VL_TRAP()
    00546   }
    00547
    00548   mByteAlign = bytealign;
    00549
    00550   updatePitch();
    00551 }
    00552 //-----------------------------------------------------------------------------
    00553 void Image::updatePitch()
    00554 {
    00555   int xbits  = mWidth * bitsPerPixel();
    00556   int xbytes = xbits/8 + ( (xbits % 8) ? 1 : 0 );
    00557   mPitch     = xbytes/mByteAlign*mByteAlign + ( (xbytes % mByteAlign) ? mByteAlign : 0 );
    00558 }
    00559 //-----------------------------------------------------------------------------
    00560 void Image::allocateCubemap(int x, int y, int bytealign, EImageFormat format, EImageType type)
    00561 {
    00562   clear();
    00563
    00564   setWidth(x);
    00565   setHeight(y);
    00566   setDepth(0);
    00567   setFormat(format);
    00568   setType(type);
    00569   setByteAlignment(bytealign);
    00570   mIsCubemap = true;
    00571
    00572   // mPixels.clear();
    00573   mPixels->resize(requiredMemory());
    00574 }
    00575 //-----------------------------------------------------------------------------
    00576 void Image::allocate()
    00577 {
    00578   mMipmaps.clear();
    00579   mPixels->resize(requiredMemory());
    00580 }
    00581 //-----------------------------------------------------------------------------
    00582 void Image::allocate1D(int x, EImageFormat format, EImageType type)
    00583 {
    00584   clear();
    00585
    00586   VL_CHECK(x);
    00587   setWidth(x);
    00588   setHeight(0);
    00589   setDepth(0);
    00590   setFormat(format);
    00591   setType(type);
    00592   setByteAlignment(1);
    00593   mIsCubemap = false;
    00594
    00595   mPixels->resize(requiredMemory());
    00596 }
    00597 //-----------------------------------------------------------------------------
    00598 void Image::allocate2D(int x, int y, int bytealign, EImageFormat format, EImageType type)
    00599 {
    00600   clear();
    00601
    00602   VL_CHECK(x);
    00603   VL_CHECK(y);
    00604   setWidth(x);
    00605   setHeight(y);
    00606   setDepth(0);
    00607   setFormat(format);
    00608   setType(type);
    00609   setByteAlignment(bytealign);
    00610   mIsCubemap = false;
    00611
    00612   int req_mem = requiredMemory();
    00613   if (req_mem == 0)
    00614     Log::bug("Image::allocate2D could not allocate memory, probably your image settings are invalid.\n");
    00615   // mPixels.clear();
    00616   mPixels->resize(req_mem);
    00617 }
    00618 //-----------------------------------------------------------------------------
    00619 void Image::allocate3D(int x, int y, int z, int bytealign, EImageFormat format, EImageType type)
    00620 {
    00621   clear();
    00622
    00623   VL_CHECK(x);
    00624   VL_CHECK(y);
    00625   VL_CHECK(z);
    00626   setWidth(x);
    00627   setHeight(y);
    00628   setDepth(z);
    00629   setFormat(format);
    00630   setType(type);
    00631   setByteAlignment(bytealign);
    00632   mIsCubemap = false;
    00633
    00634   mPixels->resize(requiredMemory());
    00635 }
    00636 //-----------------------------------------------------------------------------
    00637 void Image::reset(int x, int y, int z, int bytealign, EImageFormat format, EImageType type, bool is_cubemap)
    00638 {
    00639   clear();
    00640
    00641   setWidth(x);
    00642   setHeight(y);
    00643   setDepth(z);
    00644   setFormat(format);
    00645   setType(type);
    00646   setByteAlignment(bytealign);
    00647   mIsCubemap = is_cubemap;
    00648 }
    00649 //-----------------------------------------------------------------------------
    00650 void Image::clear()
    00651 {
    00652   mPixels->clear();
    00653   mMipmaps.clear();
    00654   mObjectName.clear();
    00655   mWidth = 0;
    00656   mHeight = 0;
    00657   mDepth = 0;
    00658   mPitch = 0;
    00659   mFormat = IF_RGBA;
    00660   mType = IT_UNSIGNED_BYTE;
    00661   mByteAlign = 1;
    00662   mIsCubemap = false;
    00663 }
    00664 //-----------------------------------------------------------------------------
    00665 Image& Image::operator=(const Image& other)
    00666 {
    00667   setObjectName(other.objectName());
    00668
    00669   // deep copy of the pixels
    00670   *mPixels = *other.mPixels;
    00671
    00672   // copy image info
    00673   mWidth  = other.mWidth;
    00674   mHeight  = other.mHeight;
    00675   mDepth  = other.mDepth;
    00676   mPitch  = other.mPitch;
    00677   mByteAlign = other.mByteAlign;
    00678   mFormat    = other.mFormat;
    00679   mType      = other.mType;
    00680   mIsCubemap = other.mIsCubemap;
    00681
    00682   // deep copy of the mipmaps
    00683   mMipmaps.resize(other.mMipmaps.size());
    00684   for(int i=0; i<(int)mMipmaps.size(); ++i)
    00685   {
    00686     mMipmaps[i] = new Image;
    00687     *mMipmaps[i] = *other.mMipmaps[i];
    00688   }
    00689   return *this;
    00690 }
    00691 //-----------------------------------------------------------------------------
    00692 unsigned char* Image::pixelsXP()
    00693 {
    00694   if( dimension() != 4 || !pixels())
    00695   {
    00696     VL_TRAP()
    00697     return NULL;
    00698   }
    00699   else
    00700   {
    00701     return pixels();
    00702   }
    00703 }
    00704 //-----------------------------------------------------------------------------
    00705 unsigned char* Image::pixelsXN()
    00706 {
    00707   if( dimension() != 4 || !pixels())
    00708   {
    00709     VL_TRAP()
    00710     return NULL;
    00711   }
    00712   else
    00713   {
    00714     return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 1;
    00715   }
    00716 }
    00717 //-----------------------------------------------------------------------------
    00718 unsigned char* Image::pixelsYP()
    00719 {
    00720   if( dimension() != 4 || !pixels())
    00721   {
    00722     VL_TRAP()
    00723     return NULL;
    00724   }
    00725   else
    00726   {
    00727     return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 2;
    00728   }
    00729 }
    00730 //-----------------------------------------------------------------------------
    00731 unsigned char* Image::pixelsYN()
    00732 {
    00733   if( dimension() != 4 || !pixels())
    00734   {
    00735     VL_TRAP()
    00736     return NULL;
    00737   }
    00738   else
    00739   {
    00740     return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 3;
    00741   }
    00742 }
    00743 //-----------------------------------------------------------------------------
    00744 unsigned char* Image::pixelsZP()
    00745 {
    00746   if( dimension() != 4 || !pixels())
    00747   {
    00748     VL_TRAP()
    00749     return NULL;
    00750   }
    00751   else
    00752   {
    00753     return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 4;
    00754   }
    00755 }
    00756 //-----------------------------------------------------------------------------
    00757 unsigned char* Image::pixelsZN()
    00758 {
    00759   if ( dimension() != 4 || !pixels())
    00760   {
    00761     VL_TRAP()
    00762     return NULL;
    00763   }
    00764   else
    00765   {
    00766     return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 5;
    00767   }
    00768 }
    00769 //-----------------------------------------------------------------------------
    00771 unsigned char* Image::pixelsZSlice(int slice)
    00772 {
    00773   VL_CHECK(slice < depth());
    00774   VL_CHECK(slice >= 0 );
    00775   if (mIsCubemap || !pixels())
    00776     return NULL;
    00777   else
    00778   {
    00779     return (unsigned char*)pixels() + pitch()*height()*slice;
    00780   }
    00781 }
    00782 //-----------------------------------------------------------------------------
    00783 ref<Image> vl::createCubemap(const Image* xp, const Image* xn, const Image* yp, const Image* yn, const Image* zp, const Image* zn)
    00784 {
    00785   // check validity of all the images
    00786   // contract:
    00787   // - they must be all isValid() images, must have been allocated, must be 2D images, must
    00788   // - have exactly the same dimensions, format, type, byte alignment.
    00789   // - they must be square
    00790
    00791   const Image* img[] = {xp, xn, yp, yn, zp, zn};
    00792
    00793   // check they are square (later we check they have the same size)
    00794   if (img[0]->width() != img[0]->height())
    00795   {
    00796     Log::error("Cubemap creation failed: all the images must be square.\n");
    00797     return NULL;
    00798   }
    00799
    00800   for(int i=0; i<6; ++i)
    00801   {
    00802     if (img[i] == NULL || !img[i]->isValid() || img[i]->pixels() == NULL || img[i]->dimension() != 2)
    00803     {
    00804       Log::error("Cubemap creation failed: one or more image is invalid (could be NULL, not allocated, not 2D, wrong internal_ configuration or other).\n");
    00805       return NULL;
    00806     }
    00807
    00808     // check that they have the same size
    00809     if (img[0]->width() != img[i]->width())
    00810     {
    00811       Log::error("Cubemap creation failed: the faces of the cube must have the very same dimensions.\n");
    00812       return NULL;
    00813     }
    00814
    00815     // check that they have the same size
    00816     if (img[0]->height() != img[i]->height())
    00817     {
    00818       Log::error("Cubemap creation failed: the faces of the cube must have the very same dimensions.\n");
    00819       return NULL;
    00820     }
    00821
    00822     // check that they have the same format
    00823     if (img[0]->format() != img[i]->format())
    00824     {
    00825       Log::error("Cubemap creation failed: the faces of the cube must have the very same format.\n");
    00826       return NULL;
    00827     }
    00828
    00829     // check that they have the same type
    00830     if (img[0]->type() != img[i]->type())
    00831     {
    00832       Log::error("Cubemap creation failed: the faces of the cube must have the very same type.\n");
    00833       return NULL;
    00834     }
    00835
    00836     // check that they have the same byte alignment
    00837     if (img[0]->byteAlignment() != img[i]->byteAlignment())
    00838     {
    00839       Log::error("Cubemap creation failed: the faces of the cube must have the very same byte alignment.\n");
    00840       return NULL;
    00841     }
    00842
    00843     // check that they have the same required memory
    00844     if (img[0]->requiredMemory() != img[i]->requiredMemory())
    00845     {
    00846       Log::error("Cubemap creation failed: the faces of the cube must require the very same amount of memory.\n");
    00847       return NULL;
    00848     }
    00849   }
    00850
    00851   // create a cube map image from the given 2D images
    00852
    00853   ref<Image> cubemap = new Image;
    00854
    00855   cubemap->allocateCubemap( img[0]->width(), img[0]->height(), img[0]->byteAlignment(), img[0]->format(), img[0]->type() );
    00856
    00857   memcpy( cubemap->pixelsXP(), img[0]->pixels(), img[0]->requiredMemory() );
    00858   memcpy( cubemap->pixelsXN(), img[1]->pixels(), img[0]->requiredMemory() );
    00859   memcpy( cubemap->pixelsYP(), img[2]->pixels(), img[0]->requiredMemory() );
    00860   memcpy( cubemap->pixelsYN(), img[3]->pixels(), img[0]->requiredMemory() );
    00861   memcpy( cubemap->pixelsZP(), img[4]->pixels(), img[0]->requiredMemory() );
    00862   memcpy( cubemap->pixelsZN(), img[5]->pixels(), img[0]->requiredMemory() );
    00863
    00864   return cubemap.get();
    00865 }
    00866 //-----------------------------------------------------------------------------
    00867 void Image::flipVertically()
    00868 {
    00869   if (dimension() == ID_1D)
    00870     return;
    00871
    00872   VL_CHECK(pixels());
    00873   int row_size = pitch();
    00874   std::vector<unsigned char> row1;
    00875   row1.resize(row_size);
    00876
    00877   std::vector<unsigned char*> pxl;
    00878
    00879   if (dimension() == ID_2D)
    00880   {
    00881     pxl.push_back( (unsigned char*)pixels() );
    00882   }
    00883   else
    00884   if (dimension() == ID_Cubemap)
    00885   {
    00886     pxl.push_back( (unsigned char*)pixelsXP() );
    00887     pxl.push_back( (unsigned char*)pixelsXN() );
    00888     pxl.push_back( (unsigned char*)pixelsYP() );
    00889     pxl.push_back( (unsigned char*)pixelsYN() );
    00890     pxl.push_back( (unsigned char*)pixelsZP() );
    00891     pxl.push_back( (unsigned char*)pixelsZN() );
    00892   }
    00893   else
    00894   if (dimension() == ID_3D)
    00895   {
    00896     for(int zslice=0; zslice<depth(); zslice++)
    00897       pxl.push_back( (unsigned char*)pixelsZSlice(zslice) );
    00898   }
    00899
    00900   for(unsigned img=0; img<pxl.size(); img++)
    00901   {
    00902     for(int i=0; i<height()/2; ++i)
    00903     {
    00904       int j = height() - 1 - i;
    00905       memcpy(&row1[0], pxl[img]+i*row_size, row_size);
    00906       memcpy(pxl[img]+i*row_size, pxl[img]+j*row_size, row_size);
    00907       memcpy(pxl[img]+j*row_size,  &row1[0], row_size);
    00908     }
    00909   }
    00910 }
    00911 //-----------------------------------------------------------------------------
    00912 int Image::requiredMemory(int width, int height, int depth, int bytealign, EImageFormat format, EImageType type, bool is_cubemap)
    00913 {
    00914   // byte align
    00915
    00916   switch(bytealign)
    00917   {
    00918   case 1:
    00919   case 2:
    00920   case 4:
    00921   case 8:
    00922     break;
    00923   case 0:
    00924   default:
    00925     bytealign = sizeof(unsigned char*);
    00926   }
    00927
    00928   // fix width and height to match compression scheme
    00929
    00930   switch(format)
    00931   {
    00932     case IF_COMPRESSED_RGB_S3TC_DXT1:
    00933     case IF_COMPRESSED_RGBA_S3TC_DXT1:
    00934     case IF_COMPRESSED_RGBA_S3TC_DXT3:
    00935     case IF_COMPRESSED_RGBA_S3TC_DXT5:
    00936       if (width % 4)
    00937         width = width - width % 4 + 4;
    00938       if (height % 4)
    00939         height = height - height % 4 + 4;
    00940     default:
    00941       break;
    00942   }
    00943
    00944   // pitch
    00945
    00946   int xbits = width * bitsPerPixel(type, format);
    00947   int xbytes = xbits/8 + ( (xbits % 8) ? 1 : 0 );
    00948   int pitch  = xbytes/bytealign*bytealign + ( (xbytes % bytealign) ? bytealign : 0 );
    00949
    00950   // computation
    00951
    00952   height = height ? height : 1;
    00953   depth  = depth  ? depth  : 1;
    00954   int req_mem = pitch * height * depth;
    00955
    00956   // minimum memory taken by a compressed block
    00957   if (req_mem < 8 && format == IF_COMPRESSED_RGB_S3TC_DXT1)
    00958     req_mem = 8;
    00959
    00960   if (req_mem < 8 && format == IF_COMPRESSED_RGBA_S3TC_DXT1)
    00961     req_mem = 8;
    00962
    00963   if (req_mem < 16 && format == IF_COMPRESSED_RGBA_S3TC_DXT3)
    00964     req_mem = 16;
    00965
    00966   if (req_mem < 16 && format == IF_COMPRESSED_RGBA_S3TC_DXT5)
    00967     req_mem = 16;
    00968
    00969   // todo: add other compression schemes
    00970   // ...
    00971
    00972   // cubemap
    00973   if (is_cubemap)
    00974     req_mem *= 6;
    00975
    00976   return req_mem;
    00977 }
    00978 //-----------------------------------------------------------------------------
    00979 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1)
    00980 {
    00981   std::vector<fvec4> colors;
    00982   colors.push_back(c0); colors.push_back(c1);
    00983   return makeColorSpectrum(width, colors);
    00984 }
    00985 //-----------------------------------------------------------------------------
    00986 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2)
    00987 {
    00988   std::vector<fvec4> colors;
    00989   colors.push_back(c0); colors.push_back(c1); colors.push_back(c2);
    00990   return makeColorSpectrum(width, colors);
    00991 }
    00992 //-----------------------------------------------------------------------------
    00993 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2, const fvec4& c3)
    00994 {
    00995   std::vector<fvec4> colors;
    00996   colors.push_back(c0); colors.push_back(c1); colors.push_back(c2); colors.push_back(c3);
    00997   return makeColorSpectrum(width, colors);
    00998 }
    00999 //-----------------------------------------------------------------------------
    01000 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2, const fvec4& c3, const fvec4& c4)
    01001 {
    01002   std::vector<fvec4> colors;
    01003   colors.push_back(c0); colors.push_back(c1); colors.push_back(c2); colors.push_back(c3); colors.push_back(c4);
    01004   return makeColorSpectrum(width, colors);
    01005 }
    01006 //-----------------------------------------------------------------------------
    01007 ref<Image> vl::makeNonUniformColorSpectrum(size_t width, size_t col_count, const fvec4* colors, const float* col_pos)
    01008 {
    01009   //     c0    c1    c2    c4
    01010   // |---t0----t1----t2----t4---|
    01011   // before t0 the color is pure c0
    01012   // after t4 the color is pure t4
    01013
    01014   ref<Image> img = new Image(width, 0, 0, 1, IF_RGBA, IT_UNSIGNED_BYTE);
    01015   ubvec4* px = (ubvec4*)img->pixels();
    01016   int last = col_count-1;
    01017   for(int i=0; i<img->width(); ++i)
    01018   {
    01019     float t = (float)i/(img->width()-1);
    01020     if (t<=col_pos[0])
    01021       px[i] = (ubvec4)(colors[0]*255.0f);
    01022     else
    01023     if (t>=col_pos[last])
    01024       px[i] = (ubvec4)(colors[last]*255.0f);
    01025     else
    01026     {
    01027       for(size_t j=0; j<col_count-1; ++j)
    01028       {
    01029         if (t>=col_pos[j] && t<=col_pos[j+1])
    01030         {
    01031           float tt = 0;
    01032           if (col_pos[j+1]-col_pos[j] != 0)
    01033             tt = (t-col_pos[j])/(col_pos[j+1]-col_pos[j]);
    01034           VL_CHECK(tt>=0 && tt<=1.0f)
    01035           px[i] = (ubvec4)((colors[j] * (1.0f-tt) + colors[j+1] * tt)*255.0f);
    01036           break;
    01037         }
    01038       }
    01039     }
    01040   }
    01041   return img;
    01042 }
    01043 //-----------------------------------------------------------------------------
    01044 ref<Image> vl::makeNonUniformColorSpectrum(int width, const std::vector<fvec4>& colors, const std::vector<float>& col_pos)
    01045 {
    01046   if (colors.empty() || colors.size() != col_pos.size())
    01047     return NULL;
    01048   else
    01049     return makeNonUniformColorSpectrum(width, colors.size(), &colors[0], &col_pos[0]);
    01050 }
    01051 //-----------------------------------------------------------------------------
    01052 ref<Image> vl::makeColorSpectrum(size_t width, const std::vector<fvec4>& colors)
    01053 {
    01054   ref<Image> img = new Image(width, 0, 0, 1, IF_RGBA, IT_UNSIGNED_BYTE);
    01055   int index = colors.size() - 1;
    01056   for(int i=0; i<img->width(); ++i)
    01057   {
    01058     int   coli = (int)(index * (float)i/img->width());
    01059     float colt = (index * (float)i/img->width()) - coli;
    01060     img->pixels()[i*4 + 0] = (unsigned char)(255.0 * (colors[coli].r()*(1.0f-colt) + colors[coli+1].r()*colt));
    01061     img->pixels()[i*4 + 1] = (unsigned char)(255.0 * (colors[coli].g()*(1.0f-colt) + colors[coli+1].g()*colt));
    01062     img->pixels()[i*4 + 2] = (unsigned char)(255.0 * (colors[coli].b()*(1.0f-colt) + colors[coli+1].b()*colt));
    01063     img->pixels()[i*4 + 3] = 255;
    01064   }
    01065   return img;
    01066 }
    01067 //-----------------------------------------------------------------------------
    01069 ref<Image> vl::assemble3DImage(const std::vector< ref<Image> >& images)
    01070 {
    01071   if (images.empty())
    01072     return NULL;
    01073   // sanity checks
    01074   for(unsigned i=1; i<images.size(); ++i)
    01075   {
    01076     if (images[i]->width()  != images[0]->width())  return NULL;
    01077     if (images[i]->height() != images[0]->height()) return NULL;
    01078     if (images[i]->depth()  != images[0]->depth())  return NULL;
    01079     if (images[i]->type()   != images[0]->type())   return NULL;
    01080     if (images[i]->format() != images[0]->format()) return NULL;
    01081     if (images[i]->byteAlignment()  != images[0]->byteAlignment())  return NULL;
    01082     if (images[i]->bitsPerPixel()   != images[0]->bitsPerPixel())   return NULL;
    01083     if (images[i]->requiredMemory() != images[0]->requiredMemory()) return NULL;
    01084   }
    01085
    01086   ref<Image> img = new Image;
    01087   img->allocate3D( images[0]->width(), images[0]->height(), images.size(), 1, images[0]->format(), images[0]->type() );
    01088   VL_CHECK(img->requiredMemory() == images[0]->requiredMemory()*(int)images.size())
    01089   for(unsigned i=0; i<images.size(); ++i)
    01090   {
    01091     VL_CHECK(images[i]->pixels())
    01092     memcpy(img->pixelsZSlice(i), images[i]->pixels(), images[i]->requiredMemory());
    01093   }
    01094   return img;
    01095 }
    01096 //-----------------------------------------------------------------------------
    01097 bool vl::loadImagesFromDir(const String& dir_path, const String& ext, std::vector< ref<Image> >& images)
    01098 {
    01099   images.clear();
    01100   if (ext.empty() || dir_path.empty())
    01101     return false;
    01102   ref<VirtualDirectory> dir = defFileSystem()->locateDirectory(dir_path);
    01103   if (!dir)
    01104     return false;
    01105   std::vector<String> files;
    01106   dir->listFiles(files);
    01107   std::sort(files.begin(), files.end());
    01108   for(unsigned i=0; i<files.size(); ++i)
    01109   {
    01110     if (files[i].extractFileExtension().toLowerCase() == ext.toLowerCase())
    01111     {
    01112       images.push_back( loadImage(files[i]) );
    01113       if (images.back().get() == NULL)
    01114         return false;
    01115     }
    01116   }
    01117   return true;
    01118 }
    01119 //-----------------------------------------------------------------------------
    01120 ref<Image> vl::loadImage( const String& path )
    01121 {
    01122   ref<VirtualFile> file = defFileSystem()->locateFile(path);
    01123   if ( !file )
    01124   {
    01125     Log::error( Say("File '%s' not found.\n") << path );
    01126     return NULL;
    01127   }
    01128   else
    01129     return loadImage(file.get());
    01130 }
    01131 //-----------------------------------------------------------------------------
    01132 ref<Image> vl::loadImage( VirtualFile* file )
    01133 {
    01134   ref<ResourceDatabase> res_db = defLoadWriterManager()->loadResource(file);
    01135
    01136   if (!res_db)
    01137   {
    01138     Log::error( Say("vl::loadImage('%s') failed.\n") << file->path() );
    01139     return NULL;
    01140   }
    01141
    01142   ref<Image> img;
    01143
    01144   if (res_db->count<Image>())
    01145     img = res_db->get<Image>(0);
    01146
    01147   VL_CHECK( !file->isOpen() )
    01148   file->close();
    01149
    01150   if (img)
    01151     img->setObjectName( file->path().toStdString() );
    01152
    01153   return img;
    01154 }
    01155 //-----------------------------------------------------------------------------
    01156 bool vl::saveImage( Image* img, const String& path)
    01157 {
    01158   ref<ResourceDatabase> res_db = new ResourceDatabase;
    01159   res_db->resources().push_back(img);
    01160   bool ok = defLoadWriterManager()->writeResource(path, res_db.get());
    01161   if (!ok)
    01162     Log::error( Say("vl::saveImage('%s') failed.\n") << path );
    01163   return ok;
    01164 }
    01165 //-----------------------------------------------------------------------------
    01166 bool vl::saveImage( Image* img, VirtualFile* file )
    01167 {
    01168   ref<ResourceDatabase> res_db = new ResourceDatabase;
    01169   res_db->resources().push_back(img);
    01170   bool ok = defLoadWriterManager()->writeResource(file, res_db.get());
    01171   if (!ok)
    01172     Log::error( Say("vl::saveImage('%s') failed.\n") << file->path() );
    01173   return ok;
    01174 }
    01175 //-----------------------------------------------------------------------------
    01176 ref<Image> vl::loadCubemap(const String& xp_file, const String& xn_file, const String& yp_file, const String& yn_file, const String& zp_file, const String& zn_file)
    01177 {
    01178   ref<Image> xp = loadImage(xp_file);
    01179   ref<Image> xn = loadImage(xn_file);
    01180   ref<Image> yp = loadImage(yp_file);
    01181   ref<Image> yn = loadImage(yn_file);
    01182   ref<Image> zp = loadImage(zp_file);
    01183   ref<Image> zn = loadImage(zn_file);
    01184
    01185   if (!xp || !xn || !yp || !yn || !zp || !zn)
    01186   {
    01187     Log::error("vl::loadCubemap() failed.\n");
    01188     return NULL;
    01189   }
    01190
    01191   ref<Image> img = vl::createCubemap(xp.get(), xn.get(), yp.get(), yn.get(), zp.get(), zn.get());
    01192
    01193   return img;
    01194 }
    01195 //-----------------------------------------------------------------------------
    01196 ref<Image> vl::loadRAW(VirtualFile* file, long long file_offset, int width, int height, int depth, int bytealign, EImageFormat format, EImageType type)
    01197 {
    01198   ref<Image> img = new Image(width, height, depth, bytealign, format, type);
    01199   if ( file->isOpen() || file->open(OM_ReadOnly) )
    01200   {
    01201     bool ok = file_offset == -1 || file->seekSet(file_offset);
    01202     if (!ok)
    01203     {
    01204       Log::error( Say("loadRAW('%s'): seek set to position %n failed.\n") << file_offset );
    01205       return NULL;
    01206     }
    01207     int count = (int)file->read( img->pixels(), img->requiredMemory() );
    01208     if (count != img->requiredMemory())
    01209       Log::error( Say("loadRAW('%s'): error reading RAW file.\n") << file->path() );
    01210     return img;
    01211   }
    01212   else
    01213   {
    01214     Log::error( Say("loadRAW('%s'): could not open file for reading.\n") << file->path() );
    01215     return NULL;
    01216   }
    01217 }
    01218 //-----------------------------------------------------------------------------
    01219 ref<Image> vl::Image::convertType(EImageType new_type) const
    01220 {
    01221   switch(type())
    01222   {
    01223     case IT_UNSIGNED_BYTE:
    01224     case IT_BYTE:
    01225     case IT_UNSIGNED_SHORT:
    01226     case IT_SHORT:
    01227     case IT_UNSIGNED_INT:
    01228     case IT_INT:
    01229     case IT_FLOAT:
    01230       break;
    01231     default:
    01232       Log::error("Image::convertType(): unsupported source image type.\n");
    01233       return NULL;
    01234   }
    01235
    01236   switch(new_type)
    01237   {
    01238     case IT_UNSIGNED_BYTE:
    01239     case IT_BYTE:
    01240     case IT_UNSIGNED_SHORT:
    01241     case IT_SHORT:
    01242     case IT_UNSIGNED_INT:
    01243     case IT_INT:
    01244     case IT_FLOAT:
    01245       break;
    01246     default:
    01247       Log::error("Image::convertType(): unsupported destination image type.\n");
    01248       return NULL;
    01249   }
    01250
    01251   switch(format())
    01252   {
    01253     case IF_RGB:
    01254     case IF_RGBA:
    01255     case IF_BGR:
    01256     case IF_BGRA:
    01257     case IF_RED:
    01258     case IF_GREEN:
    01259     case IF_BLUE:
    01260     case IF_ALPHA:
    01261     case IF_LUMINANCE:
    01262     case IF_LUMINANCE_ALPHA:
    01263     case IF_DEPTH_COMPONENT:
    01264       break;
    01265     default:
    01266       Log::error("Image::convertType(): unsupported image format.\n");
    01267       return NULL;
    01268   }
    01269
    01270   ref<Image> img = new Image;
    01271   img->setObjectName( objectName() );
    01272   img->setFormat(format());
    01273   img->setType(new_type);
    01274   img->setWidth(width());
    01275   img->setHeight(height());
    01276   img->setDepth(depth());
    01277   img->setByteAlignment(1);
    01278   img->mIsCubemap = isCubemap();
    01279   img->allocate();
    01280
    01281   int components = 0;
    01282   switch(format())
    01283   {
    01284     case IF_RGB:   components = 3; break;
    01285     case IF_RGBA:  components = 4; break;
    01286     case IF_BGR:   components = 3; break;
    01287     case IF_BGRA:  components = 4; break;
    01288     case IF_RED:   components = 1; break;
    01289     case IF_GREEN: components = 1; break;
    01290     case IF_BLUE:  components = 1; break;
    01291     case IF_ALPHA: components = 1; break;
    01292     case IF_LUMINANCE:       components = 1; break;
    01293     case IF_LUMINANCE_ALPHA: components = 2; break;
    01294     case IF_DEPTH_COMPONENT: components = 1; break;
    01295     default:
    01296       break;
    01297   }
    01298
    01299   int line_count = img->height()?img->height():1;
    01300   if (img->depth())
    01301     line_count *= img->depth();
    01302   else
    01303   if (img->isCubemap())
    01304     line_count *= 6;
    01305
    01306   for(int i=0; i<line_count; ++i)
    01307   {
    01308     const void* srcLine = pixels()      + pitch()*i;
    01309     void* dstLine = img->pixels() + img->pitch()*i;
    01310
    01311     const unsigned char* srcUByte  = (const unsigned char*)srcLine;
    01312     const GLbyte*        srcSByte  = (const GLbyte*)srcLine;
    01313     const GLushort*      srcUShort = (const GLushort*)srcLine;
    01314     const GLshort*       srcSShort = (const GLshort*)srcLine;
    01315     const unsigned int*  srcUInt   = (const unsigned int*)srcLine;
    01316     const int*           srcSInt   = (const int*)srcLine;
    01317     const float*         srcFloat  = (const float*)srcLine;
    01318
    01319     unsigned char* dstUByte  = (unsigned char*)dstLine;
    01320     GLbyte*        dstSByte  = (GLbyte*)dstLine;
    01321     GLushort*      dstUShort = (GLushort*)dstLine;
    01322     GLshort*       dstSShort = (GLshort*)dstLine;
    01323     unsigned int*  dstUInt   = (unsigned int*)dstLine;
    01324     int*           dstSInt   = (int*)dstLine;
    01325     float*         dstFloat  = (float*)dstLine;
    01326
    01327     for(int j=0; j<img->width(); ++j)
    01328     {
    01329       for(int c=0; c<components; ++c)
    01330       {
    01331         double dval = 0;
    01332         long long qint = 0;
    01333
    01334         // convert dst format to double
    01335
    01336         switch(type())
    01337         {
    01338           case IT_UNSIGNED_BYTE:  qint = *srcUByte;  dval = qint/255.0; ++srcUByte; break;
    01339           case IT_BYTE:           qint = *srcSByte;  dval = qint/127.0; ++srcSByte; break;
    01340           case IT_UNSIGNED_SHORT: qint = *srcUShort; dval = qint/65535.0; ++srcUShort; break;
    01341           case IT_SHORT:          qint = *srcSShort; dval = qint/32767.0; ++srcSShort; break;
    01342           case IT_UNSIGNED_INT:   qint = *srcUInt;   dval = qint/4294967295.0; ++srcUInt; break;
    01343           case IT_INT:            qint = *srcSInt;   dval = qint/2147483647.0; ++srcSInt; break;
    01344           case IT_FLOAT:          dval = *srcFloat;  ++srcFloat; break;
    01345           default:
    01346             return NULL;
    01347         }
    01348
    01349         // clamp 0.0 >= dval >= 1.0
    01350         dval = dval < 0.0 ? 0.0 :
    01351                dval > 1.0 ? 1.0 :
    01352                dval;
    01353
    01354         // convert double to dst format
    01355
    01356         switch(img->type())
    01357         {
    01358           case IT_UNSIGNED_BYTE:  *dstUByte  = (unsigned char) (dval*255.0); ++dstUByte; break;
    01359           case IT_BYTE:           *dstSByte  = (GLbyte)  (dval*127.0); ++dstSByte; break;
    01360           case IT_UNSIGNED_SHORT: *dstUShort = (GLushort)(dval*65535.0); ++dstUShort; break;
    01361           case IT_SHORT:          *dstSShort = (GLshort) (dval*32767.0); ++dstSShort; break;
    01362           case IT_UNSIGNED_INT:   *dstUInt   = (unsigned int)  (dval*4294967295.0); ++dstUInt; break;
    01363           case IT_INT:            *dstSInt   = (int)   (dval*2147483647.0); ++dstSInt; break;
    01364           case IT_FLOAT:          *dstFloat  = (float)dval; ++dstFloat; break;
    01365           default:
    01366             return NULL;
    01367         }
    01368       }
    01369     }
    01370   }
    01371
    01372   return img;
    01373 }
    01374 //-----------------------------------------------------------------------------
    01375 namespace {
    01376   template<typename T>
    01377   void equalizeTemplate(void* ptr, int pitch, int comps, int w, int h, T max_val)
    01378   {
    01379     // find min/max
    01380     T vmin = *((T*)ptr);
    01381     T vmax = *((T*)ptr);
    01382     for(int y=0; y<h; ++y)
    01383     {
    01384       T* px = (T*)((char*)ptr + pitch*y);
    01385       for(int x=0; x<w; ++x)
    01386       {
    01387         for(int i=0; i<comps; ++i)
    01388         {
    01389           if (vmin > px[x*comps+i]) vmin = px[x*comps+i];
    01390           if (vmax < px[x*comps+i]) vmax = px[x*comps+i];
    01391         }
    01392       }
    01393     }
    01394     // equalize
    01395     T range = vmax-vmin;
    01396     for(int y=0; y<h; ++y)
    01397     {
    01398       T* px = (T*)((char*)ptr + pitch*y);
    01399       for(int x=0; x<w; ++x)
    01400       {
    01401         for(int i=0; i<comps; ++i)
    01402           px[x*comps+i] = (T)(((float)px[x*comps+i]-vmin)/range*max_val);
    01403       }
    01404     }
    01405   }
    01406 }
    01409 bool Image::equalize()
    01410 {
    01411   int comps = 0;
    01412   switch(format())
    01413   {
    01414     case IF_RGB:   comps = 3; break;
    01415     case IF_RGBA:  comps = 4; break;
    01416     case IF_BGR:   comps = 3; break;
    01417     case IF_BGRA:  comps = 4; break;
    01418     case IF_RED:   comps = 1; break;
    01419     case IF_GREEN: comps = 1; break;
    01420     case IF_BLUE:  comps = 1; break;
    01421     case IF_ALPHA: comps = 1; break;
    01422     case IF_LUMINANCE: comps = 1; break;
    01423     case IF_LUMINANCE_ALPHA: comps = 2; break;
    01424     case IF_DEPTH_COMPONENT: comps = 1; break;
    01425     default:
    01426       Log::error("Image::equalize(): unsupported image format().\n");
    01427       return false;
    01428   }
    01429   int w = width();
    01430   int h = height()?height():1;
    01431   int d = depth()?depth():1;
    01432   if (isCubemap())
    01433     h=h*6;
    01434   else
    01435     h=h*d;
    01436
    01437   switch(type())
    01438   {
    01439     case IT_UNSIGNED_BYTE:  equalizeTemplate<unsigned char> (pixels(), pitch(), comps, w, h, 0xFF);      break;
    01440     case IT_UNSIGNED_SHORT: equalizeTemplate<unsigned short>(pixels(), pitch(), comps, w, h, 0xFFFF);     break;
    01441     case IT_UNSIGNED_INT:   equalizeTemplate<unsigned int>  (pixels(), pitch(), comps, w, h, 0xFFFFFFFF); break;
    01442     case IT_FLOAT:          equalizeTemplate<float>         (pixels(), pitch(), comps, w, h, 1.0f);       break;
    01443       break;
    01444     default:
    01445       Log::error("Image::equalize(): unsupported image type(). Types supported are IT_UNSIGNED_BYTE, IT_UNSIGNED_SHORT, IT_UNSIGNED_INT, IT_FLOAT.\n");
    01446       return false;
    01447   }
    01448   return true;
    01449 }
    01450 //-----------------------------------------------------------------------------
    01471 bool Image::contrastHounsfieldAuto()
    01472 {
    01473   if ( !tags()->has("WindowCenter") || !tags()->has("WindowWidth") || !tags()->has("BitsStored") || !tags()->has("RescaleIntercept"))
    01474     return false;
    01475
    01476   float center    = tags()->value("WindowCenter").toFloat();
    01477   float width     = tags()->value("WindowWidth").toFloat();
    01478   float range     = (1<<tags()->value("BitsStored").toInt()) - 1.0f;
    01479   float intercept = tags()->value("RescaleIntercept").toFloat();
    01480   float slope     = tags()->value("RescaleSlope").toFloat();
    01481
    01482   // Hounsfield units: -1000 = air, +1000 = solid bone
    01483   // Transform from Hounsfield units to normalized 0..1 units
    01484   center = (center-intercept) / range / slope;
    01485   width  = width / range / slope;
    01486   return contrast( center-width/2.0f, center+width/2.0f );
    01487 }
    01488 //-----------------------------------------------------------------------------
    01499 bool Image::contrastHounsfield(float center, float width, float intercept, float range)
    01500 {
    01501   // Hounsfield units: -1000 = air, +1000 = solid bone
    01502   // Transform from Hounsfield units to normalized 0..1 units
    01503   center = (center-intercept) / range;
    01504   width  = width / range;
    01505   return contrast( center-width/2.0f, center+width/2.0f );
    01506 }
    01507 //-----------------------------------------------------------------------------
    01508 namespace {
    01509   template<typename T>
    01510   void contrastTemplate(void* ptr, int pitch, int w, int h, T max_val, float black, float white)
    01511   {
    01512     float range = white-black;
    01513     for(int y=0; y<h; ++y)
    01514     {
    01515       T* px = (T*)((char*)ptr + pitch*y);
    01516       for(int x=0; x<w; ++x)
    01517       {
    01518         float t = (float)px[x]/max_val; // 0..1
    01519         t = (t-black)/range;
    01520         t = vl::clamp(t, 0.0f, 1.0f);
    01521         px[x] = (T)(t*max_val);
    01522       }
    01523     }
    01524   }
    01525 }
    01528 bool Image::contrast(float black, float white)
    01529 {
    01530   switch(format())
    01531   {
    01532     case IF_RED:
    01533     case IF_GREEN:
    01534     case IF_BLUE:
    01535     case IF_ALPHA:
    01536     case IF_LUMINANCE:
    01537     case IF_DEPTH_COMPONENT:
    01538       break;
    01539     default:
    01540       Log::error("Image::equalize(): unsupported image format().\n");
    01541       return false;
    01542   }
    01543   int w = width();
    01544   int h = height()?height():1;
    01545   int d = depth()?depth():1;
    01546   if (isCubemap())
    01547     h=h*6;
    01548   else
    01549     h=h*d;
    01550
    01551   switch(type())
    01552   {
    01553     case IT_UNSIGNED_BYTE:  contrastTemplate<unsigned char> (pixels(), pitch(), w, h, 0xFF, black, white);       break;
    01554     case IT_UNSIGNED_SHORT: contrastTemplate<unsigned short>(pixels(), pitch(), w, h, 0xFFFF, black, white);     break;
    01555     case IT_UNSIGNED_INT:   contrastTemplate<unsigned int>  (pixels(), pitch(), w, h, 0xFFFFFFFF, black, white); break;
    01556     case IT_FLOAT:          contrastTemplate<float>         (pixels(), pitch(), w, h, 1.0f, black, white);       break;
    01557       break;
    01558     default:
    01559       Log::error("Image::equalize(): unsupported image type(). Types supported are IT_UNSIGNED_BYTE, IT_UNSIGNED_SHORT, IT_UNSIGNED_INT, IT_FLOAT.\n");
    01560       return false;
    01561   }
    01562   return true;
    01563 }
    01564 //-----------------------------------------------------------------------------
    01565 namespace
    01566 {
    01567   class rgbal
    01568   {
    01569   public:
    01570     rgbal(): r(-1), g(-1), b(-1), a(-1), l(-1) {}
    01571     int r,g,b,a,l;
    01572   };
    01573
    01574   template<typename T>
    01575   void convert(const T*src_px, T*dst_px, T max_value, const rgbal& srco, const rgbal& dsto)
    01576   {
    01577     // set dst default values first
    01578     if (dsto.r != -1)
    01579       dst_px[dsto.r] = 0;
    01580     if (dsto.g != -1)
    01581       dst_px[dsto.g] = 0;
    01582     if (dsto.b != -1)
    01583       dst_px[dsto.b] = 0;
    01584     if (dsto.a != -1)
    01585       dst_px[dsto.a] = max_value;
    01586     if (dsto.l != -1)
    01587       dst_px[dsto.l] = 0;
    01588
    01589     // try copy src -> dst
    01590     if (dsto.r != -1 && srco.r != -1 )
    01591       dst_px[dsto.r] = src_px[srco.r];
    01592     if (dsto.g != -1 && srco.g != -1)
    01593       dst_px[dsto.g] = src_px[srco.g];
    01594     if (dsto.b != -1 && srco.b != -1)
    01595       dst_px[dsto.b] = src_px[srco.b];
    01596     if (dsto.a != -1 && srco.a != -1)
    01597       dst_px[dsto.a] = src_px[srco.a];
    01598     if (dsto.l != -1 && srco.l != -1)
    01599       dst_px[dsto.l] = src_px[srco.l];
    01600
    01601     // try rgb -> gray conversion
    01602     if (dsto.l != -1 && srco.r != -1 && srco.g != -1 && srco.b != -1)
    01603     {
    01604       dvec3 col(src_px[srco.r], src_px[srco.g], src_px[srco.b]);
    01605       double gray = dot(col / dvec3(max_value,max_value,max_value), dvec3(0.299,0.587,0.114));
    01606       dst_px[dsto.l] = T(gray * max_value);
    01607     }
    01608     else
    01609     // try r -> gray conversion
    01610     if (dsto.l != -1 && srco.r != -1 && srco.g == -1 && srco.b == -1)
    01611       dst_px[dsto.l] = src_px[srco.r];
    01612     else
    01613     // try g -> gray conversion
    01614     if (dsto.l != -1 && srco.r == -1 && srco.g != -1 && srco.b == -1)
    01615       dst_px[dsto.l] = src_px[srco.g];
    01616     else
    01617     // try b -> gray conversion
    01618     if (dsto.l != -1 && srco.r == -1 && srco.g == -1 && srco.b != -1)
    01619       dst_px[dsto.l] = src_px[srco.b];
    01620     else
    01621     // try gray -> r,g,b
    01622     if (srco.l != -1)
    01623     {
    01624       if (dsto.r != -1)
    01625         dst_px[dsto.r] = src_px[srco.l];
    01626       if (dsto.g != -1)
    01627         dst_px[dsto.g] = src_px[srco.l];
    01628       if (dsto.b != -1)
    01629         dst_px[dsto.b] = src_px[srco.l];
    01630     }
    01631   }
    01632 }
    01633 ref<Image> vl::Image::convertFormat(EImageFormat new_format) const
    01634 {
    01635   switch(type())
    01636   {
    01637     case IT_UNSIGNED_BYTE:
    01638     case IT_BYTE:
    01639     case IT_UNSIGNED_SHORT:
    01640     case IT_SHORT:
    01641     case IT_UNSIGNED_INT:
    01642     case IT_INT:
    01643     case IT_FLOAT:
    01644       break;
    01645     default:
    01646       Log::error("Image::convertType(): unsupported image type.\n");
    01647       return NULL;
    01648   }
    01649
    01650   switch(format())
    01651   {
    01652     case IF_RGB:
    01653     case IF_RGBA:
    01654     case IF_BGR:
    01655     case IF_BGRA:
    01656     case IF_RED:
    01657     case IF_GREEN:
    01658     case IF_BLUE:
    01659     case IF_ALPHA:
    01660     case IF_LUMINANCE:
    01661     case IF_LUMINANCE_ALPHA:
    01662       break;
    01663     default:
    01664       Log::error("Image::convertType(): unsupported source image format.\n");
    01665       return NULL;
    01666   }
    01667
    01668   switch(new_format)
    01669   {
    01670     case IF_RGB:
    01671     case IF_RGBA:
    01672     case IF_BGR:
    01673     case IF_BGRA:
    01674     case IF_RED:
    01675     case IF_GREEN:
    01676     case IF_BLUE:
    01677     case IF_ALPHA:
    01678     case IF_LUMINANCE:
    01679     case IF_LUMINANCE_ALPHA:
    01680       break;
    01681     default:
    01682       Log::error("Image::convertType(): unsupported destination image format.\n");
    01683       return NULL;
    01684   }
    01685
    01686   ref<Image> img = new Image;
    01687   img->setObjectName( objectName() );
    01688   img->setFormat(new_format);
    01689   img->setType(type());
    01690   img->setWidth(width());
    01691   img->setHeight(height());
    01692   img->setDepth(depth());
    01693   img->setByteAlignment(1);
    01694   img->mIsCubemap = isCubemap();
    01695   img->allocate();
    01696
    01697   rgbal srco; // = {-1,-1,-1,-1,-1},
    01698   rgbal dsto; // = {-1,-1,-1,-1,-1};
    01699
    01700   // compute src and dst color component offsets
    01701
    01702   switch(format())
    01703   {
    01704     case IF_RGB:             srco.r = 0; srco.g = 1; srco.b = 2; break;
    01705     case IF_RGBA:            srco.r = 0; srco.g = 1; srco.b = 2; srco.a = 3; break;
    01706     case IF_BGR:             srco.r = 2; srco.g = 1; srco.b = 0; break;
    01707     case IF_BGRA:            srco.r = 2; srco.g = 1; srco.b = 0; srco.a = 3; break;
    01708     case IF_RED:             srco.r = 0; break;
    01709     case IF_GREEN:           srco.g = 0; break;
    01710     case IF_BLUE:            srco.b = 0; break;
    01711     case IF_ALPHA:           srco.a = 0; break;
    01712     case IF_LUMINANCE:       srco.l = 0; break;
    01713     case IF_LUMINANCE_ALPHA: srco.l = 0; srco.a = 1; break;
    01714     default:
    01715       return NULL;
    01716   }
    01717
    01718   switch(new_format)
    01719   {
    01720     case IF_RGB:             dsto.r = 0; dsto.g = 1; dsto.b = 2; break;
    01721     case IF_RGBA:            dsto.r = 0; dsto.g = 1; dsto.b = 2; dsto.a = 3; break;
    01722     case IF_BGR:             dsto.r = 2; dsto.g = 1; dsto.b = 0; break;
    01723     case IF_BGRA:            dsto.r = 2; dsto.g = 1; dsto.b = 0; dsto.a = 3; break;
    01724     case IF_RED:             dsto.r = 0; break;
    01725     case IF_GREEN:           dsto.g = 0; break;
    01726     case IF_BLUE:            dsto.b = 0; break;
    01727     case IF_ALPHA:           dsto.a = 0; break;
    01728     case IF_LUMINANCE:       dsto.l = 0; break;
    01729     case IF_LUMINANCE_ALPHA: dsto.l = 0; dsto.a = 1; break;
    01730     default:
    01731       return NULL;
    01732   }
    01733
    01734   int src_comp = 0;
    01735   switch(format())
    01736   {
    01737     case IF_RGB:   src_comp = 3; break;
    01738     case IF_RGBA:  src_comp = 4; break;
    01739     case IF_BGR:   src_comp = 3; break;
    01740     case IF_BGRA:  src_comp = 4; break;
    01741     case IF_RED:   src_comp = 1; break;
    01742     case IF_GREEN: src_comp = 1; break;
    01743     case IF_BLUE:  src_comp = 1; break;
    01744     case IF_ALPHA: src_comp = 1; break;
    01745     case IF_LUMINANCE:       src_comp = 1; break;
    01746     case IF_LUMINANCE_ALPHA: src_comp = 2; break;
    01747     default:
    01748       break;
    01749   }
    01750
    01751   int dst_comp = 0;
    01752   switch(new_format)
    01753   {
    01754     case IF_RGB:   dst_comp = 3; break;
    01755     case IF_RGBA:  dst_comp = 4; break;
    01756     case IF_BGR:   dst_comp = 3; break;
    01757     case IF_BGRA:  dst_comp = 4; break;
    01758     case IF_RED:   dst_comp = 1; break;
    01759     case IF_GREEN: dst_comp = 1; break;
    01760     case IF_BLUE:  dst_comp = 1; break;
    01761     case IF_ALPHA: dst_comp = 1; break;
    01762     case IF_LUMINANCE:       dst_comp = 1; break;
    01763     case IF_LUMINANCE_ALPHA: dst_comp = 2; break;
    01764     case IF_DEPTH_COMPONENT: dst_comp = 1; break;
    01765     default:
    01766       break;
    01767   }
    01768
    01769   int line_count = img->height()?img->height():1;
    01770   if (img->depth())
    01771     line_count *= img->depth();
    01772   else
    01773   if (img->isCubemap())
    01774     line_count *= 6;
    01775
    01776   for(int i=0; i<line_count; ++i)
    01777   {
    01778     const void* srcLine = pixels()      + pitch()*i;
    01779     void* dstLine = img->pixels() + img->pitch()*i;
    01780
    01781     const unsigned char* srcUByte  = (const unsigned char*)srcLine;
    01782     const GLbyte*        srcSByte  = (const GLbyte*)srcLine;
    01783     const GLushort*      srcUShort = (const GLushort*)srcLine;
    01784     const GLshort*       srcSShort = (const GLshort*)srcLine;
    01785     const unsigned int*  srcUInt   = (const unsigned int*)srcLine;
    01786     const int*           srcSInt   = (const int*)srcLine;
    01787     const float*         srcFloat  = (const float*)srcLine;
    01788
    01789     unsigned char* dstUByte  = (unsigned char*)dstLine;
    01790     GLbyte*        dstSByte  = (GLbyte*)dstLine;
    01791     GLushort*      dstUShort = (GLushort*)dstLine;
    01792     GLshort*       dstSShort = (GLshort*)dstLine;
    01793     unsigned int*  dstUInt   = (unsigned int*)dstLine;
    01794     int*           dstSInt   = (int*)dstLine;
    01795     float*         dstFloat  = (float*)dstLine;
    01796
    01797     for(int j=0; j<img->width(); ++j)
    01798     {
    01799       switch(type())
    01800       {
    01801         case IT_UNSIGNED_BYTE:  convert<unsigned char> (srcUByte,  dstUByte,  255,         srco, dsto); srcUByte+=src_comp;  dstUByte+=dst_comp;  break;
    01802         case IT_BYTE:           convert<GLbyte>        (srcSByte,  dstSByte,  127,         srco, dsto); srcSByte+=src_comp;  dstSByte+=dst_comp;  break;
    01803         case IT_UNSIGNED_SHORT: convert<GLushort>      (srcUShort, dstUShort, 65535,       srco, dsto); srcUShort+=src_comp; dstUShort+=dst_comp; break;
    01804         case IT_SHORT:          convert<GLshort>       (srcSShort, dstSShort, 32767,       srco, dsto); srcSShort+=src_comp; dstSShort+=dst_comp; break;
    01805         case IT_UNSIGNED_INT:   convert<unsigned int>  (srcUInt,   dstUInt,   4294967295U, srco, dsto); srcUInt+=src_comp;   dstUInt+=dst_comp;   break;
    01806         case IT_INT:            convert<int>           (srcSInt,   dstSInt,   2147483647,  srco, dsto); srcSInt+=src_comp;   dstSInt+=dst_comp;   break;
    01807         case IT_FLOAT:          convert<float>         (srcFloat,  dstFloat,  1.0f,        srco, dsto); srcFloat+=src_comp;  dstFloat+=dst_comp;  break;
    01808         default:
    01809           return NULL;
    01810       }
    01811     }
    01812   }
    01813
    01814   return img;
    01815 }
    01816 //-----------------------------------------------------------------------------
    01817 fvec4 Image::sampleLinear(double x) const
    01818 {
    01819   if (x < 0)
    01820     x = 0;
    01821   if (x >= width()-1)
    01822     x = (width()-1) - 0.000001;
    01823
    01824   int ix1 = (int)x;
    01825   int ix2 = ix1+1;
    01826
    01827   VL_CHECK(ix2<(int)width())
    01828
    01829   float w21 = (float)vl::fract(x);
    01830   float w11 = 1.0f - w21;
    01831
    01832   fvec4 c11 = sample(ix1);
    01833   fvec4 c21 = sample(ix2);
    01834
    01835   return c11*w11 + c21*w21;
    01836 }
    01837 //-----------------------------------------------------------------------------
    01838 fvec4 Image::sampleLinear(double x, double y) const
    01839 {
    01840   int h = height()?height():1;
    01841   if (x < 0)
    01842     x = 0;
    01843   if (y < 0)
    01844     y = 0;
    01845   if (x >= width()-1)
    01846     x = (width()-1)  - 0.000001;
    01847   if (y >= h-1)
    01848     y = (h-1) - 0.000001;
    01849
    01850   int ix1 = (int)x;
    01851   int iy1 = (int)y;
    01852   int ix2 = ix1+1;
    01853   int iy2 = iy1+1;
    01854
    01855   VL_CHECK(ix2<(int)width())
    01856   VL_CHECK(iy2<(int)height())
    01857
    01858   double tx  = vl::fract(x);
    01859   double ty  = vl::fract(y);
    01860   double tx1 = 1.0f - vl::fract(x);
    01861   double ty1 = 1.0f - vl::fract(y);
    01862
    01863   float w11 = float(tx1*ty1);
    01864   float w12 = float(tx1*ty);
    01865   float w22 = float(tx *ty);
    01866   float w21 = float(tx *ty1);
    01867
    01868   fvec4 c11 = sample(ix1, iy1);
    01869   fvec4 c12 = sample(ix1, iy2);
    01870   fvec4 c22 = sample(ix2, iy2);
    01871   fvec4 c21 = sample(ix2, iy1);
    01872
    01873   return c11*w11 + c12*w12 + c22*w22 + c21*w21;
    01874 }
    01875 //-----------------------------------------------------------------------------
    01876 fvec4 Image::sampleLinear(double x, double y, double z) const
    01877 {
    01878   if (x>width() -1.000001) x = width() -1.000001;
    01879   if (y>height()-1.000001) y = height()-1.000001;
    01880   if (z>depth() -1.000001) z = depth() -1.000001;
    01881   if (x<0) x=0;
    01882   if (y<0) y=0;
    01883   if (z<0) z=0;
    01884   int ix = int(x);
    01885   float xt = float(x - ix);
    01886   int iy = int(y);
    01887   float yt = float(y - iy);
    01888   int iz = int(z);
    01889   float zt = float(z - iz);
    01890   fvec4 val0 = sample(ix  , iy,   iz);
    01891   fvec4 val1 = sample(ix+1, iy,   iz);
    01892   fvec4 val2 = sample(ix+1, iy+1, iz);
    01893   fvec4 val3 = sample(ix,   iy+1, iz);
    01894   fvec4 val4 = sample(ix  , iy,   iz+1);
    01895   fvec4 val5 = sample(ix+1, iy,   iz+1);
    01896   fvec4 val6 = sample(ix+1, iy+1, iz+1);
    01897   fvec4 val7 = sample(ix,   iy+1, iz+1);
    01898   float xt1 = 1-xt;
    01899   float yt1 = 1-yt;
    01900   float zt1 = 1-zt;
    01901   fvec4 v1 = val0*(yt1) + val3*yt;
    01902   fvec4 v2 = val1*(yt1) + val2*yt;
    01903   fvec4 a = v1*(xt1) + v2*xt;
    01904   v1 = val4*(yt1) + val7*yt;
    01905   v2 = val5*(yt1) + val6*yt;
    01906   fvec4 b = v1*(xt1) + v2*xt;
    01907   return a*(zt1) + b*zt;
    01908 }
    01909 //-----------------------------------------------------------------------------
    01910 fvec4 Image::sample(int x, int y, int z) const
    01911 {
    01912   VL_CHECK(x<width())
    01913   VL_CHECK(!y || y<height())
    01914   VL_CHECK(!z || z<depth())
    01915
    01916   // find the start of the line
    01917   int h = height()?height():1;
    01918   const unsigned char* px = pixels() + y*pitch() + h*pitch()*z;
    01919
    01920   int comp = 0;
    01921   switch(format())
    01922   {
    01923     case IF_RGB:   comp = 3; break;
    01924     case IF_RGBA:  comp = 4; break;
    01925     case IF_BGR:   comp = 3; break;
    01926     case IF_BGRA:  comp = 4; break;
    01927     case IF_RED:   comp = 1; break;
    01928     case IF_GREEN: comp = 1; break;
    01929     case IF_BLUE:  comp = 1; break;
    01930     case IF_ALPHA: comp = 1; break;
    01931     case IF_LUMINANCE:       comp = 1; break;
    01932     case IF_LUMINANCE_ALPHA: comp = 2; break;
    01933     case IF_DEPTH_COMPONENT: comp = 1; break;
    01934     default:
    01935       break;
    01936   }
    01937
    01938   switch(type())
    01939   {
    01940     case IT_UNSIGNED_BYTE:  px += x*comp*1; break;
    01941     case IT_BYTE:           px += x*comp*1; break;
    01942     case IT_UNSIGNED_SHORT: px += x*comp*2; break;
    01943     case IT_SHORT:          px += x*comp*2; break;
    01944     case IT_UNSIGNED_INT:   px += x*comp*4; break;
    01945     case IT_INT:            px += x*comp*4; break;
    01946     case IT_FLOAT:          px += x*comp*4; break;
    01947     default:
    01948       break;
    01949   }
    01950
    01951   // convert component by component
    01952
    01953   fvec4 pixel(0,0,0,0);
    01954
    01955   for(int i=0; i<comp; ++i)
    01956   {
    01957     double value = 0;
    01958
    01959     switch(type())
    01960     {
    01961       case IT_UNSIGNED_BYTE:  value = (double)((unsigned char*)px)[i]; value/=255.0; break;
    01962       case IT_BYTE:           value = (double)((char*)px)[i]; value/=127.0; break;
    01963       case IT_UNSIGNED_SHORT: value = (double)((unsigned short*)px)[i]; value/=65535.0; break;
    01964       case IT_SHORT:          value = (double)((short*)px)[i]; value/=32767.0; break;
    01965       case IT_UNSIGNED_INT:   value = (double)((unsigned int*)px)[i]; value/=4294967295.0; break;
    01966       case IT_INT:            value = (double)((int*)px)[i]; value/=2147483647.0; break;
    01967       case IT_FLOAT:          value = (double)((float*)px)[i]; break;
    01968       default:
    01969         break;
    01970     }
    01971
    01972     pixel[i] = (float)value;
    01973   }
    01974
    01975   fvec4 p(0,0,0,0);
    01976
    01977   // arrange values based on the format
    01978   switch(format())
    01979   {
    01980     case IF_RGB:   p = pixel; break;
    01981     case IF_RGBA:  p = pixel; break;
    01982     case IF_BGR:   p = pixel; p.r() = pixel.b(); p.b() = pixel.r(); break;
    01983     case IF_BGRA:  p = pixel; p.r() = pixel.b(); p.b() = pixel.r(); break;
    01984     case IF_RED:   p = fvec4(pixel[0], 0, 0, 0); break;
    01985     case IF_GREEN: p = fvec4(0, pixel[0], 0, 0); break;
    01986     case IF_BLUE:  p = fvec4(0, 0, pixel[0], 0); break;
    01987     case IF_ALPHA: p = fvec4(0, 0, 0, pixel[0]); break;
    01988     case IF_LUMINANCE:       p = fvec4(pixel[0], pixel[0], pixel[0], 0); break;
    01989     case IF_LUMINANCE_ALPHA: p = fvec4(pixel[0], pixel[0], pixel[0], pixel[1]); break;
    01990     case IF_DEPTH_COMPONENT: p = fvec4(pixel[0], 0, 0, 0); break;
    01991     default:
    01992       break;
    01993   }
    01994
    01995   return p;
    01996 }
    01997 //-----------------------------------------------------------------------------
    01998 ref<Image> Image::subImage(int xstart, int ystart, int width, int height)
    01999 {
    02000   VL_CHECK(xstart+width  <= this->width())
    02001   VL_CHECK(ystart+height <= this->height())
    02002
    02003   ref<Image> img = new Image;
    02004   img->allocate2D(width, height, 1, format(), type());
    02005   // copy line by line
    02006   for(int i=0; i<height; ++i)
    02007   {
    02008     unsigned char* dst = img->pixels() + img->pitch()*i;
    02009     unsigned char* src = pixels() + pitch()*(i+ystart) + xstart*bitsPerPixel()/8;
    02010     memcpy(dst, src, width*bitsPerPixel()/8);
    02011   }
    02012   return img;
    02013 }
    02014 //-----------------------------------------------------------------------------
    02015 void Image::copySubImage(Image* img_src, RectI src, ivec2 dst)
    02016 {
    02017   ref<Image> img = img_src;
    02018   if (img->type() != this->type())
    02019     img = img->convertType(this->type());
    02020   if (img->format() != this->format())
    02021     img = img->convertFormat(this->format());
    02022   // tests
    02023   VL_CHECK(dst.x()>=0)
    02024   VL_CHECK(dst.y()>=0)
    02025   VL_CHECK(dst.x() + src.width()  <= this->width() )
    02026   VL_CHECK(dst.y() + src.height() <= this->height())
    02027   VL_CHECK(src.x()>=0)
    02028   VL_CHECK(src.y()>=0)
    02029   VL_CHECK(src.right() < img->width() )
    02030   VL_CHECK(src.top()   < img->height())
    02031   for(int i=0; i<src.height(); ++i)
    02032   {
    02033     int ysrc = i+src.y();
    02034     int ydst = i+dst.y();
    02035     unsigned char* psrc = img->pixels() + img->pitch()*ysrc + (src.x()*img->bitsPerPixel()/8);
    02036     unsigned char* pdst = this->pixels() + this->pitch()*ydst + (dst.x()*this->bitsPerPixel()/8);
    02037     memcpy(pdst, psrc, src.width()*this->bitsPerPixel()/8);
    02038   }
    02039 }
    02040 //-----------------------------------------------------------------------------
    02041 void Image::substituteColorRGB_RGBA(unsigned int before, unsigned int after)
    02042 {
    02043   if (type() != IT_UNSIGNED_BYTE)
    02044   {
    02045     Log::error("Image::substituteColorRGB_RGBA(): this function can be called only on images whose type() is IT_UNSIGNED_BYTE\n");
    02046     return;
    02047   }
    02048   if (format() != IF_RGBA && format() != IF_RGB)
    02049   {
    02050     Log::error("Image::substituteColorRGB_RGBA(): this function can be called only on images whose format() is either IF_RGBA or IF_RGB\n");
    02051     return;
    02052   }
    02053   unsigned char bef[3];
    02054   unsigned char aft[4];
    02055   bef[0] = (unsigned char)((before >> 16) & 0xFF);
    02056   bef[1] = (unsigned char)((before >>  8) & 0xFF);
    02057   bef[2] = (unsigned char)((before >>  0) & 0xFF);
    02058
    02059   aft[0] = (unsigned char)((after  >> 24) & 0xFF);
    02060   aft[1] = (unsigned char)((after  >> 16) & 0xFF);
    02061   aft[2] = (unsigned char)((after  >>  8) & 0xFF);
    02062   aft[3] = (unsigned char)((after  >>  0) & 0xFF);
    02063
    02064   int comps = format() == IF_RGBA ? 4 : 3;
    02065   int d = depth() ? depth() : 1;
    02066   for(int y=0; y<height()*d; ++y)
    02067   {
    02068     for(int x=0; x<width(); ++x)
    02069     {
    02070       unsigned char* px = pixels() + pitch()*y + x*comps;
    02071       if (px[0] == bef[0] && px[1] == bef[1] && px[2] == bef[2])
    02072       {
    02073         px[0] = aft[0];
    02074         px[1] = aft[1];
    02075         px[2] = aft[2];
    02076         if (comps == 4)
    02077           px[3] = aft[3];
    02078       }
    02079     }
    02080   }
    02081 }
    02082 //-----------------------------------------------------------------------------
    02083 void Image::substituteColorRGB_RGB(unsigned int before, unsigned int after)
    02084 {
    02085   if (type() != IT_UNSIGNED_BYTE)
    02086   {
    02087     Log::error("Image::substituteColorRGB_RGB(): this function can be called only on images whose type() is IT_UNSIGNED_BYTE\n");
    02088     return;
    02089   }
    02090   if (format() != IF_RGBA && format() != IF_RGB)
    02091   {
    02092     Log::error("Image::substituteColorRGB_RGB(): this function can be called only on images whose format() is either IF_RGBA or IF_RGB\n");
    02093     return;
    02094   }
    02095   unsigned char bef[3];
    02096   unsigned char aft[3];
    02097   bef[0] = (unsigned char)((before >> 16) & 0xFF);
    02098   bef[1] = (unsigned char)((before >>  8) & 0xFF);
    02099   bef[2] = (unsigned char)((before >>  0) & 0xFF);
    02100
    02101   aft[0] = (unsigned char)((after  >> 24) & 0xFF);
    02102   aft[1] = (unsigned char)((after  >> 16) & 0xFF);
    02103   aft[2] = (unsigned char)((after  >>  8) & 0xFF);
    02104
    02105   int comps = format() == IF_RGBA ? 4 : 3;
    02106   int d = depth() ? depth() : 1;
    02107   for(int y=0; y<height()*d; ++y)
    02108   {
    02109     for(int x=0; x<width(); ++x)
    02110     {
    02111       unsigned char* px = pixels() + pitch()*y + x*comps;
    02112       if (px[0] == bef[0] && px[1] == bef[1] && px[2] == bef[2])
    02113       {
    02114         px[0] = aft[0];
    02115         px[1] = aft[1];
    02116         px[2] = aft[2];
    02117       }
    02118     }
    02119   }
    02120 }
    02121 //-----------------------------------------------------------------------------
    02122 void Image::substituteColorGreenKey(unsigned int col0, unsigned int col1)
    02123 {
    02124   if (type() != IT_UNSIGNED_BYTE)
    02125   {
    02126     Log::error("Image::substituteColorRGB_RGB(): this function can be called only on images whose type() is IT_UNSIGNED_BYTE\n");
    02127     return;
    02128   }
    02129   if (format() != IF_RGBA && format() != IF_RGB)
    02130   {
    02131     Log::error("Image::substituteColorRGB_RGB(): this function can be called only on images whose format() is either IF_RGBA or IF_RGB\n");
    02132     return;
    02133   }
    02134   unsigned char c0[3];
    02135   unsigned char c1[3];
    02136   c0[0] = (unsigned char)((col0 >> 16) & 0xFF);
    02137   c0[1] = (unsigned char)((col0 >>  8) & 0xFF);
    02138   c0[2] = (unsigned char)((col0 >>  0) & 0xFF);
    02139
    02140   c1[0] = (unsigned char)((col1 >> 16) & 0xFF);
    02141   c1[1] = (unsigned char)((col1 >>  8) & 0xFF);
    02142   c1[2] = (unsigned char)((col1 >>  0) & 0xFF);
    02143
    02144   int comps = format() == IF_RGBA ? 4 : 3;
    02145   int d = depth() ? depth() : 1;
    02146   for(int y=0; y<height()*d; ++y)
    02147   {
    02148     for(int x=0; x<width(); ++x)
    02149     {
    02150       unsigned char* px = pixels() + pitch()*y + x*comps;
    02151       double t = (double)px[1] / 0xFF;
    02152       px[0] = (unsigned char)(c0[0]*(1.0-t) + c1[0]*t);
    02153       px[1] = (unsigned char)(c0[1]*(1.0-t) + c1[1]*t);
    02154       px[2] = (unsigned char)(c0[2]*(1.0-t) + c1[2]*t);
    02155     }
    02156   }
    02157 }
    02158 //-----------------------------------------------------------------------------

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