Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlVolume/VolumeUtils.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #include <vlVolume/VolumeUtils.hpp>
00033 #include <vlCore/Log.hpp>
00034 #include <vlCore/glsl_math.hpp>
00035 
00036 using namespace vl;
00037 
00038 //-----------------------------------------------------------------------------
00039 ref<Image> vl::genRGBAVolume(const Image* data, const Image* trfunc, const fvec3& light_dir, bool alpha_from_data)
00040 {
00041   ref<Image> img;
00042 
00043   if(data->type() == IT_UNSIGNED_BYTE)
00044     img = genRGBAVolumeT<unsigned char,IT_UNSIGNED_BYTE>(data,trfunc,light_dir,alpha_from_data);
00045   else
00046   if(data->type() == IT_UNSIGNED_SHORT)
00047     img = genRGBAVolumeT<unsigned short,IT_UNSIGNED_SHORT>(data,trfunc,light_dir,alpha_from_data);
00048   else
00049   if(data->type() == IT_FLOAT)
00050     img = genRGBAVolumeT<float,IT_FLOAT>(data,trfunc,light_dir,alpha_from_data);
00051   else
00052     Log::error("genRGBAVolume() called with non supported data type().\n");
00053 
00054   return img;
00055 }
00056 //-----------------------------------------------------------------------------
00057 ref<Image> vl::genRGBAVolume(const Image* data, const Image* trfunc, bool alpha_from_data)
00058 {
00059   ref<Image> img;
00060 
00061   if(data->type() == IT_UNSIGNED_BYTE)
00062     img = genRGBAVolumeT<unsigned char,IT_UNSIGNED_BYTE>(data,trfunc,alpha_from_data);
00063   else
00064   if(data->type() == IT_UNSIGNED_SHORT)
00065     img = genRGBAVolumeT<unsigned short,IT_UNSIGNED_SHORT>(data,trfunc,alpha_from_data);
00066   else
00067   if(data->type() == IT_FLOAT)
00068     img = genRGBAVolumeT<float,IT_FLOAT>(data,trfunc,alpha_from_data);
00069   else
00070     Log::error("genRGBAVolume() called with non supported data type().\n");
00071 
00072   return img;
00073 }
00074 //-----------------------------------------------------------------------------
00075 template<typename data_type, EImageType img_type>
00076 ref<Image> vl::genRGBAVolumeT(const Image* data, const Image* trfunc, const fvec3& light_dir, bool alpha_from_data)
00077 {
00078   if (!trfunc || !data)
00079     return NULL;
00080   if (data->format() != IF_LUMINANCE)
00081   {
00082     Log::error("genRGBAVolume() called with non IF_LUMINANCE data format().\n");
00083     return NULL;
00084   }
00085   if (data->type() != img_type)
00086   {
00087     Log::error("genRGBAVolume() called with invalid data type().\n");
00088     return NULL;
00089   }
00090   if (data->dimension() != ID_3D)
00091   {
00092     Log::error("genRGBAVolume() called with non 3D data.\n");
00093     return NULL;
00094   }
00095   if (trfunc->dimension() != ID_1D)
00096   {
00097     Log::error("genRGBAVolume() transfer function image must be an 1D image.\n");
00098     return NULL;
00099   }
00100   if (trfunc->format() != IF_RGBA)
00101   {
00102     Log::error("genRGBAVolume() transfer function format() must be IF_RGBA.\n");
00103     return NULL;
00104   }
00105   if (trfunc->type() != IT_UNSIGNED_BYTE)
00106   {
00107     Log::error("genRGBAVolume() transfer function format() must be IT_UNSIGNED_BYTE.\n");
00108     return NULL;
00109   }
00110 
00111   float normalizer_num = 0;
00112   switch(data->type())
00113   {
00114     case IT_UNSIGNED_BYTE:  normalizer_num = 1.0f/255.0f;   break;
00115     case IT_UNSIGNED_SHORT: normalizer_num = 1.0f/65535.0f; break;
00116     case IT_FLOAT:          normalizer_num = 1.0f;          break;
00117     default:
00118       break;
00119   }
00120 
00121   // light normalization
00122   fvec3 L = light_dir;
00123   L.normalize();
00124   int w = data->width();
00125   int h = data->height();
00126   int d = data->depth();
00127   int pitch = data->pitch();
00128   const unsigned char* lum_px = data->pixels();
00129   // generated volume
00130   ref<Image> volume = new Image( w, h, d, 1, IF_RGBA, IT_UNSIGNED_BYTE );
00131   ubvec4* rgba_px = (ubvec4*)volume->pixels();
00132   for(int z=0; z<d; ++z)
00133   {
00134     int z1 = z-1;
00135     int z2 = z+1;
00136     z1 = clamp(z1, 0, d-1);
00137     z2 = clamp(z2, 0, d-1);
00138     for(int y=0; y<h; ++y)
00139     {
00140       int y1 = y-1;
00141       int y2 = y+1;
00142       y1 = clamp(y1, 0, h-1);
00143       y2 = clamp(y2, 0, h-1);
00144       for(int x=0; x<w; ++x, ++rgba_px)
00145       {
00146         // value
00147         float lum = (*(data_type*)(lum_px + x*sizeof(data_type) + y*pitch + z*pitch*h)) * normalizer_num;
00148         // value -> transfer function
00149         float xval = lum*trfunc->width();
00150         VL_CHECK(xval>=0)
00151         if (xval > trfunc->width()-1.001f)
00152           xval = trfunc->width()-1.001f;
00153         int ix1 = (int)xval;
00154         int ix2 = ix1+1;
00155         VL_CHECK(ix2<trfunc->width())
00156         float w21  = (float)fract(xval);
00157         float w11  = 1.0f - w21;
00158         fvec4 c11  = (fvec4)((ubvec4*)trfunc->pixels())[ix1];
00159         fvec4 c21  = (fvec4)((ubvec4*)trfunc->pixels())[ix2];
00160         fvec4 rgba = (c11*w11 + c21*w21)*(1.0f/255.0f);
00161 
00162         // bake the lighting
00163         int x1 = x-1;
00164         int x2 = x+1;
00165         x1 = clamp(x1, 0, w-1);
00166         x2 = clamp(x2, 0, w-1);
00167         data_type vx1 = (*(data_type*)(lum_px + x1*sizeof(data_type) + y *pitch + z *pitch*h));
00168         data_type vx2 = (*(data_type*)(lum_px + x2*sizeof(data_type) + y *pitch + z *pitch*h));
00169         data_type vy1 = (*(data_type*)(lum_px + x *sizeof(data_type) + y1*pitch + z *pitch*h));
00170         data_type vy2 = (*(data_type*)(lum_px + x *sizeof(data_type) + y2*pitch + z *pitch*h));
00171         data_type vz1 = (*(data_type*)(lum_px + x *sizeof(data_type) + y *pitch + z1*pitch*h));
00172         data_type vz2 = (*(data_type*)(lum_px + x *sizeof(data_type) + y *pitch + z2*pitch*h));
00173         fvec3 N1(float(vx1-vx2), float(vy1-vy2), float(vz1-vz2));
00174         N1.normalize();
00175         fvec3 N2 = -N1 * 0.15f;
00176         float l1 = max(dot(N1,L),0.0f);
00177         float l2 = max(dot(N2,L),0.0f); // opposite dim light to enhance 3D perception
00178         rgba.r() = rgba.r()*l1 + rgba.r()*l2+0.2f; // +0.2f = ambient light
00179         rgba.g() = rgba.g()*l1 + rgba.g()*l2+0.2f;
00180         rgba.b() = rgba.b()*l1 + rgba.b()*l2+0.2f;
00181         rgba.r() = clamp(rgba.r(), 0.0f, 1.0f);
00182         rgba.g() = clamp(rgba.g(), 0.0f, 1.0f);
00183         rgba.b() = clamp(rgba.b(), 0.0f, 1.0f);
00184 
00185         // map pixel
00186         rgba_px->r() = (unsigned char)(rgba.r()*255.0f);
00187         rgba_px->g() = (unsigned char)(rgba.g()*255.0f);
00188         rgba_px->b() = (unsigned char)(rgba.b()*255.0f);
00189         if (alpha_from_data)
00190           rgba_px->a() = (unsigned char)(lum*255.0f);
00191         else
00192           rgba_px->a() = (unsigned char)(rgba.a()*255.0f);
00193       }
00194     }
00195   }
00196 
00197   return volume;
00198 }
00199 //-----------------------------------------------------------------------------
00200 template<typename data_type, EImageType img_type>
00201 ref<Image> vl::genRGBAVolumeT(const Image* data, const Image* trfunc, bool alpha_from_data)
00202 {
00203   if (!trfunc || !data)
00204     return NULL;
00205   if (data->format() != IF_LUMINANCE)
00206   {
00207     Log::error("genRGBAVolume() called with non IF_LUMINANCE data format().\n");
00208     return NULL;
00209   }
00210   if (data->type() != img_type)
00211   {
00212     Log::error("genRGBAVolume() called with invalid data type().\n");
00213     return NULL;
00214   }  
00215   if (data->dimension() != ID_3D)
00216   {
00217     Log::error("genRGBAVolume() called with non 3D data.\n");
00218     return NULL;
00219   }
00220   if (trfunc->dimension() != ID_1D)
00221   {
00222     Log::error("genRGBAVolume() transfer function image must be an 1D image.\n");
00223     return NULL;
00224   }
00225   if (trfunc->format() != IF_RGBA)
00226   {
00227     Log::error("genRGBAVolume() transfer function format() must be IF_RGBA.\n");
00228     return NULL;
00229   }
00230   if (trfunc->type() != IT_UNSIGNED_BYTE)
00231   {
00232     Log::error("genRGBAVolume() transfer function format() must be IT_UNSIGNED_BYTE.\n");
00233     return NULL;
00234   }
00235 
00236   float normalizer_num = 0;
00237   switch(data->type())
00238   {
00239     case IT_UNSIGNED_BYTE:  normalizer_num = 1.0f/255.0f;   break;
00240     case IT_UNSIGNED_SHORT: normalizer_num = 1.0f/65535.0f; break;
00241     case IT_FLOAT:          normalizer_num = 1.0f;          break;
00242     default:
00243       break;
00244   }
00245 
00246   // light normalization
00247   int w = data->width();
00248   int h = data->height();
00249   int d = data->depth();
00250   int pitch = data->pitch();
00251   const unsigned char* lum_px = data->pixels();
00252   // generated volume
00253   ref<Image> volume = new Image( w, h, d, 1, IF_RGBA, IT_UNSIGNED_BYTE );
00254   ubvec4* rgba_px = (ubvec4*)volume->pixels();
00255   for(int z=0; z<d; ++z)
00256   {
00257     int z1 = z-1;
00258     int z2 = z+1;
00259     z1 = clamp(z1, 0, d-1);
00260     z2 = clamp(z2, 0, d-1);
00261     for(int y=0; y<h; ++y)
00262     {
00263       int y1 = y-1;
00264       int y2 = y+1;
00265       y1 = clamp(y1, 0, h-1);
00266       y2 = clamp(y2, 0, h-1);
00267       for(int x=0; x<w; ++x, ++rgba_px)
00268       {
00269         // value
00270         float lum = (*(data_type*)(lum_px + x*sizeof(data_type) + y*pitch + z*pitch*h)) * normalizer_num;
00271         // value -> transfer function
00272         float xval = lum*trfunc->width();
00273         VL_CHECK(xval>=0)
00274         if (xval > trfunc->width()-1.001f)
00275           xval = trfunc->width()-1.001f;
00276         int ix1 = (int)xval;
00277         int ix2 = ix1+1;
00278         VL_CHECK(ix2<trfunc->width())
00279         float w21  = (float)fract(xval);
00280         float w11  = 1.0f - w21;
00281         fvec4 c11  = (fvec4)((ubvec4*)trfunc->pixels())[ix1];
00282         fvec4 c21  = (fvec4)((ubvec4*)trfunc->pixels())[ix2];
00283         fvec4 rgba = (c11*w11 + c21*w21)*(1.0f/255.0f);
00284 
00285         // map pixel
00286         rgba_px->r() = (unsigned char)(rgba.r()*255.0f);
00287         rgba_px->g() = (unsigned char)(rgba.g()*255.0f);
00288         rgba_px->b() = (unsigned char)(rgba.b()*255.0f);
00289         if (alpha_from_data)
00290           rgba_px->a() = (unsigned char)(lum*255.0f);
00291         else
00292           rgba_px->a() = (unsigned char)(rgba.a()*255.0f);
00293       }
00294     }
00295   }
00296 
00297   return volume;
00298 }
00299 //-----------------------------------------------------------------------------
00300 ref<Image> vl::genGradientNormals(const Image* img)
00301 {
00302   ref<Image> gradient = new Image;
00303   gradient->allocate3D(img->width(), img->height(), img->depth(), 1, IF_RGB, IT_FLOAT);
00304   fvec3* px = (fvec3*)gradient->pixels();
00305   fvec3 A, B;
00306   for(int z=0; z<gradient->depth(); ++z)
00307   {
00308     for(int y=0; y<gradient->height(); ++y)
00309     {
00310       for(int x=0; x<gradient->width(); ++x)
00311       {
00312         // clamped coordinates
00313         int xp = x+1, xn = x-1;
00314         int yp = y+1, yn = y-1;
00315         int zp = z+1, zn = z-1;
00316         if (xn<0) xn = 0;
00317         if (yn<0) yn = 0;
00318         if (zn<0) zn = 0;
00319         if (xp>img->width() -1) xp = img->width() -1;
00320         if (yp>img->height()-1) yp = img->height()-1;
00321         if (zp>img->depth() -1) zp = img->depth() -1;
00322 
00323         A.x() = img->sample(xn,y,z).r();
00324         B.x() = img->sample(xp,y,z).r();
00325         A.y() = img->sample(x,yn,z).r();
00326         B.y() = img->sample(x,yp,z).r();
00327         A.z() = img->sample(x,y,zn).r();
00328         B.z() = img->sample(x,y,zp).r();
00329 
00330         // write normal packed into 0..1 format
00331         px[x + img->width()*y + img->width()*img->height()*z] = normalize(A - B) * 0.5f + 0.5f;
00332       }
00333     }
00334   }
00335   return gradient;
00336 }
00337 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:44.
Permission is granted to use this page to write and publish articles regarding Visualization Library.