converter.h

00001 /***************************************************************************
00002                           converter.h  -  description
00003                              -------------------
00004     begin                : Tue Dec 4 2001
00005     copyright            : (C) 2001 by Michael von Mengershausen
00006     email                : mengers@cns.mpg.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #ifndef CONVERTER_H
00019 #define CONVERTER_H
00020 
00021 #include <limits>
00022 
00023 #include <tjutils/tjcomplex.h>
00024 #include <tjutils/tjtypes.h>
00025 #include <tjutils/tjlog.h>
00026 #include <assert.h>
00027 
00033 // helper class used for debugging the odindata component
00034 class OdinData {
00035  public:
00036   static const char* get_compName();
00037 };
00038 
00040 
00046 enum autoscaleOption {noscale, autoscale};
00047 
00049 
00053 class Converter {
00054 
00055 public:
00056 
00057 
00058 
00060 // get_elements function overloading
00061 
00062 //  specializations for complex type
00063 static int get_elements(const STD_complex&) {
00064   return 2;
00065 }
00066 
00070 template<typename T>
00071 static int get_elements(const T&) {
00072   return 1;
00073 }
00074 
00075 
00077 
00078 
00085 template<typename Src, typename Dst>
00086 static void convert_array(const Src* src, Dst* dst, int srcsize, int dstsize, autoscaleOption scaleopt=autoscale) {
00087   Log<OdinData> odinlog("Converter","convert_array");
00088   init();
00089   const int srcstep=get_elements(*dst);
00090   const int dststep=get_elements(*src);
00091   bool doScale = (scaleopt!=noscale && std::numeric_limits<Dst>::is_integer);
00092 
00093   if(dststep*srcsize != srcstep*dstsize) {
00094     ODINLOG(odinlog,warningLog) << "size mismatch: dststep(" << dststep << ") * srcsize(" << srcsize << ") != srcstep(" << srcstep << ") * dstsize(" << dstsize << ")" << STD_endl;
00095   }
00096 
00097   double scale=1.0;
00098   double offset=0.0;
00099   if(doScale) {
00100     const double domain_minus=creal(std::numeric_limits<Dst>::min());//negative value domain of this dst
00101     const double domain_plus =creal(std::numeric_limits<Dst>::max());//positive value domain of this dst
00102     double minval=domain_plus;
00103     double maxval=domain_minus;
00104     if(srcsize>0) minval=maxval=creal(src[0]);
00105     for(int i=1; i<srcsize; i++) {
00106       if(src[i]<minval) minval=creal(src[i]);
00107       if(src[i]>maxval) maxval=creal(src[i]);
00108     }
00109 
00110     ODINLOG(odinlog,normalDebug) << "src Range:" << minval << "=>" << maxval << STD_endl;
00111     ODINLOG(odinlog,normalDebug) << "dst Domain:" << domain_minus << "=>" << domain_plus << STD_endl;
00112 
00113     assert(domain_minus<=0 && domain_plus>=0); //I think we can assume this
00114     assert(domain_minus<domain_plus);//we also should assume this
00115 
00116     //set offset for src
00117     //if all src is completly on positive domain, or if there is no negative domain use minval
00118     //else if src is completly on negative dmain, or if there is no positive domain use maxval
00119     //elsewise leave it at 0 and scale both sides
00120     if(minval>0 || !domain_minus)offset=-minval;
00121     else if(maxval<0 || !domain_plus)offset=-maxval;
00122 
00123     //calculate range of values which will be on postive/negative domain when offset is applied
00124     const double range_plus =maxval+offset; //allways >=0
00125     const double range_minus=minval+offset; //allways <=0
00126 
00127     //set scaling factor to fit src-range into dst domain 
00128     //some compilers dont make x/0 = inf, so we use std::numeric_limits<double>::max() instead, in this case
00129     const double scale_plus = 
00130         range_plus ? domain_plus/range_plus :
00131         std::numeric_limits<double>::max();
00132     const double scale_minus= 
00133         range_minus ? domain_minus/ range_minus: 
00134         std::numeric_limits<double>::max();
00135     ODINLOG(odinlog,normalDebug) << "scale_minus/scale_plus=" << scale_minus << "/" << scale_plus << STD_endl;
00136 
00137     scale = std::min(scale_plus,scale_minus);//get the smaller scaling factor so the bigger range will fit into his domain
00138     doScale=(scale!=1. || offset);
00139     offset*=scale;//calc offset for dst
00140   }
00141   if(doScale)ODINLOG(odinlog,normalDebug) << "converting with scale/offset=" << scale << "/" << offset << STD_endl;
00142   else ODINLOG(odinlog,normalDebug) << "converting without scaling" << STD_endl;
00143 
00144   if(srcstep==dststep)//use common convert for data of same complexity
00145   {
00146      if(doScale)
00147       convert_array_impl(src,dst, srcsize < dstsize?srcsize:dstsize,scale,offset);
00148     else
00149       convert_array_impl(src,dst, srcsize < dstsize?srcsize:dstsize);
00150   }
00151   else //do generic convert for data of different complexity
00152   {
00153     int srcindex=0, dstindex=0;
00154     while(srcindex<srcsize && dstindex<dstsize) {
00155       convert(src+srcindex, dst+dstindex,scale,offset);
00156       srcindex+=srcstep;
00157       dstindex+=dststep;
00158     }
00159   }
00160 }
00161 
00162 static void init();
00163 
00164 private:
00165 
00167 // convert
00168 
00172 template<typename Src, typename Dst> static void convert_array_impl(const Src* src, Dst* dst, unsigned int count,double scale=1,double offset=0) {
00173     Log<OdinData> odinlog("Converter","convert_array_impl(using generic impl)");
00174     ODINLOG(odinlog,normalDebug) << "generic convert " << TypeTraits::type2label(*src) << "=>" << TypeTraits::type2label(*dst) << STD_endl;
00175     ODINLOG(odinlog,normalDebug) << "scale/offset=" << scale << "/" << offset << STD_endl;
00176     while(count--)
00177         convert(src++, dst++,scale,offset);
00178 }
00179 
00180 template<typename Src> static void convert_array_impl(const Src* src, Src* dst, unsigned int count) {
00181     Log<OdinData> odinlog("Converter","convert_array_impl(using memcopy)");
00182     ODINLOG(odinlog,normalDebug) << "generic convert " << TypeTraits::type2label(*src) << "=>" << TypeTraits::type2label(*dst) << STD_endl;
00183   memcpy(dst,src,sizeof(Src)*count);
00184 }
00185 
00186 #ifdef USE_OIL
00187 #define DECL_CONVERT(SRC_TYPE,DST_TYPE,SRC_KEY,DST_KEY) static void convert_array_impl(const SRC_TYPE  *src,DST_TYPE *dst,const unsigned int count);
00188 #define DECL_SCALED_CONVERT(SRC_TYPE,DST_TYPE,SRC_KEY,DST_KEY) static void convert_array_impl(const SRC_TYPE  *src,DST_TYPE *dst,const unsigned int count,const double scale,const double offset);
00189 #define DECL_CONVERT_CPY(TYPE) static void convert_array_impl(const TYPE *src,TYPE *dst,const unsigned int count);
00190 
00191 //>>s32
00192 DECL_CONVERT(float,int32_t,f32,s32)
00193 DECL_CONVERT(double,int32_t,f64,s32)
00194 DECL_CONVERT_CPY(int32_t)
00195 DECL_CONVERT(uint32_t,int32_t,u32,s32)
00196 DECL_CONVERT(int16_t,int32_t,s16,s32)
00197 DECL_CONVERT(uint16_t,int32_t,u16,s32)
00198 DECL_CONVERT(int8_t,int32_t,s8,s32)
00199 DECL_CONVERT(uint8_t,int32_t,u8,s32)
00200 
00201 //>>u32
00202 DECL_CONVERT(float,uint32_t,f32,u32)
00203 DECL_CONVERT(double,uint32_t,f64,u32)
00204 DECL_CONVERT(int32_t,uint32_t,s32,u32)
00205 DECL_CONVERT_CPY(uint32_t)
00206 //DECL_CONVERT(int16_t,uint32_t,s16,u32) ** Not available in liboil - but should be imho
00207 DECL_CONVERT(uint16_t,uint32_t,u16,u32)
00208 //DECL_CONVERT(int8_t,uint32_t,s8,u32) ** Not available in liboil - but should be imho
00209 DECL_CONVERT(uint8_t,uint32_t,u8,u32)
00210 
00211 //>>s16
00212 DECL_CONVERT(float,int16_t,f32,s16)
00213 DECL_CONVERT(double,int16_t,f64,s16)
00214 DECL_CONVERT(int32_t,int16_t,s32,s16)
00215 DECL_CONVERT(uint32_t,int16_t,u32,s16)
00216 DECL_CONVERT_CPY(int16_t)
00217 DECL_CONVERT(uint16_t,int16_t,u16,s16)
00218 DECL_CONVERT(int8_t,int16_t,s8,s16)
00219 DECL_CONVERT(uint8_t,int16_t,u8,s16)
00220 
00221 //>>u16
00222 DECL_CONVERT(float,uint16_t,f32,u16)
00223 DECL_CONVERT(double,uint16_t,f64,u16)
00224 DECL_CONVERT(int32_t,uint16_t,s32,u16)
00225 DECL_CONVERT(uint32_t,uint16_t,u32,u16)
00226 DECL_CONVERT(int16_t,uint16_t,s16,u16)
00227 DECL_CONVERT_CPY(uint16_t)
00228 //DECL_CONVERT(int8_t,uint16_t,s8,u16) ** Not available in liboil - but should be imho
00229 DECL_CONVERT(uint8_t,uint16_t,u8,u16)
00230 
00231 //>>s8
00232 DECL_CONVERT(float,int8_t,f32,s8)
00233 DECL_CONVERT(double,int8_t,f64,s8)
00234 DECL_CONVERT(int32_t,int8_t,s32,s8)
00235 DECL_CONVERT(uint32_t,int8_t,u32,s8)
00236 DECL_CONVERT(int16_t,int8_t,s16,s8)
00237 DECL_CONVERT(uint16_t,int8_t,u16,s8)
00238 DECL_CONVERT_CPY(int8_t)
00239 DECL_CONVERT(uint8_t,int8_t,u8,s8)
00240 
00241 //>>u8
00242 DECL_CONVERT(float,uint8_t,f32,u8)
00243 DECL_CONVERT(double,uint8_t,f64,u8)
00244 DECL_CONVERT(int32_t,uint8_t,s32,u8)
00245 DECL_CONVERT(uint32_t,uint8_t,u32,u8)
00246 DECL_CONVERT(int16_t,uint8_t,s16,u8)
00247 DECL_CONVERT(uint16_t,uint8_t,u16,u8)
00248 DECL_CONVERT(int8_t,uint8_t,s8,u8)
00249 DECL_CONVERT_CPY(uint8_t)
00250 
00251 //>>f32
00252 DECL_CONVERT_CPY(float)
00253 DECL_CONVERT(double,float,f64,f32)
00254 DECL_CONVERT(int32_t,float,s32,f32)
00255 DECL_CONVERT(uint32_t,float,u32,f32)
00256 DECL_CONVERT(int16_t,float,s16,f32)
00257 DECL_CONVERT(uint16_t,float,u16,f32)
00258 DECL_CONVERT(int8_t,float,s8,f32)
00259 DECL_CONVERT(uint8_t,float,u8,f32)
00260 
00261 //>>f64
00262 DECL_CONVERT(float,double,f32,f64)
00263 DECL_CONVERT_CPY(double)
00264 DECL_CONVERT(int32_t,double,s32,f64)
00265 DECL_CONVERT(uint32_t,double,u32,f64)
00266 DECL_CONVERT(int16_t,double,s16,f64)
00267 DECL_CONVERT(uint16_t,double,u16,f64)
00268 DECL_CONVERT(int8_t,double,s8,f64)
00269 DECL_CONVERT(uint8_t,double,u8,f64)
00270 
00271 //scale>>s32
00272 DECL_SCALED_CONVERT(float,int32_t,f32,s32)
00273 DECL_SCALED_CONVERT(double,int32_t,f64,s32)
00274 
00275 //scale>>u32
00276 DECL_SCALED_CONVERT(float,uint32_t,f32,u32)
00277 DECL_SCALED_CONVERT(double,uint32_t,f64,u32)
00278 
00279 //scale>>s16
00280 DECL_SCALED_CONVERT(float,int16_t,f32,s16)
00281 DECL_SCALED_CONVERT(double,int16_t,f64,s16)
00282 
00283 //scale>>u16
00284 DECL_SCALED_CONVERT(float,uint16_t,f32,u16)
00285 DECL_SCALED_CONVERT(double,uint16_t,f64,u16)
00286 
00287 //scale>>s8
00288 DECL_SCALED_CONVERT(float,int8_t,f32,s8)
00289 DECL_SCALED_CONVERT(double,int8_t,f64,s8)
00290 
00291 //scale>>u8
00292 DECL_SCALED_CONVERT(float,uint8_t,f32,u8)
00293 DECL_SCALED_CONVERT(double,uint8_t,f64,u8)
00294 
00295 //scale>>f32
00296 DECL_SCALED_CONVERT(int32_t,float,s32,f32)
00297 DECL_SCALED_CONVERT(uint32_t,float,u32,f32)
00298 DECL_SCALED_CONVERT(int16_t,float,s16,f32)
00299 DECL_SCALED_CONVERT(uint16_t,float,u16,f32)
00300 DECL_SCALED_CONVERT(int8_t,float,s8,f32)
00301 DECL_SCALED_CONVERT(uint8_t,float,u8,f32)
00302 
00303 //scale>>f64
00304 DECL_SCALED_CONVERT(int32_t,double,s32,f64)
00305 DECL_SCALED_CONVERT(uint32_t,double,u32,f64)
00306 DECL_SCALED_CONVERT(int16_t,double,s16,f64)
00307 DECL_SCALED_CONVERT(uint16_t,double,u16,f64)
00308 DECL_SCALED_CONVERT(int8_t,double,s8,f64)
00309 DECL_SCALED_CONVERT(uint8_t,double,u8,f64)
00310 
00311 #undef DECL_CONVERT
00312 #undef DECL_SCALED_CONVERT
00313 #endif //USE_OIL
00314 
00315 
00316 // Implementing our own round functions since lround/lroundf do not work for unsigned numbers, and they are flawed in MinGW
00317 template<typename T> static T round(double x) {
00318   return (T)(x < 0 ? x - 0.5 : x + 0.5);
00319 }
00320 
00321 
00322 // specialized converter functions
00323 
00324 // to complex
00325 static void convert(const s8bit* src, STD_complex* dst,float scale,float offset) {
00326   (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
00327 }
00328 static void convert(const u8bit* src, STD_complex* dst,float scale,float offset) {
00329   (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
00330 }
00331 static void convert(const u16bit* src, STD_complex* dst,float scale,float offset) {
00332   (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
00333 }
00334 static void convert(const s16bit* src, STD_complex* dst,float scale,float offset) {
00335   (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
00336 }
00337 static void convert(const u32bit* src, STD_complex* dst,float scale,float offset) {
00338   (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
00339 }
00340 static void convert(const s32bit* src, STD_complex* dst,float scale,float offset) {
00341   (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
00342 }
00343 static void convert(const float *src, STD_complex* dst,float scale,float offset) {
00344   dst[0]=STD_complex(src[0]*scale+offset,src[1]*scale);
00345 }
00346 static void convert(const double *src, STD_complex* dst,float scale,float offset) {
00347   dst[0]=STD_complex(src[0]*scale+offset,src[1]*scale);
00348 }
00349 
00350 // from complex
00351 static void convert(const STD_complex* src, s8bit* dst,float scale,float offset) {
00352   dst[0]=round<s8bit>(src->real()*scale+offset);
00353   dst[1]=round<s8bit>(src->imag()*scale);
00354 }
00355 static void convert(const STD_complex* src, u8bit* dst,float scale,float offset) {
00356   dst[0]=round<u8bit>(src->real()*scale+offset);
00357   dst[1]=round<u8bit>(src->imag()*scale);
00358 }
00359 static void convert(const STD_complex* src, s16bit* dst,float scale,float offset) {
00360   dst[0]=round<s16bit>(src->real()*scale+offset);
00361   dst[1]=round<s16bit>(src->imag()*scale);
00362 }
00363 static void convert(const STD_complex* src, u16bit* dst,float scale,float offset) {
00364   dst[0]=round<u16bit>(src->real()*scale+offset);
00365   dst[1]=round<u16bit>(src->imag()*scale);
00366 }
00367 static void convert(const STD_complex* src, s32bit* dst,float scale,float offset) {
00368   dst[0]=round<s32bit>(src->real()*scale+offset);
00369   dst[1]=round<s32bit>(src->imag()*scale);
00370 }
00371 static void convert(const STD_complex* src, u32bit* dst,float scale,float offset) {
00372   dst[0]=round<u32bit>(src->real()*scale+offset);
00373   dst[1]=round<u32bit>(src->imag()*scale);
00374 }
00375 static void convert(const STD_complex* src, float* dst,float scale,float offset) {
00376   dst[0]=src->real()*scale+offset;
00377   dst[1]=src->imag()*scale;
00378 }
00379 static void convert(const STD_complex* src, double* dst,float scale,float offset) {
00380   dst[0]=src->real()*scale+offset;
00381   dst[1]=src->imag()*scale;
00382 }
00383 
00384 
00385 // from float to integer
00386 static void convert(const float* src, s8bit* dst,float scale,float offset) {
00387   dst[0]=round<s8bit>(src[0]*scale+offset);
00388 }
00389 static void convert(const float* src, u8bit* dst,float scale,float offset) {
00390   dst[0]=round<u8bit>(src[0]*scale+offset);
00391 }
00392 static void convert(const float* src, s16bit* dst,float scale,float offset) {
00393   dst[0]=round<s16bit>(src[0]*scale+offset);
00394 }
00395 static void convert(const float* src, u16bit* dst,float scale,float offset) {
00396   dst[0]=round<u16bit>(src[0]*scale+offset);
00397 }
00398 static void convert(const float* src, s32bit* dst,float scale,float offset) {
00399   dst[0]=round<s32bit>(src[0]*scale+offset);
00400 }
00401 static void convert(const float* src, u32bit* dst,float scale,float offset) {
00402   dst[0]=round<u32bit>(src[0]*scale+offset);
00403 }
00404 
00405 
00406 // from double to integer
00407 static void convert(const double* src, s8bit* dst,float scale,float offset) {
00408   dst[0]=round<s8bit>(src[0]*scale+offset);
00409 }
00410 static void convert(const double* src, u8bit* dst,float scale,float offset) {
00411   dst[0]=round<u8bit>(src[0]*scale+offset);
00412 }
00413 static void convert(const double* src, s16bit* dst,float scale,float offset) {
00414   dst[0]=round<s16bit>(src[0]*scale+offset);
00415 }
00416 static void convert(const double* src, u16bit* dst,float scale,float offset) {
00417   dst[0]=round<u16bit>(src[0]*scale+offset);
00418 }
00419 static void convert(const double* src, s32bit* dst,float scale,float offset) {
00420   dst[0]=round<s32bit>(src[0]*scale+offset);
00421 }
00422 static void convert(const double* src, u32bit* dst,float scale,float offset) {
00423   dst[0]=round<u32bit>(src[0]*scale+offset);
00424 }
00425 
00426 
00427 
00428 //default
00429 template<typename Src, typename Dst>
00430     static void convert(const Src* src, Dst* dst,float scale,float offset) {
00431       dst[0]=(Dst)(src[0]*scale+offset);
00432 }
00433 
00435 
00436 Converter() {} // Do not allow instances
00437 
00438 
00439 };
00440 
00444 #endif

Generated on Sat Jun 14 12:31:21 2008 by  doxygen 1.5.1