00001 #ifndef vgui_range_map_txx_
00002 #define vgui_range_map_txx_
00003
00004 #include "vgui_range_map.h"
00005
00006 #include <vcl_cassert.h>
00007 #include <vcl_cmath.h>
00008 #include <vcl_limits.h>
00009
00010 template <class Type>
00011 void vgui_range_map<Type>::init_map_domain(const Type min, const Type max,
00012 long double& ratio)
00013 {
00014 assert(max>=min);
00015 assert(!vcl_numeric_limits<Type>::has_infinity ||
00016 (-min != vcl_numeric_limits<Type>::infinity() &&
00017 max != vcl_numeric_limits<Type>::infinity()));
00018 ratio = 1.0;
00019 if (max!=min)
00020 ratio = 1.0/(max - min);
00021 }
00022
00023
00024 template <class Type>
00025 void vgui_range_map<Type>::init()
00026 {
00027 if (n_components_==1)
00028 init_map_domain(Type(min_L_), Type(max_L_), ratio_L_);
00029 else if (n_components_==3||n_components_==4)
00030 {
00031 init_map_domain(Type(min_R_), Type(max_R_), ratio_R_);
00032 init_map_domain(Type(min_G_), Type(max_G_), ratio_G_);
00033 init_map_domain(Type(min_B_), Type(max_B_), ratio_B_);
00034 }
00035 if (n_components_==4)
00036 init_map_domain(Type(min_X_), Type(max_X_), ratio_X_);
00037 }
00038
00039
00040 template <class Type>
00041 vxl_byte vgui_range_map<Type>::
00042 map_pixel_byte(const Type pix, const Type min, const Type max,
00043 const float gamma, const long double ratio)
00044 {
00045 int num_bits = (sizeof(Type)*8);
00046 if (num_bits==1) {
00047 if (pix)
00048 return 255;
00049 else
00050 return 0;
00051 }
00052
00053 long double y = pix;
00054 y = (y < (long double)min) ? (long double)min : (y > (long double)max) ? (long double)max : y;
00055 if (invert_)
00056 y = (long double)max - y;
00057 else
00058 y -= (long double)min;
00059
00060
00061 y *= ratio;
00062
00063 if (gamma > 0 && gamma !=1)
00064 y = vcl_pow((long double)y, (long double)1/gamma);
00065 return static_cast<vxl_byte>((y*255.0) +0.5);
00066 }
00067
00068
00069 template <class Type>
00070 float vgui_range_map<Type>::
00071 map_pixel_float(const Type pix, const Type min, const Type max,
00072 const float gamma, const long double ratio)
00073 {
00074 int num_bits = (sizeof(Type)*8);
00075 if (num_bits==1) {
00076 if (pix)
00077 return 1.0f;
00078 else
00079 return 0.0f;
00080 }
00081
00082 long double y = pix;
00083 y = (y < (long double)min) ? (long double)min: (y > (long double)max) ? (long double)max : y;
00084 if (invert_)
00085 y = (long double)max - y;
00086 else
00087 y -= (long double)min;
00088
00089
00090 y *=ratio;
00091
00092 if (gamma > 0 && gamma!=1)
00093 y = vcl_pow((long double)y, (long double)1/gamma);
00094 return static_cast<float>(y);
00095 }
00096
00097 template <class Type>
00098 vbl_array_1d<vxl_byte> vgui_range_map<Type>::
00099 compute_byte_table(const Type min, const Type max, const float gamma,
00100 const long double ratio)
00101 {
00102 vbl_array_1d<vxl_byte> bmap(size_, 0);
00103
00104 if (!vcl_numeric_limits<Type>::is_signed)
00105 for (unsigned long i = 0; i < size_; i++)
00106 bmap[i] = map_pixel_byte(static_cast<Type>(i), min, max, gamma, ratio);
00107 else
00108 {
00109
00110 unsigned long mint =
00111 static_cast<unsigned long>(vcl_numeric_limits<Type>::min());
00112 unsigned long maxt =
00113 static_cast<unsigned long>(vcl_numeric_limits<Type>::max());
00114 for (unsigned long i = 0; mint+i <= maxt; ++i)
00115 bmap[i] = map_pixel_byte(static_cast<Type>(mint+i), min, max,
00116 gamma, ratio);
00117 }
00118 return bmap;
00119 }
00120
00121
00122 template <class Type>
00123 vbl_array_1d<float> vgui_range_map<Type>::
00124 compute_float_table(const Type min, const Type max, const float gamma,
00125 const long double ratio)
00126 {
00127 vbl_array_1d<float> null;
00128 if (vcl_numeric_limits<Type>::is_signed)
00129 return null;
00130 vbl_array_1d<float> fmap(size_, 0);
00131 Type maxt = vcl_numeric_limits<Type>::max();
00132 for (unsigned int i = 0; i <= (unsigned int)maxt; ++i)
00133 fmap[i] = map_pixel_float(Type(i), min, max, gamma, ratio);
00134 return fmap;
00135 }
00136
00137 template <class Type>
00138 vgui_range_map<Type>::vgui_range_map(vgui_range_map_params const& rmp)
00139 : vgui_range_map_params(rmp)
00140 {
00141 this->init();
00142 mapable_ = true;
00143 table_mapable_ = true;
00144 int num_bits = (sizeof(Type)*8);
00145 if (num_bits==1 || num_bits>16 || !vcl_numeric_limits<Type>::is_integer)
00146 table_mapable_ = false;
00147
00148
00149
00150 if (table_mapable_)
00151 size_ = 1 << num_bits;
00152
00153
00154
00155 if (!table_mapable_)
00156 size_ = 0;
00157 }
00158
00159 template <class Type>
00160 vgui_range_map<Type>::~vgui_range_map()
00161 {
00162 }
00163
00164
00165
00166 template <class Type>
00167 int vgui_range_map<Type>::offset()
00168 {
00169 if (table_mapable_)
00170 return - (int)vcl_numeric_limits<Type>::min();
00171 else
00172 return 0;
00173 }
00174
00175 #undef VGUI_RANGE_MAP_INSTANTIATE
00176 #define VGUI_RANGE_MAP_INSTANTIATE(T) \
00177 template class vgui_range_map<T >
00178
00179 #endif // vgui_range_map_txx_