Visualization Library 2.0.0-b3

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

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
Image.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2017, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include <vlCore/Image.hpp>
33 #include <vlCore/checks.hpp>
34 #include <vlCore/Say.hpp>
35 #include <vlCore/Log.hpp>
37 #include <vlCore/FileSystem.hpp>
38 #include <vlCore/VirtualFile.hpp>
39 #include <vlCore/glsl_math.hpp>
42 
43 #include <map>
44 #include <cmath>
45 
46 using namespace vl;
47 
48 //-----------------------------------------------------------------------------
49 // Image
50 //-----------------------------------------------------------------------------
52 {
53  reset();
54 }
55 //-----------------------------------------------------------------------------
57 {
58  VL_DEBUG_SET_OBJECT_NAME()
59  mPixels = new Buffer;
60  reset();
61 }
62 //-----------------------------------------------------------------------------
63 Image::Image( void* buffer_ptr, int buffer_bytes )
64 {
65  VL_DEBUG_SET_OBJECT_NAME()
66  mPixels = new Buffer;
67  reset();
68  mPixels->setUserAllocatedBuffer( buffer_ptr, buffer_bytes );
69 }
70 //-----------------------------------------------------------------------------
71 Image::Image( const Image& other ): Object( other )
72 {
73  VL_DEBUG_SET_OBJECT_NAME()
74  mPixels = new Buffer;
75  reset();
76  *this = other;
77 }
78 //-----------------------------------------------------------------------------
79 Image::Image( const String& path )
80 {
81  VL_DEBUG_SET_OBJECT_NAME()
82  mPixels = new Buffer;
83  reset();
84 
85  setObjectName(path.toStdString().c_str());
86  ref<Image> img = loadImage(path);
87  if (!img)
88  {
89  mFilePath = path;
90  return;
91  }
92  // quicker than *this = *img;
93  mPixels->swap(*img->mPixels);
94  mMipmaps.swap(img->mMipmaps);
95  mWidth = img->mWidth;
96  mHeight = img->mHeight;
97  mDepth = img->mDepth;
98  mPitch = img->mPitch;
99  mByteAlign = img->mByteAlign;
100  mFormat = img->mFormat;
101  mType = img->mType;
102  mIsCubemap = img->mIsCubemap;
103  mIsNormalMap = img->mIsNormalMap;
104  mHasAlpha = img->mHasAlpha;
105  mFilePath = img->mFilePath;
106 }
107 //-----------------------------------------------------------------------------
109 Image::Image( int x, int y, int z, int bytealign, EImageFormat format, EImageType type ):
110  mWidth(x), mHeight(y), mDepth(z), mPitch(0), mByteAlign(1), mFormat(format), mType(type), mIsCubemap(false), mIsNormalMap(false), mHasAlpha(false)
111 {
112  VL_DEBUG_SET_OBJECT_NAME()
113  mPixels = new Buffer;
114  setByteAlignment(bytealign);
115 
116  if (x && y && z)
117  allocate3D(x,y,z,bytealign,format,type);
118  else
119  if (x && y)
120  allocate2D(x,y,bytealign,format,type);
121  else
122  if (x)
123  allocate1D(x,format,type);
124 }
125 //-----------------------------------------------------------------------------
135 bool Image::isValid() const
136 {
137  // size check
138 
139  bool x = mWidth > 0 && mHeight == 0 && mDepth == 0;
140  bool y = mWidth > 0 && mHeight > 0 && mDepth == 0;
141  bool z = mWidth > 0 && mHeight > 0 && mDepth > 0;
142 
143  // format check
144 
145  bool okformat = false;
146 
147  // these go well with all but compressed formats
148 
149  switch(type())
150  {
151  default:
152  break;
153 
154  case IT_UNSIGNED_BYTE:
155  case IT_BYTE:
156  case IT_UNSIGNED_SHORT:
157  case IT_SHORT:
158  case IT_UNSIGNED_INT:
159  case IT_INT:
160  case IT_FLOAT:
161  {
162  switch(format())
163  {
168  {
169  break;
170  }
171 
172  default:
173  {
174  okformat = true;
175  }
176  }
177  }
178  }
179 
180  // compressed type go well only with compressed formats
181 
182  switch(type())
183  {
184  default:
185  break;
186 
187  case IT_IMPLICIT_TYPE:
188  {
189  switch(format())
190  {
195  {
196  okformat = true;
197  break;
198  }
199 
200  default:
201  {
202  break;
203  }
204  }
205  }
206  }
207 
208  switch(format())
209  {
210  default:
211  break;
212 
213  // depth stencil
214  case IF_DEPTH_STENCIL:
215  {
216  switch(type())
217  {
220  okformat = true;
221  default:
222  break;
223  }
224  }
225  break;
226 
227  // three components types
228 
229  case IF_RGB:
230  case IF_BGR:
231  {
232  switch(type())
233  {
238  case IT_UNSIGNED_INT_5_9_9_9_REV: /* EXT_texture_shared_exponent, support only GL_RGB */
239  case IT_UNSIGNED_INT_10F_11F_11F_REV: /* EXT_packed_float, supports only GL_RGB */
240  {
241  okformat = true;
242  break;
243  }
244 
245  default:
246  {
247  break;
248  }
249  }
250  break;
251  }
252 
253  // four components types
254 
255  case IF_RGBA:
256  case IF_BGRA:
257  {
258  switch(type())
259  {
268  {
269  okformat = true;
270  break;
271  }
272 
273  default:
274  {
275  break;
276  }
277  }
278  }
279  }
280 
281  #ifndef NDEBUG
282  bool isvalid = okformat && (x|y|z) && (pitch() % mByteAlign == 0);
283  Log::debug( isvalid ? "" : ( okformat ? "Image::isValid(): invalid dimensions or pitch/bytealign combination:\n" : "Image::isValid() reported an invalid format/type combination:\n") + print() );
284  #endif
285 
286  return okformat && (x|y|z) && (pitch() % mByteAlign == 0);
287 }
288 //-----------------------------------------------------------------------------
290 {
291  std::map<int, const char*> ty;
292 
293  ty[IT_IMPLICIT_TYPE] = "IT_IMPLICIT_TYPE";
294  ty[IT_UNSIGNED_BYTE] = "IT_UNSIGNED_BYTE";
295  ty[IT_BYTE] = "IT_BYTE";
296  ty[IT_UNSIGNED_SHORT] = "IT_UNSIGNED_SHORT";
297  ty[IT_SHORT] = "IT_SHORT";
298  ty[IT_UNSIGNED_INT] = "IT_UNSIGNED_INT";
299  ty[IT_INT] = "IT_INT";
300  ty[IT_FLOAT] = "IT_FLOAT";
301  ty[IT_UNSIGNED_BYTE_3_3_2] = "IT_UNSIGNED_BYTE_3_3_2";
302  ty[IT_UNSIGNED_BYTE_2_3_3_REV] = "IT_UNSIGNED_BYTE_2_3_3_REV";
303  ty[IT_UNSIGNED_SHORT_5_6_5] = "IT_UNSIGNED_SHORT_5_6_5";
304  ty[IT_UNSIGNED_SHORT_5_6_5_REV] = "IT_UNSIGNED_SHORT_5_6_5_REV";
305  ty[IT_UNSIGNED_SHORT_4_4_4_4] = "IT_UNSIGNED_SHORT_4_4_4_4";
306  ty[IT_UNSIGNED_SHORT_4_4_4_4_REV] = "IT_UNSIGNED_SHORT_4_4_4_4_REV";
307  ty[IT_UNSIGNED_SHORT_5_5_5_1] = "IT_UNSIGNED_SHORT_5_5_5_1";
308  ty[IT_UNSIGNED_SHORT_1_5_5_5_REV] = "IT_UNSIGNED_SHORT_1_5_5_5_REV";
309  ty[IT_UNSIGNED_INT_8_8_8_8] = "IT_UNSIGNED_INT_8_8_8_8";
310  ty[IT_UNSIGNED_INT_8_8_8_8_REV] = "IT_UNSIGNED_INT_8_8_8_8_REV";
311  ty[IT_UNSIGNED_INT_10_10_10_2] = "IT_UNSIGNED_INT_10_10_10_2";
312  ty[IT_UNSIGNED_INT_2_10_10_10_REV] = "IT_UNSIGNED_INT_2_10_10_10_REV";
313  ty[IT_UNSIGNED_INT_5_9_9_9_REV] = "IT_UNSIGNED_INT_5_9_9_9_REV";
314  ty[IT_UNSIGNED_INT_10F_11F_11F_REV] = "IT_UNSIGNED_INT_10F_11F_11F_REV";
315  ty[IT_UNSIGNED_INT_24_8] = "IT_UNSIGNED_INT_24_8";
316  ty[IT_FLOAT_32_UNSIGNED_INT_24_8_REV] = "IT_FLOAT_32_UNSIGNED_INT_24_8_REV";
317 
318  VL_CHECK(ty[type()] != NULL)
319 
320  return ty[type()];
321 }
322 //-----------------------------------------------------------------------------
324 {
325  std::map<int, const char*> fo;
326 
327  fo[IF_RGB] = "IF_RGB";
328  fo[IF_RGBA] = "IF_RGBA";
329  fo[IF_BGR] = "IF_BGR";
330  fo[IF_BGRA] = "IF_BGRA";
331  fo[IF_RED] = "IF_RED";
332  fo[IF_GREEN] = "IF_GREEN";
333  fo[IF_BLUE] = "IF_BLUE";
334  fo[IF_ALPHA] = "IF_ALPHA";
335  fo[IF_LUMINANCE] = "IF_LUMINANCE";
336  fo[IF_LUMINANCE_ALPHA] = "IF_LUMINANCE_ALPHA";
337  fo[IF_DEPTH_COMPONENT] = "IF_DEPTH_COMPONENT";
338  fo[IF_STENCIL_INDEX] = "IF_STENCIL_INDEX";
339  fo[IF_DEPTH_STENCIL] = "IF_DEPTH_STENCIL";
340  fo[IF_COMPRESSED_RGB_S3TC_DXT1] = "IF_COMPRESSED_RGB_S3TC_DXT1";
341  fo[IF_COMPRESSED_RGBA_S3TC_DXT1] = "IF_COMPRESSED_RGBA_S3TC_DXT1";
342  fo[IF_COMPRESSED_RGBA_S3TC_DXT3] = "IF_COMPRESSED_RGBA_S3TC_DXT3";
343  fo[IF_COMPRESSED_RGBA_S3TC_DXT5] = "IF_COMPRESSED_RGBA_S3TC_DXT5";
344 
345  VL_CHECK( fo[format()] != NULL );
346 
347  return fo[format()];
348 }
349 //-----------------------------------------------------------------------------
351 {
352  return Say(
353  "name = %s\n"
354  "width = %n\n"
355  "height = %n\n"
356  "depth = %n\n"
357  "format = %s\n"
358  "type = %s\n"
359  "pitch = %n\n"
360  "bytealign = %n\n"
361  )
362  << objectName().c_str()
363  << width()
364  << height()
365  << depth()
366  << printFormat()
367  << printType()
368  << pitch()
369  << byteAlignment();
370 }
371 //-----------------------------------------------------------------------------
373 {
374  if(mWidth > 0 && mHeight == 0 && mDepth == 0 && !mIsCubemap) return ID_1D;
375  if(mWidth > 0 && mHeight > 0 && mDepth == 0 && !mIsCubemap) return ID_2D;
376  if(mWidth > 0 && mHeight > 0 && mDepth > 0 && !mIsCubemap) return ID_3D;
377  if(mWidth > 0 && mHeight > 0 && mDepth == 0 && mIsCubemap) return ID_Cubemap;
378  return ID_Error;
379 }
380 //-----------------------------------------------------------------------------
383 {
384  int comp_size = 0;
385 
386  switch(type)
387  {
388  default:
389  break;
390 
391  case IT_UNSIGNED_BYTE: comp_size = sizeof(unsigned char) * 8; break;
392  case IT_BYTE: comp_size = sizeof(GLbyte) * 8; break;
393  case IT_UNSIGNED_SHORT: comp_size = sizeof(GLushort) * 8; break;
394  case IT_SHORT: comp_size = sizeof(GLshort) * 8; break;
395  case IT_UNSIGNED_INT: comp_size = sizeof(unsigned int) * 8; break;
396  case IT_INT: comp_size = sizeof(int) * 8; break;
397  case IT_FLOAT: comp_size = sizeof(float) * 8; break;
398 
399  case IT_UNSIGNED_BYTE_3_3_2: return 8;
400  case IT_UNSIGNED_BYTE_2_3_3_REV: return 8;
401  case IT_UNSIGNED_SHORT_5_6_5: return 16;
402  case IT_UNSIGNED_SHORT_5_6_5_REV: return 16;
403  case IT_UNSIGNED_SHORT_4_4_4_4: return 16;
404  case IT_UNSIGNED_SHORT_4_4_4_4_REV: return 16;
405  case IT_UNSIGNED_SHORT_5_5_5_1: return 16;
406  case IT_UNSIGNED_SHORT_1_5_5_5_REV: return 16;
407  case IT_UNSIGNED_INT_8_8_8_8: return 32;
408  case IT_UNSIGNED_INT_8_8_8_8_REV: return 32;
409  case IT_UNSIGNED_INT_10_10_10_2: return 32;
410  case IT_UNSIGNED_INT_2_10_10_10_REV: return 32;
411  case IT_UNSIGNED_INT_5_9_9_9_REV: return 32; /* EXT_texture_shared_exponent, support only IF_RGB */
412  case IT_UNSIGNED_INT_10F_11F_11F_REV: return 32; /* EXT_packed_float, supports only IF_RGB */
413  case IT_UNSIGNED_INT_24_8: return 32; /* EXT_packed_depth_stencil, supports only IF_DEPTH_STENCIL */
414  case IT_FLOAT_32_UNSIGNED_INT_24_8_REV: return 64; /* EXT_depth_buffer_float, supports only IF_DEPTH_STENCIL */
415  }
416 
417  switch(format)
418  {
419  case IF_RED: return comp_size * 1;
420  case IF_GREEN: return comp_size * 1;
421  case IF_BLUE: return comp_size * 1;
422  case IF_ALPHA: return comp_size * 1;
423  case IF_DEPTH_COMPONENT: return comp_size * 1;
424  case IF_STENCIL_INDEX: return comp_size * 1;
425  case IF_LUMINANCE: return comp_size * 1;
426  case IF_LUMINANCE_ALPHA: return comp_size * 2;
427  case IF_DEPTH_STENCIL: return comp_size * 0;
428  case IF_RG: return comp_size * 2;
429  case IF_RGB: return comp_size * 3;
430  case IF_BGR: return comp_size * 3;
431  case IF_RGBA: return comp_size * 4;
432  case IF_BGRA: return comp_size * 4;
433 
434  // compressed formats
435 
436  case IF_COMPRESSED_RGB_S3TC_DXT1: return 4; // 8 bytes (64 bits) per block per 16 pixels
437  case IF_COMPRESSED_RGBA_S3TC_DXT1: return 4; // 8 bytes (64 bits) per block per 16 pixels
438  case IF_COMPRESSED_RGBA_S3TC_DXT3: return 8; // 16 bytes (128 bits) per block per 16 pixels
439  case IF_COMPRESSED_RGBA_S3TC_DXT5: return 8; // 16 bytes (128 bits) per block per 16 pixels
440  default:
441  break;
442  }
443 
444  VL_TRAP()
445  return 0;
446 }
447 //-----------------------------------------------------------------------------
449 int Image::alphaBits() const
450 {
451  int comp_size = 0;
452 
453  switch(format())
454  {
455  case IF_RED: return comp_size * 0;
456  case IF_GREEN: return comp_size * 0;
457  case IF_BLUE: return comp_size * 0;
458  case IF_ALPHA: return comp_size * 1;
459  case IF_DEPTH_COMPONENT: return comp_size * 0;
460  case IF_STENCIL_INDEX: return comp_size * 0;
461  case IF_LUMINANCE: return comp_size * 0;
462  case IF_LUMINANCE_ALPHA: return comp_size * 1;
463  case IF_DEPTH_STENCIL: return comp_size * 0;
464  case IF_RGB: return comp_size * 0;
465  case IF_BGR: return comp_size * 0;
466  case IF_RGBA: return comp_size * 1;
467  case IF_BGRA: return comp_size * 1;
468 
469  // compressed formats
470 
471  case IF_COMPRESSED_RGB_S3TC_DXT1: return 0; // 8 bytes (64 bits) per block per 16 pixels
472  case IF_COMPRESSED_RGBA_S3TC_DXT1: return 1; // 8 bytes (64 bits) per block per 16 pixels
473  case IF_COMPRESSED_RGBA_S3TC_DXT3: return 4; // 16 bytes (64 bits for uncompressed alpha + 64 bits for RGB) per block per 16 pixels
474  case IF_COMPRESSED_RGBA_S3TC_DXT5: return 4; // 16 bytes (64 bits for compressed alpha + 64 bits for RGB) per block per 16 pixels
475  default:
476  break;
477  }
478 
479  switch(type())
480  {
481  default:
482  break;
483 
484  case IT_UNSIGNED_BYTE: comp_size = sizeof(unsigned char) * 8; break;
485  case IT_BYTE: comp_size = sizeof(GLbyte) * 8; break;
486  case IT_UNSIGNED_SHORT: comp_size = sizeof(GLushort) * 8; break;
487  case IT_SHORT: comp_size = sizeof(GLshort) * 8; break;
488  case IT_UNSIGNED_INT: comp_size = sizeof(unsigned int) * 8; break;
489  case IT_INT: comp_size = sizeof(int) * 8; break;
490  case IT_FLOAT: comp_size = sizeof(float) * 8; break;
491 
492  case IT_UNSIGNED_BYTE_3_3_2: return 0;
493  case IT_UNSIGNED_BYTE_2_3_3_REV: return 0;
494  case IT_UNSIGNED_SHORT_5_6_5: return 0;
495  case IT_UNSIGNED_SHORT_5_6_5_REV: return 0;
496  case IT_UNSIGNED_SHORT_4_4_4_4: return 4;
497  case IT_UNSIGNED_SHORT_4_4_4_4_REV: return 4;
498  case IT_UNSIGNED_SHORT_5_5_5_1: return 1;
499  case IT_UNSIGNED_SHORT_1_5_5_5_REV: return 1;
500  case IT_UNSIGNED_INT_8_8_8_8: return 8;
501  case IT_UNSIGNED_INT_8_8_8_8_REV: return 8;
502  case IT_UNSIGNED_INT_10_10_10_2: return 2;
503  case IT_UNSIGNED_INT_2_10_10_10_REV: return 2;
504  case IT_UNSIGNED_INT_5_9_9_9_REV: return 0; /* EXT_texture_shared_exponent, support only GL_RGB */
505  case IT_UNSIGNED_INT_10F_11F_11F_REV: return 0; /* EXT_packed_float, supports only GL_RGB */
506  case IT_UNSIGNED_INT_24_8: return 0; /* EXT_packed_depth_stencil, supports only GL_DEPTH_STENCIL */
507  case IT_FLOAT_32_UNSIGNED_INT_24_8_REV: return 0; /* EXT_depth_buffer_float, supports only IF_DEPTH_STENCIL */
508  }
509 
510  VL_TRAP()
511 
512  return 0;
513 }
514 //-----------------------------------------------------------------------------
516 {
517  switch(fmt)
518  {
523  return true;
524 
525  default:
526  return false;
527  }
528 }
529 //-----------------------------------------------------------------------------
533 {
534  VL_CHECK( isValid() )
535  return requiredMemory(width(), height(), depth(), byteAlignment(), format(), type(), isCubemap());
536 }
537 //-----------------------------------------------------------------------------
541 {
542  return mByteAlign;
543 }
544 //-----------------------------------------------------------------------------
550 void Image::setByteAlignment(int bytealign)
551 {
552  if (!mPixels->empty())
553  return;
554 
555  switch(bytealign)
556  {
557  case 0:
558  bytealign = sizeof(unsigned char*);
559  case 1:
560  case 2:
561  case 4:
562  case 8:
563  break;
564  default:
565  VL_TRAP()
566  }
567 
568  mByteAlign = bytealign;
569 
570  updatePitch();
571 }
572 //-----------------------------------------------------------------------------
574 {
575  int xbits = mWidth * bitsPerPixel();
576  int xbytes = xbits/8 + ( (xbits % 8) ? 1 : 0 );
577  mPitch = xbytes/mByteAlign*mByteAlign + ( (xbytes % mByteAlign) ? mByteAlign : 0 );
578 }
579 //-----------------------------------------------------------------------------
581 {
582  mMipmaps.clear();
583  mPixels->resize(requiredMemory());
584 }
585 //-----------------------------------------------------------------------------
587 {
588  reset();
589 
590  VL_CHECK(x);
591  setWidth(x);
592  setHeight(0);
593  setDepth(0);
594  setFormat(format);
595  setType(type);
596  setByteAlignment(1);
597  mIsCubemap = false;
598 
599  if ( ! requiredMemory() ) {
600  Log::bug("Image::allocate1D() failed, probably your image settings are invalid.\n");
601  } else {
602  if ( mPixels->allocationMode() == vl::Buffer::AutoAllocatedBuffer ) {
603  mPixels->resize( requiredMemory() );
604  }
605  }
606 }
607 //-----------------------------------------------------------------------------
608 void Image::allocate2D(int x, int y, int bytealign, EImageFormat format, EImageType type)
609 {
610  reset();
611 
612  VL_CHECK(x);
613  VL_CHECK(y);
614  setWidth(x);
615  setHeight(y);
616  setDepth(0);
617  setFormat(format);
618  setType(type);
619  setByteAlignment(bytealign);
620  mIsCubemap = false;
621 
622  if ( ! requiredMemory() ) {
623  Log::bug("Image::allocate2D() failed, probably your image settings are invalid.\n");
624  } else {
625  if ( mPixels->allocationMode() == vl::Buffer::AutoAllocatedBuffer ) {
626  mPixels->resize( requiredMemory() );
627  }
628  }
629 }
630 //-----------------------------------------------------------------------------
631 void Image::allocate3D(int x, int y, int z, int bytealign, EImageFormat format, EImageType type)
632 {
633  reset();
634 
635  VL_CHECK(x);
636  VL_CHECK(y);
637  VL_CHECK(z);
638  setWidth(x);
639  setHeight(y);
640  setDepth(z);
641  setFormat(format);
642  setType(type);
643  setByteAlignment(bytealign);
644  mIsCubemap = false;
645 
646  if ( ! requiredMemory() ) {
647  Log::bug("Image::allocate3D() failed, probably your image settings are invalid.\n");
648  } else {
649  if ( mPixels->allocationMode() == vl::Buffer::AutoAllocatedBuffer ) {
650  mPixels->resize( requiredMemory() );
651  }
652  }
653 }
654 //-----------------------------------------------------------------------------
655 void Image::allocateCubemap(int x, int y, int bytealign, EImageFormat format, EImageType type)
656 {
657  reset();
658 
659  setWidth(x);
660  setHeight(y);
661  setDepth(0);
662  setFormat(format);
663  setType(type);
664  setByteAlignment(bytealign);
665  mIsCubemap = true;
666 
667  if ( ! requiredMemory() ) {
668  Log::bug("Image::allocateCubemap() failed, probably your image settings are invalid.\n");
669  } else {
670  if ( mPixels->allocationMode() == vl::Buffer::AutoAllocatedBuffer ) {
671  mPixels->resize( requiredMemory() );
672  }
673  }
674 }
675 //-----------------------------------------------------------------------------
676 void Image::reset(int x, int y, int z, int bytealign, EImageFormat format, EImageType type, bool is_cubemap)
677 {
678  reset();
679 
680  setWidth(x);
681  setHeight(y);
682  setDepth(z);
683  setFormat(format);
684  setType(type);
685  setByteAlignment(bytealign);
686  mIsCubemap = is_cubemap;
687 }
688 //-----------------------------------------------------------------------------
690 {
691  if ( mPixels->allocationMode() == vl::Buffer::AutoAllocatedBuffer ) {
692  mPixels->clear();
693  }
694  mMipmaps.clear();
695  mObjectName.clear();
696  mWidth = 0;
697  mHeight = 0;
698  mDepth = 0;
699  mPitch = 0;
700  mFormat = IF_RGBA;
702  mByteAlign = 1;
703  mIsCubemap = false;
704  mIsNormalMap = false;
705  mHasAlpha = false;
706 }
707 //-----------------------------------------------------------------------------
709 {
710  super::operator=(other);
711 
712  // deep copy of the pixels
713  *mPixels = *other.mPixels;
714 
715  // copy image info
716  mWidth = other.mWidth;
717  mHeight = other.mHeight;
718  mDepth = other.mDepth;
719  mPitch = other.mPitch;
720  mByteAlign = other.mByteAlign;
721  mFormat = other.mFormat;
722  mType = other.mType;
723  mIsCubemap = other.mIsCubemap;
724  mIsNormalMap = other.mIsNormalMap;
725  mHasAlpha = other.mHasAlpha;
726 
727  // deep copy of the mipmaps
728  mMipmaps.resize(other.mMipmaps.size());
729  for(int i=0; i<(int)mMipmaps.size(); ++i)
730  {
731  mMipmaps[i] = new Image;
732  *mMipmaps[i] = *other.mMipmaps[i];
733  }
734  return *this;
735 }
736 //-----------------------------------------------------------------------------
737 const unsigned char* Image::pixelsXP() const
738 {
739  VL_CHECK( dimension() == 4 )
740  if( dimension() != 4 || !pixels())
741  return NULL;
742  else
743  return pixels();
744 }
745 //-----------------------------------------------------------------------------
746 unsigned char* Image::pixelsXP()
747 {
748  VL_CHECK( dimension() == 4 )
749  if( dimension() != 4 || !pixels())
750  return NULL;
751  else
752  return pixels();
753 }
754 //-----------------------------------------------------------------------------
755 const unsigned char* Image::pixelsXN() const
756 {
757  VL_CHECK( dimension() == 4 )
758  if( dimension() != 4 || !pixels())
759  return NULL;
760  else
761  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 1;
762 }
763 //-----------------------------------------------------------------------------
764 unsigned char* Image::pixelsXN()
765 {
766  VL_CHECK( dimension() == 4 )
767  if( dimension() != 4 || !pixels())
768  return NULL;
769  else
770  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 1;
771 }
772 //-----------------------------------------------------------------------------
773 const unsigned char* Image::pixelsYP() const
774 {
775  VL_CHECK( dimension() == 4 )
776  if( dimension() != 4 || !pixels())
777  return NULL;
778  else
779  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 2;
780 }
781 //-----------------------------------------------------------------------------
782 unsigned char* Image::pixelsYP()
783 {
784  VL_CHECK( dimension() == 4 )
785  if( dimension() != 4 || !pixels())
786  return NULL;
787  else
788  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 2;
789 }
790 //-----------------------------------------------------------------------------
791 const unsigned char* Image::pixelsYN() const
792 {
793  VL_CHECK( dimension() == 4 )
794  if( dimension() != 4 || !pixels())
795  return NULL;
796  else
797  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 3;
798 }
799 //-----------------------------------------------------------------------------
800 unsigned char* Image::pixelsYN()
801 {
802  VL_CHECK( dimension() == 4 )
803  if( dimension() != 4 || !pixels())
804  return NULL;
805  else
806  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 3;
807 }
808 //-----------------------------------------------------------------------------
809 const unsigned char* Image::pixelsZP() const
810 {
811  VL_CHECK( dimension() == 4 )
812  if( dimension() != 4 || !pixels())
813  return NULL;
814  else
815  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 4;
816 }
817 //-----------------------------------------------------------------------------
818 unsigned char* Image::pixelsZP()
819 {
820  VL_CHECK( dimension() == 4 )
821  if( dimension() != 4 || !pixels())
822  return NULL;
823  else
824  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 4;
825 }
826 //-----------------------------------------------------------------------------
827 const unsigned char* Image::pixelsZN() const
828 {
829  VL_CHECK( dimension() == 4 )
830  if( dimension() != 4 || !pixels())
831  return NULL;
832  else
833  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 5;
834 }
835 //-----------------------------------------------------------------------------
836 unsigned char* Image::pixelsZN()
837 {
838  VL_CHECK( dimension() == 4 )
839  if( dimension() != 4 || !pixels())
840  return NULL;
841  else
842  return (unsigned char*)pixels() + requiredMemory2D( width(), height(), byteAlignment(), format(), type() ) * 5;
843 }
844 //-----------------------------------------------------------------------------
846 unsigned char* Image::pixelsZSlice(int slice)
847 {
848  VL_CHECK(slice < depth());
849  VL_CHECK(slice >= 0 );
850  if (mIsCubemap || !pixels())
851  return NULL;
852  else
853  {
854  return (unsigned char*)pixels() + pitch()*height()*slice;
855  }
856 }
857 //-----------------------------------------------------------------------------
858 ref<Image> vl::createCubemap(const Image* xp, const Image* xn, const Image* yp, const Image* yn, const Image* zp, const Image* zn)
859 {
860  // check validity of all the images
861  // contract:
862  // - they must be all isValid() images, must have been allocated, must be 2D images, must
863  // - have exactly the same dimensions, format, type, byte alignment.
864  // - they must be square
865 
866  const Image* img[] = {xp, xn, yp, yn, zp, zn};
867 
868  // check they are square (later we check they have the same size)
869  if (img[0]->width() != img[0]->height())
870  {
871  Log::error("Cubemap creation failed: all the images must be square.\n");
872  return NULL;
873  }
874 
875  for(int i=0; i<6; ++i)
876  {
877  if (img[i] == NULL || !img[i]->isValid() || img[i]->pixels() == NULL || img[i]->dimension() != 2)
878  {
879  Log::error("Cubemap creation failed: one or more image is invalid (could be NULL, not allocated, not 2D, wrong internal_ configuration or other).\n");
880  return NULL;
881  }
882 
883  // check that they have the same size
884  if (img[0]->width() != img[i]->width())
885  {
886  Log::error("Cubemap creation failed: the faces of the cube must have the very same dimensions.\n");
887  return NULL;
888  }
889 
890  // check that they have the same size
891  if (img[0]->height() != img[i]->height())
892  {
893  Log::error("Cubemap creation failed: the faces of the cube must have the very same dimensions.\n");
894  return NULL;
895  }
896 
897  // check that they have the same format
898  if (img[0]->format() != img[i]->format())
899  {
900  Log::error("Cubemap creation failed: the faces of the cube must have the very same format.\n");
901  return NULL;
902  }
903 
904  // check that they have the same type
905  if (img[0]->type() != img[i]->type())
906  {
907  Log::error("Cubemap creation failed: the faces of the cube must have the very same type.\n");
908  return NULL;
909  }
910 
911  // check that they have the same byte alignment
912  if (img[0]->byteAlignment() != img[i]->byteAlignment())
913  {
914  Log::error("Cubemap creation failed: the faces of the cube must have the very same byte alignment.\n");
915  return NULL;
916  }
917 
918  // check that they have the same required memory
919  if (img[0]->requiredMemory() != img[i]->requiredMemory())
920  {
921  Log::error("Cubemap creation failed: the faces of the cube must require the very same amount of memory.\n");
922  return NULL;
923  }
924  }
925 
926  // create a cube map image from the given 2D images
927 
928  ref<Image> cubemap = new Image;
929 
930  cubemap->allocateCubemap( img[0]->width(), img[0]->height(), img[0]->byteAlignment(), img[0]->format(), img[0]->type() );
931 
932  memcpy( cubemap->pixelsXP(), img[0]->pixels(), img[0]->requiredMemory() );
933  memcpy( cubemap->pixelsXN(), img[1]->pixels(), img[0]->requiredMemory() );
934  memcpy( cubemap->pixelsYP(), img[2]->pixels(), img[0]->requiredMemory() );
935  memcpy( cubemap->pixelsYN(), img[3]->pixels(), img[0]->requiredMemory() );
936  memcpy( cubemap->pixelsZP(), img[4]->pixels(), img[0]->requiredMemory() );
937  memcpy( cubemap->pixelsZN(), img[5]->pixels(), img[0]->requiredMemory() );
938 
939  return cubemap.get();
940 }
941 //-----------------------------------------------------------------------------
943 {
944  if (dimension() == ID_1D)
945  return;
946 
947  VL_CHECK(pixels());
948  int row_size = pitch();
949  std::vector<unsigned char> row1;
950  row1.resize(row_size);
951 
952  std::vector<unsigned char*> pxl;
953 
954  if (dimension() == ID_2D)
955  {
956  pxl.push_back( (unsigned char*)pixels() );
957  }
958  else
959  if (dimension() == ID_Cubemap)
960  {
961  pxl.push_back( (unsigned char*)pixelsXP() );
962  pxl.push_back( (unsigned char*)pixelsXN() );
963  pxl.push_back( (unsigned char*)pixelsYP() );
964  pxl.push_back( (unsigned char*)pixelsYN() );
965  pxl.push_back( (unsigned char*)pixelsZP() );
966  pxl.push_back( (unsigned char*)pixelsZN() );
967  }
968  else
969  if (dimension() == ID_3D)
970  {
971  for(int zslice=0; zslice<depth(); zslice++)
972  pxl.push_back( (unsigned char*)pixelsZSlice(zslice) );
973  }
974 
975  for(unsigned img=0; img<pxl.size(); img++)
976  {
977  for(int i=0; i<height()/2; ++i)
978  {
979  int j = height() - 1 - i;
980  memcpy(&row1[0], pxl[img]+i*row_size, row_size);
981  memcpy(pxl[img]+i*row_size, pxl[img]+j*row_size, row_size);
982  memcpy(pxl[img]+j*row_size, &row1[0], row_size);
983  }
984  }
985 }
986 //-----------------------------------------------------------------------------
987 int Image::requiredMemory(int width, int height, int depth, int bytealign, EImageFormat format, EImageType type, bool is_cubemap)
988 {
989  // byte align
990 
991  switch(bytealign)
992  {
993  case 1:
994  case 2:
995  case 4:
996  case 8:
997  break;
998  case 0:
999  default:
1000  bytealign = sizeof(unsigned char*);
1001  }
1002 
1003  // fix width and height to match compression scheme
1004 
1005  switch(format)
1006  {
1011  if (width % 4)
1012  width = width - width % 4 + 4;
1013  if (height % 4)
1014  height = height - height % 4 + 4;
1015  default:
1016  break;
1017  }
1018 
1019  // pitch
1020 
1021  int xbits = width * bitsPerPixel(type, format);
1022  int xbytes = xbits/8 + ( (xbits % 8) ? 1 : 0 );
1023  int pitch = xbytes/bytealign*bytealign + ( (xbytes % bytealign) ? bytealign : 0 );
1024 
1025  // computation
1026 
1027  height = height ? height : 1;
1028  depth = depth ? depth : 1;
1029  int req_mem = pitch * height * depth;
1030 
1031  // minimum memory taken by a compressed block
1032  if (req_mem < 8 && format == IF_COMPRESSED_RGB_S3TC_DXT1)
1033  req_mem = 8;
1034 
1035  if (req_mem < 8 && format == IF_COMPRESSED_RGBA_S3TC_DXT1)
1036  req_mem = 8;
1037 
1038  if (req_mem < 16 && format == IF_COMPRESSED_RGBA_S3TC_DXT3)
1039  req_mem = 16;
1040 
1041  if (req_mem < 16 && format == IF_COMPRESSED_RGBA_S3TC_DXT5)
1042  req_mem = 16;
1043 
1044  // todo: add other compression schemes
1045  // ...
1046 
1047  // cubemap
1048  if (is_cubemap)
1049  req_mem *= 6;
1050 
1051  return req_mem;
1052 }
1053 //-----------------------------------------------------------------------------
1054 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1)
1055 {
1056  std::vector<fvec4> colors;
1057  colors.push_back(c0); colors.push_back(c1);
1058  return makeColorSpectrum(width, colors);
1059 }
1060 //-----------------------------------------------------------------------------
1061 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2)
1062 {
1063  std::vector<fvec4> colors;
1064  colors.push_back(c0); colors.push_back(c1); colors.push_back(c2);
1065  return makeColorSpectrum(width, colors);
1066 }
1067 //-----------------------------------------------------------------------------
1068 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2, const fvec4& c3)
1069 {
1070  std::vector<fvec4> colors;
1071  colors.push_back(c0); colors.push_back(c1); colors.push_back(c2); colors.push_back(c3);
1072  return makeColorSpectrum(width, colors);
1073 }
1074 //-----------------------------------------------------------------------------
1075 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2, const fvec4& c3, const fvec4& c4)
1076 {
1077  std::vector<fvec4> colors;
1078  colors.push_back(c0); colors.push_back(c1); colors.push_back(c2); colors.push_back(c3); colors.push_back(c4);
1079  return makeColorSpectrum(width, colors);
1080 }
1081 //-----------------------------------------------------------------------------
1082 ref<Image> vl::makeColorSpectrum(size_t width, const fvec4& c0, const fvec4& c1, const fvec4& c2, const fvec4& c3, const fvec4& c4, const fvec4& c5)
1083 {
1084  std::vector<fvec4> colors;
1085  colors.push_back(c0); colors.push_back(c1); colors.push_back(c2); colors.push_back(c3); colors.push_back(c4); colors.push_back(c5);
1086  return makeColorSpectrum(width, colors);
1087 }
1088 //-----------------------------------------------------------------------------
1089 ref<Image> vl::makeNonUniformColorSpectrum(size_t width, size_t col_count, const fvec4* colors, const float* col_pos)
1090 {
1091  // c0 c1 c2 c4
1092  // |---t0----t1----t2----t4---|
1093  // before t0 the color is pure c0
1094  // after t4 the color is pure t4
1095 
1096  ref<Image> img = new Image(width, 0, 0, 1, IF_RGBA, IT_UNSIGNED_BYTE);
1097  ubvec4* px = (ubvec4*)img->pixels();
1098  int last = col_count-1;
1099  for(int i=0; i<img->width(); ++i)
1100  {
1101  float t = (float)i/(img->width()-1);
1102  if (t<=col_pos[0])
1103  px[i] = (ubvec4)(colors[0]*255.0f);
1104  else
1105  if (t>=col_pos[last])
1106  px[i] = (ubvec4)(colors[last]*255.0f);
1107  else
1108  {
1109  for(size_t j=0; j<col_count-1; ++j)
1110  {
1111  if (t>=col_pos[j] && t<=col_pos[j+1])
1112  {
1113  float tt = 0;
1114  if (col_pos[j+1]-col_pos[j] != 0)
1115  tt = (t-col_pos[j])/(col_pos[j+1]-col_pos[j]);
1116  VL_CHECK(tt>=0 && tt<=1.0f)
1117  px[i] = (ubvec4)((colors[j] * (1.0f-tt) + colors[j+1] * tt)*255.0f);
1118  break;
1119  }
1120  }
1121  }
1122  }
1123  return img;
1124 }
1125 //-----------------------------------------------------------------------------
1126 ref<Image> vl::makeNonUniformColorSpectrum(int width, const std::vector<fvec4>& colors, const std::vector<float>& col_pos)
1127 {
1128  if (colors.empty() || colors.size() != col_pos.size())
1129  return NULL;
1130  else
1131  return makeNonUniformColorSpectrum(width, colors.size(), &colors[0], &col_pos[0]);
1132 }
1133 //-----------------------------------------------------------------------------
1134 ref<Image> vl::makeColorSpectrum(size_t width, const std::vector<fvec4>& colors)
1135 {
1136  ref<Image> img = new Image(width, 0, 0, 1, IF_RGBA, IT_UNSIGNED_BYTE);
1137  int index = colors.size() - 1;
1138  for(int i=0; i<img->width(); ++i)
1139  {
1140  int coli = (int)(index * (float)i/img->width());
1141  float colt = (index * (float)i/img->width()) - coli;
1142  img->pixels()[i*4 + 0] = (unsigned char)(255.0 * (colors[coli].r()*(1.0f-colt) + colors[coli+1].r()*colt));
1143  img->pixels()[i*4 + 1] = (unsigned char)(255.0 * (colors[coli].g()*(1.0f-colt) + colors[coli+1].g()*colt));
1144  img->pixels()[i*4 + 2] = (unsigned char)(255.0 * (colors[coli].b()*(1.0f-colt) + colors[coli+1].b()*colt));
1145  img->pixels()[i*4 + 3] = 255;
1146  }
1147  return img;
1148 }
1149 //-----------------------------------------------------------------------------
1151 ref<Image> vl::assemble3DImage(const std::vector< ref<Image> >& images)
1152 {
1153  if (images.empty())
1154  return NULL;
1155  // sanity checks
1156  for(unsigned i=1; i<images.size(); ++i)
1157  {
1158  if (images[i]->width() != images[0]->width()) return NULL;
1159  if (images[i]->height() != images[0]->height()) return NULL;
1160  if (images[i]->depth() != images[0]->depth()) return NULL;
1161  if (images[i]->type() != images[0]->type()) return NULL;
1162  if (images[i]->format() != images[0]->format()) return NULL;
1163  if (images[i]->byteAlignment() != images[0]->byteAlignment()) return NULL;
1164  if (images[i]->bitsPerPixel() != images[0]->bitsPerPixel()) return NULL;
1165  if (images[i]->requiredMemory() != images[0]->requiredMemory()) return NULL;
1166  }
1167 
1168  ref<Image> img = new Image;
1169  img->allocate3D( images[0]->width(), images[0]->height(), images.size(), 1, images[0]->format(), images[0]->type() );
1170  VL_CHECK(img->requiredMemory() == images[0]->requiredMemory()*(int)images.size())
1171  for(unsigned i=0; i<images.size(); ++i)
1172  {
1173  VL_CHECK(images[i]->pixels())
1174  memcpy(img->pixelsZSlice(i), images[i]->pixels(), images[i]->requiredMemory());
1175  }
1176  return img;
1177 }
1178 //-----------------------------------------------------------------------------
1179 bool vl::loadImagesFromDir(const String& dir_path, const String& ext, std::vector< ref<Image> >& images)
1180 {
1181  images.clear();
1182  if (ext.empty() || dir_path.empty())
1183  return false;
1185  if (!dir)
1186  return false;
1187  std::vector<String> files;
1188  dir->listFiles(files);
1189  std::sort(files.begin(), files.end());
1190  for(unsigned i=0; i<files.size(); ++i)
1191  {
1192  if (files[i].extractFileExtension().toLowerCase() == ext.toLowerCase())
1193  {
1194  images.push_back( loadImage(files[i]) );
1195  if (images.back().get() == NULL)
1196  return false;
1197  }
1198  }
1199  return true;
1200 }
1201 //-----------------------------------------------------------------------------
1203 {
1204  ref<VirtualFile> file = defFileSystem()->locateFile(path);
1205  if ( !file )
1206  {
1207  Log::error( Say("File '%s' not found.\n") << path );
1208  return NULL;
1209  }
1210  else
1211  return loadImage(file.get());
1212 }
1213 //-----------------------------------------------------------------------------
1215 {
1217 
1218  if (!res_db)
1219  {
1220  Log::error( Say("vl::loadImage('%s') failed.\n") << file->path() );
1221  return NULL;
1222  }
1223 
1224  ref<Image> img;
1225 
1226  img = res_db->get<Image>(0);
1227 
1228  VL_CHECK( !file->isOpen() )
1229  file->close();
1230 
1231  if (img)
1232  {
1233  img->setObjectName( file->path().toStdString().c_str() );
1234  img->setFilePath( file->path() );
1235  }
1236 
1237  return img;
1238 }
1239 //-----------------------------------------------------------------------------
1240 bool vl::saveImage( Image* img, const String& path)
1241 {
1243  res_db->resources().push_back(img);
1244  bool ok = defLoadWriterManager()->writeResource(path, res_db.get());
1245  if (!ok)
1246  Log::error( Say("vl::saveImage('%s') failed.\n") << path );
1247  return ok;
1248 }
1249 //-----------------------------------------------------------------------------
1250 bool vl::saveImage( Image* img, VirtualFile* file )
1251 {
1253  res_db->resources().push_back(img);
1254  bool ok = defLoadWriterManager()->writeResource(file, res_db.get());
1255  if (!ok)
1256  Log::error( Say("vl::saveImage('%s') failed.\n") << file->path() );
1257  return ok;
1258 }
1259 //-----------------------------------------------------------------------------
1260 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)
1261 {
1262  ref<Image> xp = loadImage(xp_file);
1263  ref<Image> xn = loadImage(xn_file);
1264  ref<Image> yp = loadImage(yp_file);
1265  ref<Image> yn = loadImage(yn_file);
1266  ref<Image> zp = loadImage(zp_file);
1267  ref<Image> zn = loadImage(zn_file);
1268 
1269  if (!xp || !xn || !yp || !yn || !zp || !zn)
1270  {
1271  Log::error("vl::loadCubemap() failed.\n");
1272  return NULL;
1273  }
1274 
1275  ref<Image> img = vl::createCubemap(xp.get(), xn.get(), yp.get(), yn.get(), zp.get(), zn.get());
1276 
1277  return img;
1278 }
1279 //-----------------------------------------------------------------------------
1280 ref<Image> vl::loadRAW(VirtualFile* file, long long file_offset, int width, int height, int depth, int bytealign, EImageFormat format, EImageType type)
1281 {
1282  ref<Image> img = new Image(width, height, depth, bytealign, format, type);
1283  if ( file->isOpen() || file->open(OM_ReadOnly) )
1284  {
1285  bool ok = file_offset == -1 || file->seekSet(file_offset);
1286  if (!ok)
1287  {
1288  Log::error( Say("loadRAW('%s'): seek set to position %n failed.\n") << file_offset );
1289  return NULL;
1290  }
1291  int count = (int)file->read( img->pixels(), img->requiredMemory() );
1292  if (count != img->requiredMemory())
1293  Log::error( Say("loadRAW('%s'): error reading RAW file.\n") << file->path() );
1294  return img;
1295  }
1296  else
1297  {
1298  Log::error( Say("loadRAW('%s'): could not open file for reading.\n") << file->path() );
1299  return NULL;
1300  }
1301 }
1302 //-----------------------------------------------------------------------------
1304 {
1305  switch(type())
1306  {
1307  case IT_UNSIGNED_BYTE:
1308  case IT_BYTE:
1309  case IT_UNSIGNED_SHORT:
1310  case IT_SHORT:
1311  case IT_UNSIGNED_INT:
1312  case IT_INT:
1313  case IT_FLOAT:
1314  break;
1315  default:
1316  Log::error("Image::convertType(): unsupported source image type.\n");
1317  return NULL;
1318  }
1319 
1320  switch(new_type)
1321  {
1322  case IT_UNSIGNED_BYTE:
1323  case IT_BYTE:
1324  case IT_UNSIGNED_SHORT:
1325  case IT_SHORT:
1326  case IT_UNSIGNED_INT:
1327  case IT_INT:
1328  case IT_FLOAT:
1329  break;
1330  default:
1331  Log::error("Image::convertType(): unsupported destination image type.\n");
1332  return NULL;
1333  }
1334 
1335  switch(format())
1336  {
1337  case IF_RGB:
1338  case IF_RGBA:
1339  case IF_BGR:
1340  case IF_BGRA:
1341  case IF_RED:
1342  case IF_GREEN:
1343  case IF_BLUE:
1344  case IF_ALPHA:
1345  case IF_LUMINANCE:
1346  case IF_LUMINANCE_ALPHA:
1347  case IF_DEPTH_COMPONENT:
1348  break;
1349  default:
1350  Log::error("Image::convertType(): unsupported image format.\n");
1351  return NULL;
1352  }
1353 
1354  ref<Image> img = new Image;
1355  img->setObjectName( objectName().c_str() );
1356  img->setFormat(format());
1357  img->setType(new_type);
1358  img->setWidth(width());
1359  img->setHeight(height());
1360  img->setDepth(depth());
1361  img->setByteAlignment(1);
1362  img->mIsCubemap = isCubemap();
1363  img->mIsNormalMap = mIsNormalMap;
1364  img->mHasAlpha = mHasAlpha;
1365  img->allocate();
1366 
1367  int components = 0;
1368  switch(format())
1369  {
1370  case IF_RGB: components = 3; break;
1371  case IF_RGBA: components = 4; break;
1372  case IF_BGR: components = 3; break;
1373  case IF_BGRA: components = 4; break;
1374  case IF_RED: components = 1; break;
1375  case IF_GREEN: components = 1; break;
1376  case IF_BLUE: components = 1; break;
1377  case IF_ALPHA: components = 1; break;
1378  case IF_LUMINANCE: components = 1; break;
1379  case IF_LUMINANCE_ALPHA: components = 2; break;
1380  case IF_DEPTH_COMPONENT: components = 1; break;
1381  default:
1382  break;
1383  }
1384 
1385  int line_count = img->height()?img->height():1;
1386  if (img->depth())
1387  line_count *= img->depth();
1388  else
1389  if (img->isCubemap())
1390  line_count *= 6;
1391 
1392  for(int i=0; i<line_count; ++i)
1393  {
1394  const void* srcLine = pixels() + pitch()*i;
1395  void* dstLine = img->pixels() + img->pitch()*i;
1396 
1397  const unsigned char* srcUByte = (const unsigned char*)srcLine;
1398  const GLbyte* srcSByte = (const GLbyte*)srcLine;
1399  const GLushort* srcUShort = (const GLushort*)srcLine;
1400  const GLshort* srcSShort = (const GLshort*)srcLine;
1401  const unsigned int* srcUInt = (const unsigned int*)srcLine;
1402  const int* srcSInt = (const int*)srcLine;
1403  const float* srcFloat = (const float*)srcLine;
1404 
1405  unsigned char* dstUByte = (unsigned char*)dstLine;
1406  GLbyte* dstSByte = (GLbyte*)dstLine;
1407  GLushort* dstUShort = (GLushort*)dstLine;
1408  GLshort* dstSShort = (GLshort*)dstLine;
1409  unsigned int* dstUInt = (unsigned int*)dstLine;
1410  int* dstSInt = (int*)dstLine;
1411  float* dstFloat = (float*)dstLine;
1412 
1413  for(int j=0; j<img->width(); ++j)
1414  {
1415  for(int c=0; c<components; ++c)
1416  {
1417  double dval = 0;
1418  long long qint = 0;
1419 
1420  // convert dst format to double
1421 
1422  switch(type())
1423  {
1424  case IT_UNSIGNED_BYTE: qint = *srcUByte; dval = qint/255.0; ++srcUByte; break;
1425  case IT_BYTE: qint = *srcSByte; dval = qint/127.0; ++srcSByte; break;
1426  case IT_UNSIGNED_SHORT: qint = *srcUShort; dval = qint/65535.0; ++srcUShort; break;
1427  case IT_SHORT: qint = *srcSShort; dval = qint/32767.0; ++srcSShort; break;
1428  case IT_UNSIGNED_INT: qint = *srcUInt; dval = qint/4294967295.0; ++srcUInt; break;
1429  case IT_INT: qint = *srcSInt; dval = qint/2147483647.0; ++srcSInt; break;
1430  case IT_FLOAT: dval = *srcFloat; ++srcFloat; break;
1431  default:
1432  return NULL;
1433  }
1434 
1435  // clamp 0.0 >= dval >= 1.0
1436  dval = dval < 0.0 ? 0.0 :
1437  dval > 1.0 ? 1.0 :
1438  dval;
1439 
1440  // convert double to dst format
1441 
1442  switch(img->type())
1443  {
1444  case IT_UNSIGNED_BYTE: *dstUByte = (unsigned char) (dval*255.0); ++dstUByte; break;
1445  case IT_BYTE: *dstSByte = (GLbyte) (dval*127.0); ++dstSByte; break;
1446  case IT_UNSIGNED_SHORT: *dstUShort = (GLushort)(dval*65535.0); ++dstUShort; break;
1447  case IT_SHORT: *dstSShort = (GLshort) (dval*32767.0); ++dstSShort; break;
1448  case IT_UNSIGNED_INT: *dstUInt = (unsigned int) (dval*4294967295.0); ++dstUInt; break;
1449  case IT_INT: *dstSInt = (int) (dval*2147483647.0); ++dstSInt; break;
1450  case IT_FLOAT: *dstFloat = (float)dval; ++dstFloat; break;
1451  default:
1452  return NULL;
1453  }
1454  }
1455  }
1456  }
1457 
1458  return img;
1459 }
1460 //-----------------------------------------------------------------------------
1461 namespace {
1462  template<typename T>
1463  void equalizeTemplate(void* ptr, int pitch, int comps, int w, int h, T max_val)
1464  {
1465  // find min/max
1466  T vmin = *((T*)ptr);
1467  T vmax = *((T*)ptr);
1468  for(int y=0; y<h; ++y)
1469  {
1470  T* px = (T*)((char*)ptr + pitch*y);
1471  for(int x=0; x<w; ++x)
1472  {
1473  for(int i=0; i<comps; ++i)
1474  {
1475  if (vmin > px[x*comps+i]) vmin = px[x*comps+i];
1476  if (vmax < px[x*comps+i]) vmax = px[x*comps+i];
1477  }
1478  }
1479  }
1480  // equalize
1481  T range = vmax-vmin;
1482  for(int y=0; y<h; ++y)
1483  {
1484  T* px = (T*)((char*)ptr + pitch*y);
1485  for(int x=0; x<w; ++x)
1486  {
1487  for(int i=0; i<comps; ++i)
1488  px[x*comps+i] = (T)(((float)px[x*comps+i]-vmin)/range*max_val);
1489  }
1490  }
1491  }
1492 }
1496 {
1497  int comps = 0;
1498  switch(format())
1499  {
1500  case IF_RGB: comps = 3; break;
1501  case IF_RGBA: comps = 4; break;
1502  case IF_BGR: comps = 3; break;
1503  case IF_BGRA: comps = 4; break;
1504  case IF_RED: comps = 1; break;
1505  case IF_GREEN: comps = 1; break;
1506  case IF_BLUE: comps = 1; break;
1507  case IF_ALPHA: comps = 1; break;
1508  case IF_LUMINANCE: comps = 1; break;
1509  case IF_LUMINANCE_ALPHA: comps = 2; break;
1510  case IF_DEPTH_COMPONENT: comps = 1; break;
1511  default:
1512  Log::error("Image::equalize(): unsupported image format().\n");
1513  return false;
1514  }
1515  int w = width();
1516  int h = height()?height():1;
1517  int d = depth()?depth():1;
1518  if (isCubemap())
1519  h=h*6;
1520  else
1521  h=h*d;
1522 
1523  switch(type())
1524  {
1525  case IT_UNSIGNED_BYTE: equalizeTemplate<unsigned char> (pixels(), pitch(), comps, w, h, 0xFF); break;
1526  case IT_UNSIGNED_SHORT: equalizeTemplate<unsigned short>(pixels(), pitch(), comps, w, h, 0xFFFF); break;
1527  case IT_UNSIGNED_INT: equalizeTemplate<unsigned int> (pixels(), pitch(), comps, w, h, 0xFFFFFFFF); break;
1528  case IT_FLOAT: equalizeTemplate<float> (pixels(), pitch(), comps, w, h, 1.0f); break;
1529  break;
1530  default:
1531  Log::error("Image::equalize(): unsupported image type(). Types supported are IT_UNSIGNED_BYTE, IT_UNSIGNED_SHORT, IT_UNSIGNED_INT, IT_FLOAT.\n");
1532  return false;
1533  }
1534  return true;
1535 }
1536 //-----------------------------------------------------------------------------
1558 {
1559  if ( !tags()->has("WindowCenter") || !tags()->has("WindowWidth") || !tags()->has("BitsStored") || !tags()->has("RescaleIntercept"))
1560  return false;
1561 
1562  float center = tags()->value("WindowCenter").toFloat();
1563  float width = tags()->value("WindowWidth").toFloat();
1564  float range = (1<<tags()->value("BitsStored").toInt()) - 1.0f;
1565  float intercept = tags()->value("RescaleIntercept").toFloat();
1566  float slope = tags()->value("RescaleSlope").toFloat();
1567 
1568  // Hounsfield units: -1000 = air, +1000 = solid bone
1569  // Transform from Hounsfield units to normalized 0..1 units
1570  center = (center-intercept) / range / slope;
1571  width = width / range / slope;
1572  return contrast( center-width/2.0f, center+width/2.0f );
1573 }
1574 //-----------------------------------------------------------------------------
1585 bool Image::contrastHounsfield(float center, float width, float intercept, float range)
1586 {
1587  // Hounsfield units: -1000 = air, +1000 = solid bone
1588  // Transform from Hounsfield units to normalized 0..1 units
1589  center = (center-intercept) / range;
1590  width = width / range;
1591  return contrast( center-width/2.0f, center+width/2.0f );
1592 }
1593 //-----------------------------------------------------------------------------
1594 namespace {
1595  template<typename T>
1596  void contrastTemplate(void* ptr, int pitch, int w, int h, T max_val, float black, float white)
1597  {
1598  float range = white-black;
1599  for(int y=0; y<h; ++y)
1600  {
1601  T* px = (T*)((char*)ptr + pitch*y);
1602  for(int x=0; x<w; ++x)
1603  {
1604  float t = (float)px[x]/max_val; // 0..1
1605  t = (t-black)/range;
1606  t = vl::clamp(t, 0.0f, 1.0f);
1607  px[x] = (T)(t*max_val);
1608  }
1609  }
1610  }
1611 }
1614 bool Image::contrast(float black, float white)
1615 {
1616  switch(format())
1617  {
1618  case IF_RED:
1619  case IF_GREEN:
1620  case IF_BLUE:
1621  case IF_ALPHA:
1622  case IF_LUMINANCE:
1623  case IF_DEPTH_COMPONENT:
1624  break;
1625  default:
1626  Log::error("Image::equalize(): unsupported image format().\n");
1627  return false;
1628  }
1629  int w = width();
1630  int h = height()?height():1;
1631  int d = depth()?depth():1;
1632  if (isCubemap())
1633  h=h*6;
1634  else
1635  h=h*d;
1636 
1637  switch(type())
1638  {
1639  case IT_UNSIGNED_BYTE: contrastTemplate<unsigned char> (pixels(), pitch(), w, h, 0xFF, black, white); break;
1640  case IT_UNSIGNED_SHORT: contrastTemplate<unsigned short>(pixels(), pitch(), w, h, 0xFFFF, black, white); break;
1641  case IT_UNSIGNED_INT: contrastTemplate<unsigned int> (pixels(), pitch(), w, h, 0xFFFFFFFF, black, white); break;
1642  case IT_FLOAT: contrastTemplate<float> (pixels(), pitch(), w, h, 1.0f, black, white); break;
1643  break;
1644  default:
1645  Log::error("Image::equalize(): unsupported image type(). Types supported are IT_UNSIGNED_BYTE, IT_UNSIGNED_SHORT, IT_UNSIGNED_INT, IT_FLOAT.\n");
1646  return false;
1647  }
1648  return true;
1649 }
1650 //-----------------------------------------------------------------------------
1651 namespace
1652 {
1653  class rgbal
1654  {
1655  public:
1656  rgbal(): r(-1), g(-1), b(-1), a(-1), l(-1) {}
1657  int r,g,b,a,l;
1658  };
1659 
1660  template<typename T>
1661  void convert(const T*src_px, T*dst_px, T max_value, const rgbal& srco, const rgbal& dsto)
1662  {
1663  // set dst default values first
1664  if (dsto.r != -1)
1665  dst_px[dsto.r] = 0;
1666  if (dsto.g != -1)
1667  dst_px[dsto.g] = 0;
1668  if (dsto.b != -1)
1669  dst_px[dsto.b] = 0;
1670  if (dsto.a != -1)
1671  dst_px[dsto.a] = max_value;
1672  if (dsto.l != -1)
1673  dst_px[dsto.l] = 0;
1674 
1675  // try copy src -> dst
1676  if (dsto.r != -1 && srco.r != -1 )
1677  dst_px[dsto.r] = src_px[srco.r];
1678  if (dsto.g != -1 && srco.g != -1)
1679  dst_px[dsto.g] = src_px[srco.g];
1680  if (dsto.b != -1 && srco.b != -1)
1681  dst_px[dsto.b] = src_px[srco.b];
1682  if (dsto.a != -1 && srco.a != -1)
1683  dst_px[dsto.a] = src_px[srco.a];
1684  if (dsto.l != -1 && srco.l != -1)
1685  dst_px[dsto.l] = src_px[srco.l];
1686 
1687  // try rgb -> gray conversion
1688  if (dsto.l != -1 && srco.r != -1 && srco.g != -1 && srco.b != -1)
1689  {
1690  dvec3 col(src_px[srco.r], src_px[srco.g], src_px[srco.b]);
1691  double gray = dot(col / dvec3(max_value,max_value,max_value), dvec3(0.299,0.587,0.114));
1692  dst_px[dsto.l] = T(gray * max_value);
1693  }
1694  else
1695  // try r -> gray conversion
1696  if (dsto.l != -1 && srco.r != -1 && srco.g == -1 && srco.b == -1)
1697  dst_px[dsto.l] = src_px[srco.r];
1698  else
1699  // try g -> gray conversion
1700  if (dsto.l != -1 && srco.r == -1 && srco.g != -1 && srco.b == -1)
1701  dst_px[dsto.l] = src_px[srco.g];
1702  else
1703  // try b -> gray conversion
1704  if (dsto.l != -1 && srco.r == -1 && srco.g == -1 && srco.b != -1)
1705  dst_px[dsto.l] = src_px[srco.b];
1706  else
1707  // try gray -> r,g,b
1708  if (srco.l != -1)
1709  {
1710  if (dsto.r != -1)
1711  dst_px[dsto.r] = src_px[srco.l];
1712  if (dsto.g != -1)
1713  dst_px[dsto.g] = src_px[srco.l];
1714  if (dsto.b != -1)
1715  dst_px[dsto.b] = src_px[srco.l];
1716  }
1717  }
1718 }
1720 {
1721  switch(type())
1722  {
1723  case IT_UNSIGNED_BYTE:
1724  case IT_BYTE:
1725  case IT_UNSIGNED_SHORT:
1726  case IT_SHORT:
1727  case IT_UNSIGNED_INT:
1728  case IT_INT:
1729  case IT_FLOAT:
1730  break;
1731  default:
1732  Log::error("Image::convertType(): unsupported image type.\n");
1733  return NULL;
1734  }
1735 
1736  switch(format())
1737  {
1738  case IF_RGB:
1739  case IF_RGBA:
1740  case IF_BGR:
1741  case IF_BGRA:
1742  case IF_RED:
1743  case IF_GREEN:
1744  case IF_BLUE:
1745  case IF_ALPHA:
1746  case IF_LUMINANCE:
1747  case IF_LUMINANCE_ALPHA:
1748  break;
1749  default:
1750  Log::error("Image::convertType(): unsupported source image format.\n");
1751  return NULL;
1752  }
1753 
1754  switch(new_format)
1755  {
1756  case IF_RGB:
1757  case IF_RGBA:
1758  case IF_BGR:
1759  case IF_BGRA:
1760  case IF_RED:
1761  case IF_GREEN:
1762  case IF_BLUE:
1763  case IF_ALPHA:
1764  case IF_LUMINANCE:
1765  case IF_LUMINANCE_ALPHA:
1766  break;
1767  default:
1768  Log::error("Image::convertType(): unsupported destination image format.\n");
1769  return NULL;
1770  }
1771 
1772  ref<Image> img = new Image;
1773  img->setObjectName( objectName().c_str() );
1774  img->setFormat(new_format);
1775  img->setType(type());
1776  img->setWidth(width());
1777  img->setHeight(height());
1778  img->setDepth(depth());
1779  img->setByteAlignment(1);
1780  img->mIsCubemap = isCubemap();
1781  img->mIsNormalMap = mIsNormalMap;
1782  img->mHasAlpha = mHasAlpha;
1783  img->allocate();
1784 
1785  rgbal srco; // = {-1,-1,-1,-1,-1},
1786  rgbal dsto; // = {-1,-1,-1,-1,-1};
1787 
1788  // compute src and dst color component offsets
1789 
1790  switch(format())
1791  {
1792  case IF_RGB: srco.r = 0; srco.g = 1; srco.b = 2; break;
1793  case IF_RGBA: srco.r = 0; srco.g = 1; srco.b = 2; srco.a = 3; break;
1794  case IF_BGR: srco.r = 2; srco.g = 1; srco.b = 0; break;
1795  case IF_BGRA: srco.r = 2; srco.g = 1; srco.b = 0; srco.a = 3; break;
1796  case IF_RED: srco.r = 0; break;
1797  case IF_GREEN: srco.g = 0; break;
1798  case IF_BLUE: srco.b = 0; break;
1799  case IF_ALPHA: srco.a = 0; break;
1800  case IF_LUMINANCE: srco.l = 0; break;
1801  case IF_LUMINANCE_ALPHA: srco.l = 0; srco.a = 1; break;
1802  default:
1803  return NULL;
1804  }
1805 
1806  switch(new_format)
1807  {
1808  case IF_RGB: dsto.r = 0; dsto.g = 1; dsto.b = 2; break;
1809  case IF_RGBA: dsto.r = 0; dsto.g = 1; dsto.b = 2; dsto.a = 3; break;
1810  case IF_BGR: dsto.r = 2; dsto.g = 1; dsto.b = 0; break;
1811  case IF_BGRA: dsto.r = 2; dsto.g = 1; dsto.b = 0; dsto.a = 3; break;
1812  case IF_RED: dsto.r = 0; break;
1813  case IF_GREEN: dsto.g = 0; break;
1814  case IF_BLUE: dsto.b = 0; break;
1815  case IF_ALPHA: dsto.a = 0; break;
1816  case IF_LUMINANCE: dsto.l = 0; break;
1817  case IF_LUMINANCE_ALPHA: dsto.l = 0; dsto.a = 1; break;
1818  default:
1819  return NULL;
1820  }
1821 
1822  int src_comp = 0;
1823  switch(format())
1824  {
1825  case IF_RGB: src_comp = 3; break;
1826  case IF_RGBA: src_comp = 4; break;
1827  case IF_BGR: src_comp = 3; break;
1828  case IF_BGRA: src_comp = 4; break;
1829  case IF_RED: src_comp = 1; break;
1830  case IF_GREEN: src_comp = 1; break;
1831  case IF_BLUE: src_comp = 1; break;
1832  case IF_ALPHA: src_comp = 1; break;
1833  case IF_LUMINANCE: src_comp = 1; break;
1834  case IF_LUMINANCE_ALPHA: src_comp = 2; break;
1835  default:
1836  break;
1837  }
1838 
1839  int dst_comp = 0;
1840  switch(new_format)
1841  {
1842  case IF_RGB: dst_comp = 3; break;
1843  case IF_RGBA: dst_comp = 4; break;
1844  case IF_BGR: dst_comp = 3; break;
1845  case IF_BGRA: dst_comp = 4; break;
1846  case IF_RED: dst_comp = 1; break;
1847  case IF_GREEN: dst_comp = 1; break;
1848  case IF_BLUE: dst_comp = 1; break;
1849  case IF_ALPHA: dst_comp = 1; break;
1850  case IF_LUMINANCE: dst_comp = 1; break;
1851  case IF_LUMINANCE_ALPHA: dst_comp = 2; break;
1852  case IF_DEPTH_COMPONENT: dst_comp = 1; break;
1853  default:
1854  break;
1855  }
1856 
1857  int line_count = img->height()?img->height():1;
1858  if (img->depth())
1859  line_count *= img->depth();
1860  else
1861  if (img->isCubemap())
1862  line_count *= 6;
1863 
1864  for(int i=0; i<line_count; ++i)
1865  {
1866  const void* srcLine = pixels() + pitch()*i;
1867  void* dstLine = img->pixels() + img->pitch()*i;
1868 
1869  const unsigned char* srcUByte = (const unsigned char*)srcLine;
1870  const GLbyte* srcSByte = (const GLbyte*)srcLine;
1871  const GLushort* srcUShort = (const GLushort*)srcLine;
1872  const GLshort* srcSShort = (const GLshort*)srcLine;
1873  const unsigned int* srcUInt = (const unsigned int*)srcLine;
1874  const int* srcSInt = (const int*)srcLine;
1875  const float* srcFloat = (const float*)srcLine;
1876 
1877  unsigned char* dstUByte = (unsigned char*)dstLine;
1878  GLbyte* dstSByte = (GLbyte*)dstLine;
1879  GLushort* dstUShort = (GLushort*)dstLine;
1880  GLshort* dstSShort = (GLshort*)dstLine;
1881  unsigned int* dstUInt = (unsigned int*)dstLine;
1882  int* dstSInt = (int*)dstLine;
1883  float* dstFloat = (float*)dstLine;
1884 
1885  for(int j=0; j<img->width(); ++j)
1886  {
1887  switch(type())
1888  {
1889  case IT_UNSIGNED_BYTE: convert<unsigned char> (srcUByte, dstUByte, 255, srco, dsto); srcUByte+=src_comp; dstUByte+=dst_comp; break;
1890  case IT_BYTE: convert<GLbyte> (srcSByte, dstSByte, 127, srco, dsto); srcSByte+=src_comp; dstSByte+=dst_comp; break;
1891  case IT_UNSIGNED_SHORT: convert<GLushort> (srcUShort, dstUShort, 65535, srco, dsto); srcUShort+=src_comp; dstUShort+=dst_comp; break;
1892  case IT_SHORT: convert<GLshort> (srcSShort, dstSShort, 32767, srco, dsto); srcSShort+=src_comp; dstSShort+=dst_comp; break;
1893  case IT_UNSIGNED_INT: convert<unsigned int> (srcUInt, dstUInt, 4294967295U, srco, dsto); srcUInt+=src_comp; dstUInt+=dst_comp; break;
1894  case IT_INT: convert<int> (srcSInt, dstSInt, 2147483647, srco, dsto); srcSInt+=src_comp; dstSInt+=dst_comp; break;
1895  case IT_FLOAT: convert<float> (srcFloat, dstFloat, 1.0f, srco, dsto); srcFloat+=src_comp; dstFloat+=dst_comp; break;
1896  default:
1897  return NULL;
1898  }
1899  }
1900  }
1901 
1902  return img;
1903 }
1904 //-----------------------------------------------------------------------------
1906 {
1907  if (x < 0)
1908  x = 0;
1909  if (x >= width()-1)
1910  x = (width()-1) - 0.000001;
1911 
1912  int ix1 = (int)x;
1913  int ix2 = ix1+1;
1914 
1915  VL_CHECK(ix2<(int)width())
1916 
1917  float w21 = (float)vl::fract(x);
1918  float w11 = 1.0f - w21;
1919 
1920  fvec4 c11 = sample(ix1);
1921  fvec4 c21 = sample(ix2);
1922 
1923  return c11*w11 + c21*w21;
1924 }
1925 //-----------------------------------------------------------------------------
1926 fvec4 Image::sampleLinear(double x, double y) const
1927 {
1928  int h = height()?height():1;
1929  if (x < 0)
1930  x = 0;
1931  if (y < 0)
1932  y = 0;
1933  if (x >= width()-1)
1934  x = (width()-1) - 0.000001;
1935  if (y >= h-1)
1936  y = (h-1) - 0.000001;
1937 
1938  int ix1 = (int)x;
1939  int iy1 = (int)y;
1940  int ix2 = ix1+1;
1941  int iy2 = iy1+1;
1942 
1943  VL_CHECK(ix2<(int)width())
1944  VL_CHECK(iy2<(int)height())
1945 
1946  double tx = vl::fract(x);
1947  double ty = vl::fract(y);
1948  double tx1 = 1.0f - vl::fract(x);
1949  double ty1 = 1.0f - vl::fract(y);
1950 
1951  float w11 = float(tx1*ty1);
1952  float w12 = float(tx1*ty);
1953  float w22 = float(tx *ty);
1954  float w21 = float(tx *ty1);
1955 
1956  fvec4 c11 = sample(ix1, iy1);
1957  fvec4 c12 = sample(ix1, iy2);
1958  fvec4 c22 = sample(ix2, iy2);
1959  fvec4 c21 = sample(ix2, iy1);
1960 
1961  return c11*w11 + c12*w12 + c22*w22 + c21*w21;
1962 }
1963 //-----------------------------------------------------------------------------
1964 fvec4 Image::sampleLinear(double x, double y, double z) const
1965 {
1966  if (x>width() -1.000001) x = width() -1.000001;
1967  if (y>height()-1.000001) y = height()-1.000001;
1968  if (z>depth() -1.000001) z = depth() -1.000001;
1969  if (x<0) x=0;
1970  if (y<0) y=0;
1971  if (z<0) z=0;
1972  int ix = int(x);
1973  float xt = float(x - ix);
1974  int iy = int(y);
1975  float yt = float(y - iy);
1976  int iz = int(z);
1977  float zt = float(z - iz);
1978  fvec4 val0 = sample(ix , iy, iz);
1979  fvec4 val1 = sample(ix+1, iy, iz);
1980  fvec4 val2 = sample(ix+1, iy+1, iz);
1981  fvec4 val3 = sample(ix, iy+1, iz);
1982  fvec4 val4 = sample(ix , iy, iz+1);
1983  fvec4 val5 = sample(ix+1, iy, iz+1);
1984  fvec4 val6 = sample(ix+1, iy+1, iz+1);
1985  fvec4 val7 = sample(ix, iy+1, iz+1);
1986  float xt1 = 1-xt;
1987  float yt1 = 1-yt;
1988  float zt1 = 1-zt;
1989  fvec4 v1 = val0*(yt1) + val3*yt;
1990  fvec4 v2 = val1*(yt1) + val2*yt;
1991  fvec4 a = v1*(xt1) + v2*xt;
1992  v1 = val4*(yt1) + val7*yt;
1993  v2 = val5*(yt1) + val6*yt;
1994  fvec4 b = v1*(xt1) + v2*xt;
1995  return a*(zt1) + b*zt;
1996 }
1997 //-----------------------------------------------------------------------------
1998 fvec4 Image::sample(int x, int y, int z) const
1999 {
2000  VL_CHECK(x<width())
2001  VL_CHECK(!y || y<height())
2002  VL_CHECK(!z || z<depth())
2003 
2004  // find the start of the line
2005  int h = height()?height():1;
2006  const unsigned char* px = pixels() + y*pitch() + h*pitch()*z;
2007 
2008  int comp = 0;
2009  switch(format())
2010  {
2011  case IF_RGB: comp = 3; break;
2012  case IF_RGBA: comp = 4; break;
2013  case IF_BGR: comp = 3; break;
2014  case IF_BGRA: comp = 4; break;
2015  case IF_RED: comp = 1; break;
2016  case IF_GREEN: comp = 1; break;
2017  case IF_BLUE: comp = 1; break;
2018  case IF_ALPHA: comp = 1; break;
2019  case IF_LUMINANCE: comp = 1; break;
2020  case IF_LUMINANCE_ALPHA: comp = 2; break;
2021  case IF_DEPTH_COMPONENT: comp = 1; break;
2022  default:
2023  break;
2024  }
2025 
2026  switch(type())
2027  {
2028  case IT_UNSIGNED_BYTE: px += x*comp*1; break;
2029  case IT_BYTE: px += x*comp*1; break;
2030  case IT_UNSIGNED_SHORT: px += x*comp*2; break;
2031  case IT_SHORT: px += x*comp*2; break;
2032  case IT_UNSIGNED_INT: px += x*comp*4; break;
2033  case IT_INT: px += x*comp*4; break;
2034  case IT_FLOAT: px += x*comp*4; break;
2035  default:
2036  break;
2037  }
2038 
2039  // convert component by component
2040 
2041  fvec4 pixel(0,0,0,0);
2042 
2043  for(int i=0; i<comp; ++i)
2044  {
2045  double value = 0;
2046 
2047  switch(type())
2048  {
2049  case IT_UNSIGNED_BYTE: value = (double)((unsigned char*)px)[i]; value/=255.0; break;
2050  case IT_BYTE: value = (double)((char*)px)[i]; value/=127.0; break;
2051  case IT_UNSIGNED_SHORT: value = (double)((unsigned short*)px)[i]; value/=65535.0; break;
2052  case IT_SHORT: value = (double)((short*)px)[i]; value/=32767.0; break;
2053  case IT_UNSIGNED_INT: value = (double)((unsigned int*)px)[i]; value/=4294967295.0; break;
2054  case IT_INT: value = (double)((int*)px)[i]; value/=2147483647.0; break;
2055  case IT_FLOAT: value = (double)((float*)px)[i]; break;
2056  default:
2057  break;
2058  }
2059 
2060  pixel[i] = (float)value;
2061  }
2062 
2063  fvec4 p(0,0,0,0);
2064 
2065  // arrange values based on the format
2066  switch(format())
2067  {
2068  case IF_RGB: p = pixel; break;
2069  case IF_RGBA: p = pixel; break;
2070  case IF_BGR: p = pixel; p.r() = pixel.b(); p.b() = pixel.r(); break;
2071  case IF_BGRA: p = pixel; p.r() = pixel.b(); p.b() = pixel.r(); break;
2072  case IF_RED: p = fvec4(pixel[0], 0, 0, 0); break;
2073  case IF_GREEN: p = fvec4(0, pixel[0], 0, 0); break;
2074  case IF_BLUE: p = fvec4(0, 0, pixel[0], 0); break;
2075  case IF_ALPHA: p = fvec4(0, 0, 0, pixel[0]); break;
2076  case IF_LUMINANCE: p = fvec4(pixel[0], pixel[0], pixel[0], 0); break;
2077  case IF_LUMINANCE_ALPHA: p = fvec4(pixel[0], pixel[0], pixel[0], pixel[1]); break;
2078  case IF_DEPTH_COMPONENT: p = fvec4(pixel[0], 0, 0, 0); break;
2079  default:
2080  break;
2081  }
2082 
2083  return p;
2084 }
2085 //-----------------------------------------------------------------------------
2086 ref<Image> Image::subImage(int xstart, int ystart, int width, int height)
2087 {
2088  VL_CHECK(xstart+width <= this->width())
2089  VL_CHECK(ystart+height <= this->height())
2090 
2091  ref<Image> img = new Image;
2092  img->allocate2D(width, height, 1, format(), type());
2093  // copy line by line
2094  for(int i=0; i<height; ++i)
2095  {
2096  unsigned char* dst = img->pixels() + img->pitch()*i;
2097  unsigned char* src = pixels() + pitch()*(i+ystart) + xstart*bitsPerPixel()/8;
2098  memcpy(dst, src, width*bitsPerPixel()/8);
2099  }
2100  return img;
2101 }
2102 //-----------------------------------------------------------------------------
2103 void Image::copySubImage(Image* img_src, RectI src, ivec2 dst)
2104 {
2105  ref<Image> img = img_src;
2106  if (img->type() != this->type())
2107  img = img->convertType(this->type());
2108  if (img->format() != this->format())
2109  img = img->convertFormat(this->format());
2110  // tests
2111  VL_CHECK(dst.x()>=0)
2112  VL_CHECK(dst.y()>=0)
2113  VL_CHECK(dst.x() + src.width() <= this->width() )
2114  VL_CHECK(dst.y() + src.height() <= this->height())
2115  VL_CHECK(src.x()>=0)
2116  VL_CHECK(src.y()>=0)
2117  VL_CHECK(src.right() < img->width() )
2118  VL_CHECK(src.top() < img->height())
2119  for(int i=0; i<src.height(); ++i)
2120  {
2121  int ysrc = i+src.y();
2122  int ydst = i+dst.y();
2123  unsigned char* psrc = img->pixels() + img->pitch()*ysrc + (src.x()*img->bitsPerPixel()/8);
2124  unsigned char* pdst = this->pixels() + this->pitch()*ydst + (dst.x()*this->bitsPerPixel()/8);
2125  memcpy(pdst, psrc, src.width()*this->bitsPerPixel()/8);
2126  }
2127 }
2128 //-----------------------------------------------------------------------------
2129 void Image::substituteColorRGB_RGBA(unsigned int before, unsigned int after)
2130 {
2131  if (type() != IT_UNSIGNED_BYTE)
2132  {
2133  Log::error("Image::substituteColorRGB_RGBA(): this function can be called only on images whose type() is IT_UNSIGNED_BYTE\n");
2134  return;
2135  }
2136  if (format() != IF_RGBA && format() != IF_RGB)
2137  {
2138  Log::error("Image::substituteColorRGB_RGBA(): this function can be called only on images whose format() is either IF_RGBA or IF_RGB\n");
2139  return;
2140  }
2141  unsigned char bef[3];
2142  unsigned char aft[4];
2143  bef[0] = (unsigned char)((before >> 16) & 0xFF);
2144  bef[1] = (unsigned char)((before >> 8) & 0xFF);
2145  bef[2] = (unsigned char)((before >> 0) & 0xFF);
2146 
2147  aft[0] = (unsigned char)((after >> 24) & 0xFF);
2148  aft[1] = (unsigned char)((after >> 16) & 0xFF);
2149  aft[2] = (unsigned char)((after >> 8) & 0xFF);
2150  aft[3] = (unsigned char)((after >> 0) & 0xFF);
2151 
2152  int comps = format() == IF_RGBA ? 4 : 3;
2153  int d = depth() ? depth() : 1;
2154  for(int y=0; y<height()*d; ++y)
2155  {
2156  for(int x=0; x<width(); ++x)
2157  {
2158  unsigned char* px = pixels() + pitch()*y + x*comps;
2159  if (px[0] == bef[0] && px[1] == bef[1] && px[2] == bef[2])
2160  {
2161  px[0] = aft[0];
2162  px[1] = aft[1];
2163  px[2] = aft[2];
2164  if (comps == 4)
2165  px[3] = aft[3];
2166  }
2167  }
2168  }
2169 }
2170 //-----------------------------------------------------------------------------
2171 void Image::substituteColorRGB_RGB(unsigned int before, unsigned int after)
2172 {
2173  if (type() != IT_UNSIGNED_BYTE)
2174  {
2175  Log::error("Image::substituteColorRGB_RGB(): this function can be called only on images whose type() is IT_UNSIGNED_BYTE\n");
2176  return;
2177  }
2178  if (format() != IF_RGBA && format() != IF_RGB)
2179  {
2180  Log::error("Image::substituteColorRGB_RGB(): this function can be called only on images whose format() is either IF_RGBA or IF_RGB\n");
2181  return;
2182  }
2183  unsigned char bef[3];
2184  unsigned char aft[3];
2185  bef[0] = (unsigned char)((before >> 16) & 0xFF);
2186  bef[1] = (unsigned char)((before >> 8) & 0xFF);
2187  bef[2] = (unsigned char)((before >> 0) & 0xFF);
2188 
2189  aft[0] = (unsigned char)((after >> 24) & 0xFF);
2190  aft[1] = (unsigned char)((after >> 16) & 0xFF);
2191  aft[2] = (unsigned char)((after >> 8) & 0xFF);
2192 
2193  int comps = format() == IF_RGBA ? 4 : 3;
2194  int d = depth() ? depth() : 1;
2195  for(int y=0; y<height()*d; ++y)
2196  {
2197  for(int x=0; x<width(); ++x)
2198  {
2199  unsigned char* px = pixels() + pitch()*y + x*comps;
2200  if (px[0] == bef[0] && px[1] == bef[1] && px[2] == bef[2])
2201  {
2202  px[0] = aft[0];
2203  px[1] = aft[1];
2204  px[2] = aft[2];
2205  }
2206  }
2207  }
2208 }
2209 //-----------------------------------------------------------------------------
2210 void Image::substituteColorGreenKey(unsigned int col0, unsigned int col1)
2211 {
2212  if (type() != IT_UNSIGNED_BYTE)
2213  {
2214  Log::error("Image::substituteColorRGB_RGB(): this function can be called only on images whose type() is IT_UNSIGNED_BYTE\n");
2215  return;
2216  }
2217  if (format() != IF_RGBA && format() != IF_RGB)
2218  {
2219  Log::error("Image::substituteColorRGB_RGB(): this function can be called only on images whose format() is either IF_RGBA or IF_RGB\n");
2220  return;
2221  }
2222  unsigned char c0[3];
2223  unsigned char c1[3];
2224  c0[0] = (unsigned char)((col0 >> 16) & 0xFF);
2225  c0[1] = (unsigned char)((col0 >> 8) & 0xFF);
2226  c0[2] = (unsigned char)((col0 >> 0) & 0xFF);
2227 
2228  c1[0] = (unsigned char)((col1 >> 16) & 0xFF);
2229  c1[1] = (unsigned char)((col1 >> 8) & 0xFF);
2230  c1[2] = (unsigned char)((col1 >> 0) & 0xFF);
2231 
2232  int comps = format() == IF_RGBA ? 4 : 3;
2233  int d = depth() ? depth() : 1;
2234  for(int y=0; y<height()*d; ++y)
2235  {
2236  for(int x=0; x<width(); ++x)
2237  {
2238  unsigned char* px = pixels() + pitch()*y + x*comps;
2239  double t = (double)px[1] / 0xFF;
2240  px[0] = (unsigned char)(c0[0]*(1.0-t) + c1[0]*t);
2241  px[1] = (unsigned char)(c0[1]*(1.0-t) + c1[1]*t);
2242  px[2] = (unsigned char)(c0[2]*(1.0-t) + c1[2]*t);
2243  }
2244  }
2245 }
2246 //-----------------------------------------------------------------------------
static void debug(const String &message)
Use this function to provide extra information useful to investigate and solve problems.
Definition: Log.cpp:144
String toLowerCase() const
Returns the lower-case version of a String.
Definition: String.cpp:755
long long read(void *buffer, long long byte_count)
Reads byte_count bytes from a file. Returns the number of bytes actually read.
Definition: VirtualFile.cpp:82
float clamp(float x, float minval, float maxval)
Definition: Vector2.hpp:315
int isCompressedFormat(EImageFormat fmt)
Definition: Image.cpp:515
VLCORE_EXPORT FileSystem * defFileSystem()
Returns the default FileSystem used by VisualizationLibrary.
Definition: init_core.cpp:153
int depth() const
Definition: Image.hpp:211
void updatePitch()
Definition: Image.cpp:573
const T * get() const
Definition: Object.hpp:128
An abstract class representing a file.
Definition: VirtualFile.hpp:60
Vector4< float > fvec4
A 4 components vector with float precision.
Definition: Vector4.hpp:279
The RectI class represents a 2D rectangular area using int precision.
Definition: Rect.hpp:163
A simple String formatting class.
Definition: Say.hpp:124
const unsigned char * pixels() const
Raw pointer to pixels.
Definition: Image.hpp:170
void setObjectName(const char *name)
The name of the object, by default set to the object&#39;s class name in debug builds.
Definition: Object.hpp:220
Vector4< unsigned char > ubvec4
A 4 components vector with unsigned char precision.
Definition: Vector4.hpp:285
void setHeight(int y)
Definition: Image.hpp:126
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
VLCORE_EXPORT ref< Image > loadRAW(VirtualFile *file, long long file_offset, int width, int height, int depth, int bytealign, EImageFormat format, EImageType type)
Loads a raw image file.
Definition: Image.cpp:1280
ref< Image > convertType(EImageType new_type) const
Converts the type() of an image.
Definition: Image.cpp:1303
const T_Scalar & r() const
Definition: Vector4.hpp:111
void copySubImage(Image *img_src, RectI src, ivec2 dst)
Copies the rectangular area specified by src of img_src into an Image at position dst...
Definition: Image.cpp:2103
void setByteAlignment(int bytealign)
Modifies the byte-alignment of the rows of the image, thus changing its pitch.
Definition: Image.cpp:550
T fract(T a)
Definition: glsl_math.hpp:724
ref< Buffer > mPixels
Definition: Image.hpp:381
virtual bool isOpen() const =0
Returns true if the file has been opened.
VLCORE_EXPORT ref< Image > 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)
Loads six images and assembles them into a cubemap image.
Definition: Image.cpp:1260
int alphaBits() const
The number of bits dedicated to the alpha channel.
Definition: Image.cpp:449
bool contrastHounsfield(float center, float width, float intercept, float range)
Adjusts the contrast of an image using the window-center/window-width method used for CT images...
Definition: Image.cpp:1585
EImageFormat mFormat
Definition: Image.hpp:390
String value(const String &key) const
Definition: KeyValues.cpp:44
ref< ResourceDatabase > loadResource(const String &path, bool quick=true) const
Loads the resource specified by the given path using the appropriate ResourceLoadWriter.
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:164
String print() const
Definition: Image.cpp:350
virtual ref< VirtualFile > locateFile(const String &full_path, const String &alternate_path=String()) const
Looks for a VirtualFile on the disk and in the currently active FileSystem.
Definition: FileSystem.cpp:61
ref< Image > subImage(int xstart, int ystart, int width, int height)
Creates a new image containing the specified rectangular pixel area taken from the source image...
Definition: Image.cpp:2086
std::vector< ref< Image > > mMipmaps
Definition: Image.hpp:384
bool contrastHounsfieldAuto()
Adjusts the contrast of an image using the window-center/window-width method used for CT images...
Definition: Image.cpp:1557
Implements a buffer whose storage is in local memory.
Definition: Buffer.hpp:46
VLCORE_EXPORT bool loadImagesFromDir(const String &dir_path, const String &ext, std::vector< ref< Image > > &images)
Loads all the images with the specified extension from the given directory.
Definition: Image.cpp:1179
void setType(EImageType type)
Definition: Image.hpp:132
int requiredMemory() const
Returns the number of bytes requested to store the image.
Definition: Image.cpp:532
VLCORE_EXPORT ref< Image > makeColorSpectrum(size_t width, const std::vector< fvec4 > &colors)
Creates a 1D Image whose color is interpolated from left to right from the specified spectrum...
Definition: Image.cpp:1134
virtual ~Image()
Definition: Image.cpp:51
int mDepth
Definition: Image.hpp:387
bool isValid() const
Returns true if the image has valid width/height/depth, pitch and byte alignment, type/format combina...
Definition: Image.cpp:135
int bitsPerPixel() const
Definition: Image.hpp:104
int toInt(bool hex=false) const
Returns the int number represented by the string. The conversion is done using the standard atoi() fu...
Definition: String.cpp:1352
VLCORE_EXPORT ref< Image > loadImage(VirtualFile *file)
Loads an image from the specified file.
Definition: Image.cpp:1214
virtual void close()=0
Closes the file.
void substituteColorGreenKey(unsigned int col0, unsigned int col1)
Definition: Image.cpp:2210
void allocate3D(int x, int y, int z, int bytealign, EImageFormat format, EImageType type)
Definition: Image.cpp:631
String printFormat() const
Definition: Image.cpp:323
const String & path() const
Returns the path of the file.
Definition: VirtualFile.hpp:98
void setDepth(int z)
Definition: Image.hpp:128
int byteAlignment() const
Returns the byte-alignment of the row of the image.
Definition: Image.cpp:540
VLCORE_EXPORT ref< Image > assemble3DImage(const std::vector< ref< Image > > &images)
Assembles the given 2D images in a single 2D image, all the images must be 2D images and have the sam...
Definition: Image.cpp:1151
unsigned char * pixelsXN()
X-negative cubemap face.
Definition: Image.cpp:764
void setFilePath(const String &path)
The file from which the image was loaded.
Definition: Image.hpp:374
Visualization Library main namespace.
T height() const
Definition: Rect.hpp:72
ref< Image > createCubemap(const Image *xp, const Image *xn, const Image *yp, const Image *yn, const Image *zp, const Image *zn)
Assembles a cubemap image.
Definition: Image.cpp:858
void allocate()
Definition: Image.cpp:580
float dot(float a, float b)
Definition: glsl_math.hpp:1111
virtual ref< VirtualDirectory > locateDirectory(const String &name) const
Definition: FileSystem.cpp:96
T width() const
Definition: Rect.hpp:71
unsigned char * pixelsZN()
Z-negative cubemap face.
Definition: Image.cpp:836
void allocate1D(int x, EImageFormat format, EImageType type)
Definition: Image.cpp:586
bool equalize()
Equalizes the image. Returns false if the image format() or type() is not supported. This function supports both 3D images and cubemaps.
Definition: Image.cpp:1495
Image & operator=(const Image &other)
Definition: Image.cpp:708
static void bug(const String &message)
Use this function to provide information about programming errors: wrong parameter initialization...
Definition: Log.cpp:174
String printType() const
Definition: Image.cpp:289
int height() const
Definition: Image.hpp:209
#define VL_TRAP()
Definition: checks.hpp:70
The Vector3 class is a template class that implements a generic 3 components vector, see also vl::fvec3, vl::dvec3, vl::uvec3, vl::ivec3, vl::svec3, vl::usvec3, vl::bvec3, vl::ubvec3.
Definition: Vector3.hpp:44
const KeyValues * tags() const
A set of key/value couples that can be used to attach extra information to an image like DICOM inform...
Definition: Image.hpp:151
unsigned char * pixelsZP()
Z-positive cubemap face.
Definition: Image.cpp:818
const std::vector< ref< Object > > & resources() const
VLCORE_EXPORT bool saveImage(Image *img, VirtualFile *file)
Writes an image on the specified file.
Definition: Image.cpp:1250
The base class for all the reference counted objects.
Definition: Object.hpp:158
float toFloat() const
Returns the float number represented by the string. The conversion is done using the standard atof() ...
Definition: String.hpp:348
EImageDimension dimension() const
Definition: Image.cpp:372
void get(std::vector< ref< T > > &resources, bool clear_vector=true)
Returns all the objects of the specified type in the given vector.
Implements the OpenGL Shading Language convenience functions for scalar and vector operations...
int mPitch
Definition: Image.hpp:388
The type is implicitly defined by the EImageFormat value, for ex.
fvec4 sampleLinear(double x) const
Performs a sampling on a 1d image using linear filtering.
Definition: Image.cpp:1905
EImageDimension
Vector3< double > dvec3
A 3 components vector with double precision.
Definition: Vector3.hpp:254
int width() const
Definition: Image.hpp:207
VLCORE_EXPORT ref< Image > makeNonUniformColorSpectrum(size_t width, size_t col_count, const fvec4 *colors, const float *col_pos)
Creates a 1D Image whose color is interpolated from left to right from the specified spectrum...
Definition: Image.cpp:1089
T x() const
Definition: Rect.hpp:69
bool empty() const
Returns true if length() == 0.
Definition: String.hpp:136
virtual bool open(EOpenMode mode)=0
Opens the file in the specified mode.
unsigned char * pixelsYP()
Y-positive cubemap face.
Definition: Image.cpp:782
int pitch() const
Definition: Image.hpp:213
EImageFormat
const T_Scalar & b() const
Definition: Vector4.hpp:113
void setFormat(EImageFormat format)
Definition: Image.hpp:130
Image()
Constructor.
Definition: Image.cpp:56
#define NULL
Definition: OpenGLDefs.hpp:81
int mHeight
Definition: Image.hpp:386
bool mIsCubemap
Definition: Image.hpp:392
EImageType mType
Definition: Image.hpp:391
EImageType
T y() const
Definition: Rect.hpp:70
bool seekSet(long long offset)
Changes the current read/write position of a file.
unsigned char * pixelsYN()
Y-negative cubemap face.
Definition: Image.cpp:800
bool mIsNormalMap
Definition: Image.hpp:393
int right() const
Definition: Rect.hpp:174
const std::string & objectName() const
The name of the object, by default set to the object&#39;s class name.
Definition: Object.hpp:217
bool mHasAlpha
Definition: Image.hpp:394
ref< Image > convertFormat(EImageFormat new_format) const
Converts the format() of an image.
Definition: Image.cpp:1719
virtual void listFiles(std::vector< String > &file_list, bool append=false) const =0
void substituteColorRGB_RGB(unsigned int before, unsigned int after)
Substitutes the color &#39;before&#39; with the new color &#39;after&#39;.
Definition: Image.cpp:2171
void allocateCubemap(int x, int y, int bytealign, EImageFormat format, EImageType type)
Definition: Image.cpp:655
int mWidth
Definition: Image.hpp:385
int top() const
Definition: Rect.hpp:173
EImageType type() const
Definition: Image.hpp:217
void setWidth(int x)
Definition: Image.hpp:124
bool contrast(float black, float white)
Adjusts the contrast of an image. Returns false if the image format() or type() is not supported...
Definition: Image.cpp:1614
Implements a generic 1d, 2d, 3d and cubemap image that can have mipmaps.
Definition: Image.hpp:54
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
const T_Scalar & x() const
Definition: Vector2.hpp:132
void substituteColorRGB_RGBA(unsigned int before, unsigned int after)
Substitutes the color &#39;before&#39; with the new color &#39;after&#39;.
Definition: Image.cpp:2129
void allocate2D(int x, int y, int bytealign, EImageFormat format, EImageType type)
Definition: Image.cpp:608
String mFilePath
Definition: Image.hpp:383
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
std::string mObjectName
Definition: Object.hpp:300
int mByteAlign
Definition: Image.hpp:389
unsigned char * pixelsXP()
X-positive cubemap face.
Definition: Image.cpp:746
const T_Scalar & y() const
Definition: Vector2.hpp:133
fvec4 sample(int x, int y=0, int z=0) const
Returns the color associated to the specified pixel.
Definition: Image.cpp:1998
#define VL_CHECK(expr)
Definition: checks.hpp:73
void flipVertically()
Definition: Image.cpp:942
static int bitsPerPixel(EImageType type, EImageFormat format)
Returns the number of bits used to represents one pixel.
Definition: Image.cpp:382
unsigned char * pixelsZSlice(int zth_slice)
Zth slice of 3D image.
Definition: Image.cpp:846
static int requiredMemory2D(int x, int y, int bytealign, EImageFormat format, EImageType type)
Definition: Image.hpp:112
void reset()
Disposes all the pixel data and resets the image settings to its defaults.
Definition: Image.cpp:689
VLCORE_EXPORT LoadWriterManager * defLoadWriterManager()
Returs the default LoadWriterManager used by Visualization Library.
Definition: init_core.cpp:138
EImageFormat format() const
Definition: Image.hpp:215
The ResourceDatabase class contains and manipulates a set of resources.
bool writeResource(const String &path, ResourceDatabase *resource) const
Writes the resource specified by the given file using the appropriate ResourceLoadWriter.
bool isCubemap() const
Definition: Image.hpp:78