00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef CVD_SCALAR_CONVERT_H
00022 #define CVD_SCALAR_CONVERT_H
00023
00024 #include <cvd/byte.h>
00025 #include <cvd/internal/pixel_traits.h>
00026
00027 namespace CVD
00028 {
00029 namespace Pixel
00030 {
00031
00032 namespace Internal
00033 {
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 template<class To, class From> struct int_info {
00052
00053 static const int diff=traits<To>::bits_used - traits<From>::bits_used;
00054
00055
00056
00057 static const int chunks=traits<To>::bits_used / traits<From>::bits_used;
00058
00059 static const int extra_bits =traits<To>::bits_used % traits<From>::bits_used;
00060
00061 static const int final_rshift = traits<From>::bits_used - extra_bits;
00062
00063
00064 static const int shift_dir = (diff == 0)?0:((diff > 0)?1:-1);
00065 };
00066
00067 template<class To, int num, int shift, int bits, int r_shift> struct upshift
00068 {
00069 static To aggregate(To i)
00070 {
00071 return i << shift | upshift<To,num-1,shift-bits,bits, r_shift>::aggregate(i);
00072 }
00073 };
00074 template<class To, int shift, int bits, int r_shift> struct upshift<To,0,shift,bits,r_shift>
00075 {
00076 static To aggregate(To i)
00077 {
00078 return i >> r_shift;
00079 }
00080 };
00081
00082 template<class To, class From, int i=int_info<To,From>::shift_dir> struct shift_convert {
00083 template <class D> static To from(D f) {
00084 return static_cast<To>(f);
00085 }
00086 };
00087
00088 template<class To, class From> struct shift_convert<To, From, 1>
00089 {
00090 typedef int_info<To,From> info;
00091 template <class D> static To from(D f) {
00092
00093 return upshift<To,info::chunks, info::diff, traits<From>::bits_used, info::final_rshift>::aggregate(static_cast<To>(f));
00094 }
00095 };
00096
00097 template<class To, class From> struct shift_convert<To, From,-1> {
00098 template <class D> static To from(D f) {
00099 return static_cast<To>(f >> -int_info<To,From>::diff);
00100 }
00101 };
00102
00103
00104 static float float_for_byte[512];
00105 static double double_for_byte[512];
00106
00107 template <class S> bool buildLookupTable(S table[]) {
00108 for (int i=0; i<=511; i++)
00109 table[i] = (S)((i-255)/255.0);
00110 return true;
00111 }
00112 const static bool init_float_for_byte = buildLookupTable(float_for_byte);
00113 const static bool init_double_for_byte = buildLookupTable(double_for_byte);
00114 inline float byte_to_float(int b) { return float_for_byte[b+255]; }
00115 inline double byte_to_double(int b) { return double_for_byte[b+255]; }
00116
00117
00118
00119
00120 template <class From, class To, class D=From, bool int1 = traits<To>::integral && traits<From>::integral, bool int2 =traits<D>::integral> struct ScalarConvert {
00121 static inline To from(const D& from) {
00122 static const double factor = double(traits<To>::max_intensity)/traits<From>::max_intensity;
00123 return static_cast<To>(from*factor);
00124 }
00125 };
00126
00127
00128
00129 template <class From, class To, class D> struct ScalarConvert<From,To,D,true, true> {
00130 static inline To from(const D& f) {
00131 return shift_convert<To, From, int_info<To,From>::shift_dir>::from(f);
00132 }
00133 };
00134
00135
00136
00137
00138 template<class From, class D> struct ScalarConvert<From, bool, D, true, true>
00139 {
00140 static inline bool from(const D& from)
00141 {
00142 return from != 0;
00143 }
00144 };
00145 template<class From, class D> struct ScalarConvert<From, bool, D, true, false>
00146 {
00147 static inline bool from(const D& from)
00148 {
00149 return from != 0;
00150 }
00151 };
00152
00153
00154
00155 template <class D> struct ScalarConvert<byte,float,D,false,true> {
00156 static inline float from(const D& from) {
00157 return byte_to_float(from);
00158 }
00159 };
00160
00161
00162 template <class D> struct ScalarConvert<byte,float,D,false,false> {
00163 static inline float from(const D& from) {
00164 return static_cast<float>(from * (1.0/255.0));
00165 }
00166 };
00167
00168 template <class D> struct ScalarConvert<byte,double,D,false, true> {
00169 static inline double from(const D& from) {
00170 return byte_to_double(from);
00171 }
00172 };
00173 template <class D> struct ScalarConvert<byte,double,D,false, false> {
00174 static inline double from(const D& from) {
00175 return from * (1.0/255.0);
00176 }
00177 };
00178
00179 inline double byte_float_to_float(double d) {
00180 return d * traits<double>::max_intensity/traits<byte>::max_intensity;
00181 }
00182
00183 #if 0
00184 template <> struct ScalarConvert<byte,float,float,false> {
00185 static inline float from(const float& from) {
00186 return byte_float_to_float(from);
00187 }
00188 };
00189 template <> struct ScalarConvert<byte,double,float,false> {
00190 static inline double from(const float& from) {
00191 return byte_float_to_float(from);
00192 }
00193 };
00194 template <> struct ScalarConvert<byte,float,double,false> {
00195 static inline float from(const double& from) {
00196 return byte_float_to_float(from);
00197 }
00198 };
00199 template <> struct ScalarConvert<byte,double,double,false> {
00200 static inline double from(const double& from) {
00201 return byte_float_to_float(from);
00202 }
00203 };
00204 #endif
00205
00206 }
00207
00208
00209 template <class To, class From, class D> inline To scalar_convert(const D& d) { return Internal::ScalarConvert<From,To,D>::from(d); }
00210
00211
00212 }
00213 }
00214 #endif