ImageUtils 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSG_IMAGEUTILS
  14. #define OSG_IMAGEUTILS 1
  15. #include <osg/Export>
  16. #include <osg/Image>
  17. #include <osg/Vec3i>
  18. namespace osg {
  19. template <typename T, class O>
  20. void _readRow(unsigned int num, GLenum pixelFormat, const T* data, O& operation)
  21. {
  22. switch(pixelFormat)
  23. {
  24. case(GL_INTENSITY): { for(unsigned int i=0;i<num;++i) { T v=*data++; operation.rgba( operation.cast(v),operation.cast(v),operation.cast(v),operation.cast(v)); } } break;
  25. case(GL_LUMINANCE): { for(unsigned int i=0;i<num;++i) { operation.luminance(operation.cast(*data++)); } } break;
  26. case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { operation.alpha(operation.cast(*data++)); } } break;
  27. case(GL_LUMINANCE_ALPHA): { for(unsigned int i=0;i<num;++i) { T l=*data++; T a = *data++; operation.luminance_alpha(operation.cast(l),operation.cast(a)); } } break;
  28. case(GL_RGB): { for(unsigned int i=0;i<num;++i) { T r=*data++; T g=*data++; T b=*data++; operation.rgb(operation.cast(r),operation.cast(g),operation.cast(b)); } } break;
  29. case(GL_RGBA): { for(unsigned int i=0;i<num;++i) { T r=*data++; T g=*data++; T b=*data++; T a=*data++; operation.rgba(operation.cast(r),operation.cast(g),operation.cast(b),operation.cast(a)); } } break;
  30. case(GL_BGR): { for(unsigned int i=0;i<num;++i) { T b=*data++; T g=*data++; T r=*data++; operation.rgb(operation.cast(r),operation.cast(g),operation.cast(b)); } } break;
  31. case(GL_BGRA): { for(unsigned int i=0;i<num;++i) { T b=*data++; T g=*data++; T r=*data++; T a=*data++; operation.rgba(operation.cast(r),operation.cast(g),operation.cast(b),operation.cast(a)); } } break;
  32. }
  33. }
  34. template <class O>
  35. void readRow(unsigned int num, GLenum pixelFormat, GLenum dataType, const unsigned char* data, O& operation)
  36. {
  37. switch(dataType)
  38. {
  39. case(GL_BYTE): _readRow(num, pixelFormat, (const char*)data, operation); break;
  40. case(GL_UNSIGNED_BYTE): _readRow(num, pixelFormat, (const unsigned char*)data, operation); break;
  41. case(GL_SHORT): _readRow(num, pixelFormat, (const short*) data, operation); break;
  42. case(GL_UNSIGNED_SHORT): _readRow(num, pixelFormat, (const unsigned short*)data, operation); break;
  43. case(GL_INT): _readRow(num, pixelFormat, (const int*) data, operation); break;
  44. case(GL_UNSIGNED_INT): _readRow(num, pixelFormat, (const unsigned int*) data, operation); break;
  45. case(GL_FLOAT): _readRow(num, pixelFormat, (const float*) data, operation); break;
  46. case(GL_DOUBLE): _readRow(num, pixelFormat, (const double*) data, operation); break;
  47. }
  48. }
  49. template <class O>
  50. void readImage(const osg::Image* image, O& operation)
  51. {
  52. if (!image) return;
  53. for(int r=0;r<image->r();++r)
  54. {
  55. for(int t=0;t<image->t();++t)
  56. {
  57. readRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation);
  58. }
  59. }
  60. }
  61. /** Convenience method for making it easy to cast all pixel channels types to a unit float RGBA form.*/
  62. struct CastAndScaleToFloatOperation
  63. {
  64. float cast(char v) { return static_cast<float>(v)*(1.0f/128.0f); }
  65. float cast(unsigned char v) { return static_cast<float>(v)*(1.0f/255.0f); }
  66. float cast(short v) { return static_cast<float>(v)*(1.0f/32768.0f); }
  67. float cast(unsigned short v) { return static_cast<float>(v)*(1.0f/65535.0f); }
  68. float cast(int v) { return static_cast<float>(v)*(1.0f/2147483648.0f); }
  69. float cast(unsigned int v) { return static_cast<float>(v)*(1.0f/4294967295.0f); }
  70. float cast(float v) { return v; }
  71. float cast(double v) { return static_cast<double>(v); }
  72. };
  73. #if 0
  74. template <typename T, class O>
  75. void _readRow(unsigned int num, GLenum pixelFormat, const T* data,float scale, O& operation)
  76. {
  77. switch(pixelFormat)
  78. {
  79. case(GL_LUMINANCE): { for(unsigned int i=0;i<num;++i) { float l = float(*data++)*scale; operation.luminance(l); } } break;
  80. case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { float a = float(*data++)*scale; operation.alpha(a); } } break;
  81. case(GL_LUMINANCE_ALPHA): { for(unsigned int i=0;i<num;++i) { float l = float(*data++)*scale; float a = float(*data++)*scale; operation.luminance_alpha(l,a); } } break;
  82. case(GL_RGB): { for(unsigned int i=0;i<num;++i) { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; operation.rgb(r,g,b); } } break;
  83. case(GL_RGBA): { for(unsigned int i=0;i<num;++i) { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; float a = float(*data++)*scale; operation.rgba(r,g,b,a); } } break;
  84. case(GL_BGR): { for(unsigned int i=0;i<num;++i) { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; operation.rgb(r,g,b); } } break;
  85. case(GL_BGRA): { for(unsigned int i=0;i<num;++i) { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; float a = float(*data++)*scale; operation.rgba(r,g,b,a); } } break;
  86. }
  87. }
  88. template <class O>
  89. void readRow(unsigned int num, GLenum pixelFormat, GLenum dataType, const unsigned char* data, O& operation)
  90. {
  91. switch(dataType)
  92. {
  93. case(GL_BYTE): _readRow(num,pixelFormat, (const char*)data, 1.0f/128.0f, operation); break;
  94. case(GL_UNSIGNED_BYTE): _readRow(num,pixelFormat, (const unsigned char*)data, 1.0f/255.0f, operation); break;
  95. case(GL_SHORT): _readRow(num,pixelFormat, (const short*) data, 1.0f/32768.0f, operation); break;
  96. case(GL_UNSIGNED_SHORT): _readRow(num,pixelFormat, (const unsigned short*)data, 1.0f/65535.0f, operation); break;
  97. case(GL_INT): _readRow(num,pixelFormat, (const int*) data, 1.0f/2147483648.0f, operation); break;
  98. case(GL_UNSIGNED_INT): _readRow(num,pixelFormat, (const unsigned int*) data, 1.0f/4294967295.0f, operation); break;
  99. case(GL_FLOAT): _readRow(num,pixelFormat, (const float*) data, 1.0f, operation); break;
  100. }
  101. }
  102. template <class O>
  103. void readImage(const osg::Image* image, O& operation)
  104. {
  105. if (!image) return;
  106. for(int r=0;r<image->r();++r)
  107. {
  108. for(int t=0;t<image->t();++t)
  109. {
  110. readRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation);
  111. }
  112. }
  113. }
  114. #endif
  115. // example ModifyOperator
  116. // struct ModifyOperator
  117. // {
  118. // inline void luminance(float& l) const {}
  119. // inline void alpha(float& a) const {}
  120. // inline void luminance_alpha(float& l,float& a) const {}
  121. // inline void rgb(float& r,float& g,float& b) const {}
  122. // inline void rgba(float& r,float& g,float& b,float& a) const {}
  123. // };
  124. template <typename T, class M>
  125. void _modifyRow(unsigned int num, GLenum pixelFormat, T* data,float scale, const M& operation)
  126. {
  127. float inv_scale = 1.0f/scale;
  128. switch(pixelFormat)
  129. {
  130. case(GL_LUMINANCE): { for(unsigned int i=0;i<num;++i) { float l = float(*data)*scale; operation.luminance(l); *data++ = T(l*inv_scale); } } break;
  131. case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { float a = float(*data)*scale; operation.alpha(a); *data++ = T(a*inv_scale); } } break;
  132. case(GL_LUMINANCE_ALPHA): { for(unsigned int i=0;i<num;++i) { float l = float(*data)*scale; float a = float(*(data+1))*scale; operation.luminance_alpha(l,a); *data++ = T(l*inv_scale); *data++ = T(a*inv_scale); } } break;
  133. case(GL_RGB): { for(unsigned int i=0;i<num;++i) { float r = float(*data)*scale; float g = float(*(data+1))*scale; float b = float(*(data+2))*scale; operation.rgb(r,g,b); *data++ = T(r*inv_scale); *data++ = T(g*inv_scale); *data++ = T(b*inv_scale); } } break;
  134. case(GL_RGBA): { for(unsigned int i=0;i<num;++i) { float r = float(*data)*scale; float g = float(*(data+1))*scale; float b = float(*(data+2))*scale; float a = float(*(data+3))*scale; operation.rgba(r,g,b,a); *data++ = T(r*inv_scale); *data++ = T(g*inv_scale); *data++ = T(b*inv_scale); *data++ = T(a*inv_scale); } } break;
  135. case(GL_BGR): { for(unsigned int i=0;i<num;++i) { float b = float(*data)*scale; float g = float(*(data+1))*scale; float r = float(*(data+2))*scale; operation.rgb(r,g,b); *data++ = T(b*inv_scale); *data++ = T(g*inv_scale); *data++ = T(r*inv_scale); } } break;
  136. case(GL_BGRA): { for(unsigned int i=0;i<num;++i) { float b = float(*data)*scale; float g = float(*(data+1))*scale; float r = float(*(data+2))*scale; float a = float(*(data+3))*scale; operation.rgba(r,g,b,a); *data++ = T(b*inv_scale); *data++ = T(g*inv_scale); *data++ = T(r*inv_scale); *data++ = T(a*inv_scale); } } break;
  137. }
  138. }
  139. template <class M>
  140. void modifyRow(unsigned int num, GLenum pixelFormat, GLenum dataType, unsigned char* data, const M& operation)
  141. {
  142. switch(dataType)
  143. {
  144. case(GL_BYTE): _modifyRow(num,pixelFormat, (char*)data, 1.0f/128.0f, operation); break;
  145. case(GL_UNSIGNED_BYTE): _modifyRow(num,pixelFormat, (unsigned char*)data, 1.0f/255.0f, operation); break;
  146. case(GL_SHORT): _modifyRow(num,pixelFormat, (short*) data, 1.0f/32768.0f, operation); break;
  147. case(GL_UNSIGNED_SHORT): _modifyRow(num,pixelFormat, (unsigned short*)data, 1.0f/65535.0f, operation); break;
  148. case(GL_INT): _modifyRow(num,pixelFormat, (int*) data, 1.0f/2147483648.0f, operation); break;
  149. case(GL_UNSIGNED_INT): _modifyRow(num,pixelFormat, (unsigned int*) data, 1.0f/4294967295.0f, operation); break;
  150. case(GL_FLOAT): _modifyRow(num,pixelFormat, (float*) data, 1.0f, operation); break;
  151. }
  152. }
  153. template <class M>
  154. void modifyImage(osg::Image* image, const M& operation)
  155. {
  156. if (!image) return;
  157. for(int r=0;r<image->r();++r)
  158. {
  159. for(int t=0;t<image->t();++t)
  160. {
  161. modifyRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation);
  162. }
  163. }
  164. }
  165. /** Compute the min max colour values in the image.*/
  166. extern OSG_EXPORT bool computeMinMax(const osg::Image* image, osg::Vec4& min, osg::Vec4& max);
  167. /** Compute the min max colour values in the image.*/
  168. extern OSG_EXPORT bool offsetAndScaleImage(osg::Image* image, const osg::Vec4& offset, const osg::Vec4& scale);
  169. /** Compute source image to destination image.*/
  170. extern OSG_EXPORT bool copyImage(const osg::Image* srcImage, int src_s, int src_t, int src_r, int width, int height, int depth,
  171. osg::Image* destImage, int dest_s, int dest_t, int dest_r, bool doRescale = false);
  172. /** Compute the min max colour values in the image.*/
  173. extern OSG_EXPORT bool clearImageToColor(osg::Image* image, const osg::Vec4& colour);
  174. typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
  175. /** Search through the list of Images and find the maximum number of components used among the images.*/
  176. extern OSG_EXPORT unsigned int maximimNumOfComponents(const ImageList& imageList);
  177. /** create a 3D osg::Image from a list of osg::Image.*/
  178. extern OSG_EXPORT osg::Image* createImage3D(const ImageList& imageList,
  179. GLenum desiredPixelFormat,
  180. int s_maximumImageSize = 1024,
  181. int t_maximumImageSize = 1024,
  182. int r_maximumImageSize = 1024,
  183. bool resizeToPowerOfTwo = false);
  184. /** create a 3D osg::Image from a list of osg::Image.*/
  185. extern OSG_EXPORT osg::Image* createImage3DWithAlpha(const ImageList& imageList,
  186. int s_maximumImageSize = 1024,
  187. int t_maximumImageSize = 1024,
  188. int r_maximumImageSize = 1024,
  189. bool resizeToPowerOfTwo = false);
  190. /** create a 2D osg::Image that provides a point at the center of the image.
  191. * The colour across th image is computed from a balance between the center color and the background color controlled by the power of the radius from the center.*/
  192. extern OSG_EXPORT osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power);
  193. enum ColorSpaceOperation
  194. {
  195. NO_COLOR_SPACE_OPERATION,
  196. MODULATE_ALPHA_BY_LUMINANCE,
  197. MODULATE_ALPHA_BY_COLOR,
  198. REPLACE_ALPHA_WITH_LUMINANCE,
  199. REPLACE_RGB_WITH_LUMINANCE
  200. };
  201. /** Convert the RGBA values in a Image based on a ColorSpaceOperation defined scheme.*/
  202. extern OSG_EXPORT osg::Image* colorSpaceConversion(ColorSpaceOperation op, osg::Image* image, const osg::Vec4& colour);
  203. /** Create a copy of an osg::Image. converting the origin and orientation to standard lower left OpenGL style origin .*/
  204. extern OSG_EXPORT osg::Image* createImageWithOrientationConversion(const osg::Image* srcImage, const osg::Vec3i& srcOrigin, const osg::Vec3i& srcRow, const osg::Vec3i& srcColumn, const osg::Vec3i& srcLayer);
  205. }
  206. #endif