core/vgui/vgui_range_map.txx
Go to the documentation of this file.
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 //Initialize the internal mapping scale factors
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 //Compute the pixel byte mapping.  Used for types that aren't table mappable
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   //the type with largest dynamic range
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   // y will now be in the range 0 to (max - min)
00060   // we now put y in that range
00061   y *= ratio;
00062   // if gamma >0 && !=1 make the gamma correction
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);//round to nearest byte
00066 }
00067 
00068 //Compute the float mapping.  Used for types that are table mappable
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   //the type with largest dynamic range
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   // y will now be in the range 0 to (max - min)
00089   // we now put y in that range
00090   y *=ratio;
00091   // if gamma >0 && !=1 make the gamma correction
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   //there are two cases, signed and unsigned map domains
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     //The values have to be shifted by min
00110     long mint = static_cast<long>(vcl_numeric_limits<Type>::min());
00111     long maxt = static_cast<long>(vcl_numeric_limits<Type>::max());
00112     long range = static_cast<long>(maxt-mint);
00113     for (long i = 0; i <= range; ++i)
00114       bmap[i] = map_pixel_byte(static_cast<Type>(i+mint), min, max,
00115                                gamma, ratio);
00116   }
00117   return bmap;
00118 }
00119 
00120 // Hardware mapping cannot support signed Types
00121 template <class Type>
00122 vbl_array_1d<float> vgui_range_map<Type>::
00123 compute_float_table(const Type min, const Type max, const float gamma,
00124                     const long double ratio)
00125 {
00126   vbl_array_1d<float> null;
00127   if (vcl_numeric_limits<Type>::is_signed)
00128     return null;
00129   vbl_array_1d<float> fmap(size_, 0);
00130   Type maxt = vcl_numeric_limits<Type>::max();
00131   for (unsigned int i = 0; i <= (unsigned int)maxt; ++i)
00132     fmap[i] = map_pixel_float(Type(i), min, max, gamma, ratio);
00133   return fmap;
00134 }
00135 
00136 template <class Type>
00137 vgui_range_map<Type>::vgui_range_map(vgui_range_map_params const& rmp)
00138   :   vgui_range_map_params(rmp)
00139 {
00140   this->init();
00141   mapable_ = true;
00142   table_mapable_ = true;
00143   int num_bits = (sizeof(Type)*8);
00144   if (num_bits==1 || num_bits>16 || !vcl_numeric_limits<Type>::is_integer)
00145     table_mapable_ = false;
00146   //A lookup table is used to represent the pixel mapping
00147   //The table will primarily be used for byte and short pixel types
00148   //and can handle direct lookup of the mapping
00149   if (table_mapable_)
00150     size_ = 1 << num_bits;
00151 
00152   //The table is not mapable so it will be necessary to compute
00153   //the mapping on the fly
00154   if (!table_mapable_)
00155     size_ = 0;
00156 }
00157 
00158 template <class Type>
00159 vgui_range_map<Type>::~vgui_range_map()
00160 {
00161 }
00162 
00163 // The offset for signed, non field, types so that negative values can be
00164 // used as table index entries.
00165 template <class Type>
00166 int vgui_range_map<Type>::offset()
00167 {
00168   if (table_mapable_)
00169     return - (int)vcl_numeric_limits<Type>::min();
00170   else
00171     return 0;
00172 }
00173 
00174 #undef VGUI_RANGE_MAP_INSTANTIATE
00175 #define VGUI_RANGE_MAP_INSTANTIATE(T) \
00176 template class vgui_range_map<T >
00177 
00178 #endif // vgui_range_map_txx_