00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
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
00147 float lum = (*(data_type*)(lum_px + x*sizeof(data_type) + y*pitch + z*pitch*h)) * normalizer_num;
00148
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
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);
00178 rgba.r() = rgba.r()*l1 + rgba.r()*l2+0.2f;
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
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
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
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
00270 float lum = (*(data_type*)(lum_px + x*sizeof(data_type) + y*pitch + z*pitch*h)) * normalizer_num;
00271
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
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
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
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