Cleaned up example to use the new ImageUtils functions for creating a 3D image from a list of images.

This commit is contained in:
Robert Osfield 2011-06-08 17:45:24 +00:00
parent 86439123b4
commit 1fbbd347bf

View File

@ -78,30 +78,43 @@ enum ShadingModel
MaximumIntensityProjection
};
struct PassThroughTransformFunction
osg::Image* createTexture3D(osg::ImageList& imageList,
unsigned int numComponentsDesired,
int s_maximumTextureSize,
int t_maximumTextureSize,
int r_maximumTextureSize,
bool resizeToPowerOfTwo)
{
unsigned char operator() (unsigned char c) const { return c; }
};
if (numComponentsDesired==0)
{
return osg::createImage3DWithAlpha(imageList,
s_maximumTextureSize,
t_maximumTextureSize,
r_maximumTextureSize,
resizeToPowerOfTwo);
}
else
{
GLenum desiredPixelFormat = 0;
switch(numComponentsDesired)
{
case(1) : desiredPixelFormat = GL_LUMINANCE; break;
case(2) : desiredPixelFormat = GL_LUMINANCE_ALPHA; break;
case(3) : desiredPixelFormat = GL_RGB; break;
case(4) : desiredPixelFormat = GL_RGBA; break;
}
void clampToNearestValidPowerOfTwo(int& sizeX, int& sizeY, int& sizeZ, int s_maximumTextureSize, int t_maximumTextureSize, int r_maximumTextureSize)
{
// compute nearest powers of two for each axis.
int s_nearestPowerOfTwo = 1;
while(s_nearestPowerOfTwo<sizeX && s_nearestPowerOfTwo<s_maximumTextureSize) s_nearestPowerOfTwo*=2;
int t_nearestPowerOfTwo = 1;
while(t_nearestPowerOfTwo<sizeY && t_nearestPowerOfTwo<t_maximumTextureSize) t_nearestPowerOfTwo*=2;
int r_nearestPowerOfTwo = 1;
while(r_nearestPowerOfTwo<sizeZ && r_nearestPowerOfTwo<r_maximumTextureSize) r_nearestPowerOfTwo*=2;
sizeX = s_nearestPowerOfTwo;
sizeY = t_nearestPowerOfTwo;
sizeZ = r_nearestPowerOfTwo;
return osg::createImage3D(imageList,
desiredPixelFormat,
s_maximumTextureSize,
t_maximumTextureSize,
r_maximumTextureSize,
resizeToPowerOfTwo);
}
}
#if 1
struct ModulateAlphaByLuminanceOperator
{
ModulateAlphaByLuminanceOperator() {}
@ -113,547 +126,6 @@ struct ModulateAlphaByLuminanceOperator
inline void rgba(float& r,float& g,float& b,float& a) const { float l = (r+g+b)*0.3333333; a *= l;}
};
osg::Image* createTexture3D(osg::ImageList& imageList,
unsigned int numComponentsDesired,
int s_maximumTextureSize,
int t_maximumTextureSize,
int r_maximumTextureSize,
bool resizeToPowerOfTwo)
{
GLenum desiredPixelFormat = 0;
bool modulateAlphaByLuminance = false;
if (numComponentsDesired==0)
{
unsigned int maxNumComponents = osg::maximimNumOfComponents(imageList);
if (maxNumComponents==3)
{
desiredPixelFormat = GL_RGBA;
modulateAlphaByLuminance = true;
}
}
else
{
switch(numComponentsDesired)
{
case(1) : desiredPixelFormat = GL_LUMINANCE; break;
case(2) : desiredPixelFormat = GL_LUMINANCE_ALPHA; break;
case(3) : desiredPixelFormat = GL_RGB; break;
case(4) : desiredPixelFormat = GL_RGBA; break;
}
}
osg::ref_ptr<osg::Image> image = osg::createImage3D(imageList,
desiredPixelFormat,
s_maximumTextureSize,
t_maximumTextureSize,
r_maximumTextureSize,
resizeToPowerOfTwo);
if (image.valid())
{
if (modulateAlphaByLuminance)
{
osg::modifyImage(image.get(), ModulateAlphaByLuminanceOperator());
}
return image.release();
}
else
{
return 0;
}
}
#else
struct ProcessRow
{
virtual ~ProcessRow() {}
virtual void operator() (unsigned int num,
GLenum source_pixelFormat, unsigned char* source,
GLenum dest_pixelFormat, unsigned char* dest) const
{
switch(source_pixelFormat)
{
case(GL_LUMINANCE):
case(GL_ALPHA):
switch(dest_pixelFormat)
{
case(GL_LUMINANCE):
case(GL_ALPHA): A_to_A(num, source, dest); break;
case(GL_LUMINANCE_ALPHA): A_to_LA(num, source, dest); break;
case(GL_RGB): A_to_RGB(num, source, dest); break;
case(GL_RGBA): A_to_RGBA(num, source, dest); break;
}
break;
case(GL_LUMINANCE_ALPHA):
switch(dest_pixelFormat)
{
case(GL_LUMINANCE):
case(GL_ALPHA): LA_to_A(num, source, dest); break;
case(GL_LUMINANCE_ALPHA): LA_to_LA(num, source, dest); break;
case(GL_RGB): LA_to_RGB(num, source, dest); break;
case(GL_RGBA): LA_to_RGBA(num, source, dest); break;
}
break;
case(GL_RGB):
switch(dest_pixelFormat)
{
case(GL_LUMINANCE):
case(GL_ALPHA): RGB_to_A(num, source, dest); break;
case(GL_LUMINANCE_ALPHA): RGB_to_LA(num, source, dest); break;
case(GL_RGB): RGB_to_RGB(num, source, dest); break;
case(GL_RGBA): RGB_to_RGBA(num, source, dest); break;
}
break;
case(GL_RGBA):
switch(dest_pixelFormat)
{
case(GL_LUMINANCE):
case(GL_ALPHA): RGBA_to_A(num, source, dest); break;
case(GL_LUMINANCE_ALPHA): RGBA_to_LA(num, source, dest); break;
case(GL_RGB): RGBA_to_RGB(num, source, dest); break;
case(GL_RGBA): RGBA_to_RGBA(num, source, dest); break;
}
break;
case(GL_BGR):
switch(dest_pixelFormat)
{
case(GL_LUMINANCE):
case(GL_ALPHA): BGR_to_A(num, source, dest); break;
case(GL_LUMINANCE_ALPHA): BGR_to_LA(num, source, dest); break;
case(GL_RGB): BGR_to_RGB(num, source, dest); break;
case(GL_RGBA): BGR_to_RGBA(num, source, dest); break;
}
break;
case(GL_BGRA):
switch(dest_pixelFormat)
{
case(GL_LUMINANCE):
case(GL_ALPHA): BGRA_to_A(num, source, dest); break;
case(GL_LUMINANCE_ALPHA): BGRA_to_LA(num, source, dest); break;
case(GL_RGB): BGRA_to_RGB(num, source, dest); break;
case(GL_RGBA): BGRA_to_RGBA(num, source, dest); break;
}
break;
}
}
///////////////////////////////////////////////////////////////////////////////
// alpha sources..
virtual void A_to_A(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source++;
}
}
virtual void A_to_LA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source;
*dest++ = *source++;
}
}
virtual void A_to_RGB(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source;
*dest++ = *source;
*dest++ = *source++;
}
}
virtual void A_to_RGBA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source;
*dest++ = *source;
*dest++ = *source;
*dest++ = *source++;
}
}
///////////////////////////////////////////////////////////////////////////////
// alpha luminance sources..
virtual void LA_to_A(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
++source;
*dest++ = *source++;
}
}
virtual void LA_to_LA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source++;
*dest++ = *source++;
}
}
virtual void LA_to_RGB(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source;
*dest++ = *source;
*dest++ = *source;
source+=2;
}
}
virtual void LA_to_RGBA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source;
*dest++ = *source;
*dest++ = *source++;
*dest++ = *source++;
}
}
///////////////////////////////////////////////////////////////////////////////
// RGB sources..
virtual void RGB_to_A(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char val = *source;
*dest++ = val;
source += 3;
}
}
virtual void RGB_to_LA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char val = *source;
*dest++ = val;
*dest++ = val;
source += 3;
}
}
virtual void RGB_to_RGB(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
}
}
virtual void RGB_to_RGBA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char val = *source;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = val;
}
}
///////////////////////////////////////////////////////////////////////////////
// RGBA sources..
virtual void RGBA_to_A(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
source += 3;
*dest++ = *source++;
}
}
virtual void RGBA_to_LA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char val = *source;
source += 3;
*dest++ = val;
*dest++ = *source++;
}
}
virtual void RGBA_to_RGB(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
++source;
}
}
virtual void RGBA_to_RGBA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
*dest++ = *source++;
}
}
///////////////////////////////////////////////////////////////////////////////
// BGR sources..
virtual void BGR_to_A(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char val = *source;
*dest++ = val;
source += 3;
}
}
virtual void BGR_to_LA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char val = *source;
*dest++ = val;
*dest++ = val;
source += 3;
}
}
virtual void BGR_to_RGB(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char blue = *source++;
unsigned char green = *source++;
unsigned char red = *source++;
*dest++ = red;
*dest++ = green;
*dest++ = blue;
}
}
virtual void BGR_to_RGBA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char blue = *source++;
unsigned char green = *source++;
unsigned char red = *source++;
unsigned char val = (unsigned char)((int(red)+int(green)+int(blue))/3);
*dest++ = red;
*dest++ = green;
*dest++ = blue;
*dest++ = val;
}
}
///////////////////////////////////////////////////////////////////////////////
// BGRA sources..
virtual void BGRA_to_A(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
source += 3;
*dest++ = *source++;
}
}
virtual void BGRA_to_LA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char val = *source;
source += 3;
*dest++ = val;
*dest++ = *source++;
}
}
virtual void BGRA_to_RGB(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char blue = *source++;
unsigned char green = *source++;
unsigned char red = *source++;
*dest++ = red;
*dest++ = green;
*dest++ = blue;
++source;
}
}
virtual void BGRA_to_RGBA(unsigned int num, unsigned char* source, unsigned char* dest) const
{
for(unsigned int i=0;i<num;++i)
{
unsigned char blue = *source++;
unsigned char green = *source++;
unsigned char red = *source++;
unsigned char alpha = *source++;
*dest++ = red;
*dest++ = green;
*dest++ = blue;
*dest++ = alpha;
}
}
};
osg::Image* createTexture3D(osg::ImageList& imageList,
unsigned int numComponentsDesired,
int s_maximumTextureSize,
int t_maximumTextureSize,
int r_maximumTextureSize,
bool resizeToPowerOfTwo)
{
ProcessRow processRow;
int max_s = 0;
int max_t = 0;
unsigned int max_components = 0;
int total_r = 0;
osg::ImageList::iterator itr;
for(itr=imageList.begin();
itr!=imageList.end();
++itr)
{
osg::Image* image = itr->get();
GLenum pixelFormat = image->getPixelFormat();
if (pixelFormat==GL_ALPHA ||
pixelFormat==GL_INTENSITY ||
pixelFormat==GL_LUMINANCE ||
pixelFormat==GL_LUMINANCE_ALPHA ||
pixelFormat==GL_RGB ||
pixelFormat==GL_RGBA ||
pixelFormat==GL_BGR ||
pixelFormat==GL_BGRA)
{
max_s = osg::maximum(image->s(), max_s);
max_t = osg::maximum(image->t(), max_t);
max_components = osg::maximum(osg::Image::computeNumComponents(pixelFormat), max_components);
total_r += image->r();
}
else
{
osg::notify(osg::NOTICE)<<"Image "<<image->getFileName()<<" has unsuitable pixel format 0x"<< std::hex<< pixelFormat << std::dec << std::endl;
}
}
if (max_components==3)
{
// change RGB to a RGBA
max_components = 4;
}
if (numComponentsDesired!=0) max_components = numComponentsDesired;
GLenum desiredPixelFormat = 0;
switch(max_components)
{
case(1):
osg::notify(osg::NOTICE)<<"desiredPixelFormat = GL_LUMINANCE" << std::endl;
desiredPixelFormat = GL_LUMINANCE;
break;
case(2):
osg::notify(osg::NOTICE)<<"desiredPixelFormat = GL_LUMINANCE_ALPHA" << std::endl;
desiredPixelFormat = GL_LUMINANCE_ALPHA;
break;
case(3):
osg::notify(osg::NOTICE)<<"desiredPixelFormat = GL_RGB" << std::endl;
desiredPixelFormat = GL_RGB;
break;
case(4):
osg::notify(osg::NOTICE)<<"desiredPixelFormat = GL_RGBA" << std::endl;
desiredPixelFormat = GL_RGBA;
break;
}
if (desiredPixelFormat==0) return 0;
// compute nearest powers of two for each axis.
int s_nearestPowerOfTwo = 1;
int t_nearestPowerOfTwo = 1;
int r_nearestPowerOfTwo = 1;
if (resizeToPowerOfTwo)
{
while(s_nearestPowerOfTwo<max_s && s_nearestPowerOfTwo<s_maximumTextureSize) s_nearestPowerOfTwo*=2;
while(t_nearestPowerOfTwo<max_t && t_nearestPowerOfTwo<t_maximumTextureSize) t_nearestPowerOfTwo*=2;
while(r_nearestPowerOfTwo<total_r && r_nearestPowerOfTwo<r_maximumTextureSize) r_nearestPowerOfTwo*=2;
osg::notify(osg::NOTICE)<<"max image width = "<<max_s<<" nearest power of two = "<<s_nearestPowerOfTwo<<std::endl;
osg::notify(osg::NOTICE)<<"max image height = "<<max_t<<" nearest power of two = "<<t_nearestPowerOfTwo<<std::endl;
osg::notify(osg::NOTICE)<<"max image depth = "<<total_r<<" nearest power of two = "<<r_nearestPowerOfTwo<<std::endl;
}
else
{
s_nearestPowerOfTwo = max_s;
t_nearestPowerOfTwo = max_t;
r_nearestPowerOfTwo = total_r;
}
// now allocate the 3d texture;
osg::ref_ptr<osg::Image> image_3d = new osg::Image;
image_3d->allocateImage(s_nearestPowerOfTwo,t_nearestPowerOfTwo,r_nearestPowerOfTwo,
desiredPixelFormat,GL_UNSIGNED_BYTE);
unsigned int r_offset = (total_r<r_nearestPowerOfTwo) ? r_nearestPowerOfTwo/2 - total_r/2 : 0;
int curr_dest_r = r_offset;
// copy across the values from the source images into the image_3d.
for(itr=imageList.begin();
itr!=imageList.end();
++itr)
{
osg::Image* image = itr->get();
GLenum pixelFormat = image->getPixelFormat();
if (pixelFormat==GL_ALPHA ||
pixelFormat==GL_LUMINANCE ||
pixelFormat==GL_INTENSITY ||
pixelFormat==GL_LUMINANCE_ALPHA ||
pixelFormat==GL_RGB ||
pixelFormat==GL_RGBA ||
pixelFormat==GL_BGR ||
pixelFormat==GL_BGRA)
{
int num_r = osg::minimum(image->r(), (image_3d->r() - curr_dest_r));
int num_t = osg::minimum(image->t(), image_3d->t());
int num_s = osg::minimum(image->s(), image_3d->s());
unsigned int s_offset_dest = (image->s()<s_nearestPowerOfTwo) ? s_nearestPowerOfTwo/2 - image->s()/2 : 0;
unsigned int t_offset_dest = (image->t()<t_nearestPowerOfTwo) ? t_nearestPowerOfTwo/2 - image->t()/2 : 0;
for(int r=0;r<num_r;++r, ++curr_dest_r)
{
for(int t=0;t<num_t;++t)
{
unsigned char* dest = image_3d->data(s_offset_dest,t+t_offset_dest,curr_dest_r);
unsigned char* source = image->data(0,t,r);
processRow(num_s, image->getPixelFormat(), source, image_3d->getPixelFormat(), dest);
}
}
}
}
return image_3d.release();
}
#endif
struct ScaleOperator
{
@ -701,6 +173,23 @@ struct WriteRowOperator
inline void rgba(float& r,float& g,float& b,float& a) const { r = _colours[_pos].r(); g = _colours[_pos].g(); b = _colours[_pos].b(); a = _colours[_pos++].a(); }
};
void clampToNearestValidPowerOfTwo(int& sizeX, int& sizeY, int& sizeZ, int s_maximumTextureSize, int t_maximumTextureSize, int r_maximumTextureSize)
{
// compute nearest powers of two for each axis.
int s_nearestPowerOfTwo = 1;
while(s_nearestPowerOfTwo<sizeX && s_nearestPowerOfTwo<s_maximumTextureSize) s_nearestPowerOfTwo*=2;
int t_nearestPowerOfTwo = 1;
while(t_nearestPowerOfTwo<sizeY && t_nearestPowerOfTwo<t_maximumTextureSize) t_nearestPowerOfTwo*=2;
int r_nearestPowerOfTwo = 1;
while(r_nearestPowerOfTwo<sizeZ && r_nearestPowerOfTwo<r_maximumTextureSize) r_nearestPowerOfTwo*=2;
sizeX = s_nearestPowerOfTwo;
sizeY = t_nearestPowerOfTwo;
sizeZ = r_nearestPowerOfTwo;
}
osg::Image* readRaw(int sizeX, int sizeY, int sizeZ, int numberBytesPerComponent, int numberOfComponents, const std::string& endian, const std::string& raw_filename)
{
osgDB::ifstream fin(raw_filename.c_str(), std::ifstream::binary);