# Visualization Library

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

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlVolume/VolumeUtils.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.com                                               */
    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/GLSLmath.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 v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:26.
Permission is granted to use this page to write and publish articles regarding Visualization Library.