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