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