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 14#ifndef OSG_IMAGEUTILS 15#define OSG_IMAGEUTILS 1 16 17#include <osg/Export> 18 19#include <osg/Image> 20#include <osg/Vec3i> 21 22namespace osg { 23 24template <typename T, class O> 25void _readRow(unsigned int num, GLenum pixelFormat, const T* data, O& operation) 26{ 27 switch(pixelFormat) 28 { 29 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; 30 case(GL_LUMINANCE): { for(unsigned int i=0;i<num;++i) { operation.luminance(operation.cast(*data++)); } } break; 31 case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { operation.alpha(operation.cast(*data++)); } } break; 32 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; 33 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; 34 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; 35 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; 36 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; 37 } 38} 39 40 41template <class O> 42void readRow(unsigned int num, GLenum pixelFormat, GLenum dataType, const unsigned char* data, O& operation) 43{ 44 switch(dataType) 45 { 46 case(GL_BYTE): _readRow(num, pixelFormat, (const char*)data, operation); break; 47 case(GL_UNSIGNED_BYTE): _readRow(num, pixelFormat, (const unsigned char*)data, operation); break; 48 case(GL_SHORT): _readRow(num, pixelFormat, (const short*) data, operation); break; 49 case(GL_UNSIGNED_SHORT): _readRow(num, pixelFormat, (const unsigned short*)data, operation); break; 50 case(GL_INT): _readRow(num, pixelFormat, (const int*) data, operation); break; 51 case(GL_UNSIGNED_INT): _readRow(num, pixelFormat, (const unsigned int*) data, operation); break; 52 case(GL_FLOAT): _readRow(num, pixelFormat, (const float*) data, operation); break; 53 case(GL_DOUBLE): _readRow(num, pixelFormat, (const double*) data, operation); break; 54 } 55} 56 57 58template <class O> 59void readImage(const osg::Image* image, O& operation) 60{ 61 if (!image) return; 62 63 for(int r=0;r<image->r();++r) 64 { 65 for(int t=0;t<image->t();++t) 66 { 67 readRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation); 68 } 69 } 70} 71 72/** Convenience method for making it easy to cast all pixel channels types to a unit float RGBA form.*/ 73struct CastAndScaleToFloatOperation 74{ 75 float cast(char v) { return static_cast<float>(v)*(1.0f/128.0f); } 76 float cast(unsigned char v) { return static_cast<float>(v)*(1.0f/255.0f); } 77 float cast(short v) { return static_cast<float>(v)*(1.0f/32768.0f); } 78 float cast(unsigned short v) { return static_cast<float>(v)*(1.0f/65535.0f); } 79 float cast(int v) { return static_cast<float>(v)*(1.0f/2147483648.0f); } 80 float cast(unsigned int v) { return static_cast<float>(v)*(1.0f/4294967295.0f); } 81 float cast(float v) { return v; } 82 float cast(double v) { return static_cast<double>(v); } 83}; 84 85#if 0 86template <typename T, class O> 87void _readRow(unsigned int num, GLenum pixelFormat, const T* data,float scale, O& operation) 88{ 89 switch(pixelFormat) 90 { 91 case(GL_LUMINANCE): { for(unsigned int i=0;i<num;++i) { float l = float(*data++)*scale; operation.luminance(l); } } break; 92 case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { float a = float(*data++)*scale; operation.alpha(a); } } break; 93 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; 94 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; 95 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; 96 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; 97 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; 98 } 99} 100 101template <class O> 102void readRow(unsigned int num, GLenum pixelFormat, GLenum dataType, const unsigned char* data, O& operation) 103{ 104 switch(dataType) 105 { 106 case(GL_BYTE): _readRow(num,pixelFormat, (const char*)data, 1.0f/128.0f, operation); break; 107 case(GL_UNSIGNED_BYTE): _readRow(num,pixelFormat, (const unsigned char*)data, 1.0f/255.0f, operation); break; 108 case(GL_SHORT): _readRow(num,pixelFormat, (const short*) data, 1.0f/32768.0f, operation); break; 109 case(GL_UNSIGNED_SHORT): _readRow(num,pixelFormat, (const unsigned short*)data, 1.0f/65535.0f, operation); break; 110 case(GL_INT): _readRow(num,pixelFormat, (const int*) data, 1.0f/2147483648.0f, operation); break; 111 case(GL_UNSIGNED_INT): _readRow(num,pixelFormat, (const unsigned int*) data, 1.0f/4294967295.0f, operation); break; 112 case(GL_FLOAT): _readRow(num,pixelFormat, (const float*) data, 1.0f, operation); break; 113 } 114} 115 116template <class O> 117void readImage(const osg::Image* image, O& operation) 118{ 119 if (!image) return; 120 121 for(int r=0;r<image->r();++r) 122 { 123 for(int t=0;t<image->t();++t) 124 { 125 readRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation); 126 } 127 } 128} 129#endif 130 131 132 133// example ModifyOperator 134// struct ModifyOperator 135// { 136// inline void luminance(float& l) const {} 137// inline void alpha(float& a) const {} 138// inline void luminance_alpha(float& l,float& a) const {} 139// inline void rgb(float& r,float& g,float& b) const {} 140// inline void rgba(float& r,float& g,float& b,float& a) const {} 141// }; 142 143 144template <typename T, class M> 145void _modifyRow(unsigned int num, GLenum pixelFormat, T* data,float scale, const M& operation) 146{ 147 float inv_scale = 1.0f/scale; 148 switch(pixelFormat) 149 { 150 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; 151 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; 152 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; 153 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; 154 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; 155 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; 156 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; 157 } 158} 159 160template <class M> 161void modifyRow(unsigned int num, GLenum pixelFormat, GLenum dataType, unsigned char* data, const M& operation) 162{ 163 switch(dataType) 164 { 165 case(GL_BYTE): _modifyRow(num,pixelFormat, (char*)data, 1.0f/128.0f, operation); break; 166 case(GL_UNSIGNED_BYTE): _modifyRow(num,pixelFormat, (unsigned char*)data, 1.0f/255.0f, operation); break; 167 case(GL_SHORT): _modifyRow(num,pixelFormat, (short*) data, 1.0f/32768.0f, operation); break; 168 case(GL_UNSIGNED_SHORT): _modifyRow(num,pixelFormat, (unsigned short*)data, 1.0f/65535.0f, operation); break; 169 case(GL_INT): _modifyRow(num,pixelFormat, (int*) data, 1.0f/2147483648.0f, operation); break; 170 case(GL_UNSIGNED_INT): _modifyRow(num,pixelFormat, (unsigned int*) data, 1.0f/4294967295.0f, operation); break; 171 case(GL_FLOAT): _modifyRow(num,pixelFormat, (float*) data, 1.0f, operation); break; 172 } 173} 174 175template <class M> 176void modifyImage(osg::Image* image, const M& operation) 177{ 178 if (!image) return; 179 180 for(int r=0;r<image->r();++r) 181 { 182 for(int t=0;t<image->t();++t) 183 { 184 modifyRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation); 185 } 186 } 187} 188 189/** Compute the min max colour values in the image.*/ 190extern OSG_EXPORT bool computeMinMax(const osg::Image* image, osg::Vec4& min, osg::Vec4& max); 191 192/** Compute the min max colour values in the image.*/ 193extern OSG_EXPORT bool offsetAndScaleImage(osg::Image* image, const osg::Vec4& offset, const osg::Vec4& scale); 194 195/** Compute source image to destination image.*/ 196extern OSG_EXPORT bool copyImage(const osg::Image* srcImage, int src_s, int src_t, int src_r, int width, int height, int depth, 197 osg::Image* destImage, int dest_s, int dest_t, int dest_r, bool doRescale = false); 198 199/** Compute the min max colour values in the image.*/ 200extern OSG_EXPORT bool clearImageToColor(osg::Image* image, const osg::Vec4& colour); 201 202typedef std::vector< osg::ref_ptr<osg::Image> > ImageList; 203 204/** Search through the list of Images and find the maximum number of components used among the images.*/ 205extern OSG_EXPORT unsigned int maximimNumOfComponents(const ImageList& imageList); 206 207/** create a 3D osg::Image from a list of osg::Image.*/ 208extern OSG_EXPORT osg::Image* createImage3D(const ImageList& imageList, 209 GLenum desiredPixelFormat, 210 int s_maximumImageSize = 1024, 211 int t_maximumImageSize = 1024, 212 int r_maximumImageSize = 1024, 213 bool resizeToPowerOfTwo = false); 214 215/** create a 3D osg::Image from a list of osg::Image.*/ 216extern OSG_EXPORT osg::Image* createImage3DWithAlpha(const ImageList& imageList, 217 int s_maximumImageSize = 1024, 218 int t_maximumImageSize = 1024, 219 int r_maximumImageSize = 1024, 220 bool resizeToPowerOfTwo = false); 221 222 223 224 225/** create a 2D osg::Image that provides a point at the center of the image. 226 * 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.*/ 227extern OSG_EXPORT osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power); 228 229 230enum ColorSpaceOperation 231{ 232 NO_COLOR_SPACE_OPERATION, 233 MODULATE_ALPHA_BY_LUMINANCE, 234 MODULATE_ALPHA_BY_COLOR, 235 REPLACE_ALPHA_WITH_LUMINANCE, 236 REPLACE_RGB_WITH_LUMINANCE 237}; 238 239/** Convert the RGBA values in a Image based on a ColorSpaceOperation defined scheme.*/ 240extern OSG_EXPORT osg::Image* colorSpaceConversion(ColorSpaceOperation op, osg::Image* image, const osg::Vec4& colour); 241 242/** Create a copy of an osg::Image. converting the origin and orientation to standard lower left OpenGL style origin .*/ 243extern 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); 244 245} 246 247 248#endif 249