00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
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
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
00136
00137 bool okformat = false;
00138
00139
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
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
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
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:
00231 case IT_UNSIGNED_INT_10F_11F_11F_REV:
00232 {
00233 okformat = true;
00234 break;
00235 }
00236
00237 default:
00238 {
00239 break;
00240 }
00241 }
00242 break;
00243 }
00244
00245
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;
00404 case IT_UNSIGNED_INT_10F_11F_11F_REV: return 32;
00405 case IT_UNSIGNED_INT_24_8: return 32;
00406 case IT_FLOAT_32_UNSIGNED_INT_24_8_REV: return 64;
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
00426
00427 case IF_COMPRESSED_RGB_S3TC_DXT1: return 4;
00428 case IF_COMPRESSED_RGBA_S3TC_DXT1: return 4;
00429 case IF_COMPRESSED_RGBA_S3TC_DXT3: return 8;
00430 case IF_COMPRESSED_RGBA_S3TC_DXT5: return 8;
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
00461
00462 case IF_COMPRESSED_RGB_S3TC_DXT1: return 0;
00463 case IF_COMPRESSED_RGBA_S3TC_DXT1: return 1;
00464 case IF_COMPRESSED_RGBA_S3TC_DXT3: return 4;
00465 case IF_COMPRESSED_RGBA_S3TC_DXT5: return 4;
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;
00496 case IT_UNSIGNED_INT_10F_11F_11F_REV: return 0;
00497 case IT_UNSIGNED_INT_24_8: return 0;
00498 case IT_FLOAT_32_UNSIGNED_INT_24_8_REV: return 0;
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
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
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
00686 *mPixels = *other.mPixels;
00687
00688
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
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
00834
00835
00836
00837
00838
00839 const Image* img[] = {xp, xn, yp, yn, zp, zn};
00840
00841
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
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
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
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
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
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
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
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
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
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
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
00999
01000 height = height ? height : 1;
01001 depth = depth ? depth : 1;
01002 int req_mem = pitch * height * depth;
01003
01004
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
01018
01019
01020
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
01058
01059
01060
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
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
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
01402 dval = dval < 0.0 ? 0.0 :
01403 dval > 1.0 ? 1.0 :
01404 dval;
01405
01406
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
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
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
01535
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
01554
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;
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
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
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
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
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
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
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
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;
01752 rgbal dsto;
01753
01754
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
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
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
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
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
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