ODIN
converter.h
1 /***************************************************************************
2  converter.h - description
3  -------------------
4  begin : Tue Dec 4 2001
5  copyright : (C) 2000-2021 by Michael von Mengershausen
6  email : mengers@cns.mpg.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifndef CONVERTER_H
19 #define CONVERTER_H
20 
21 #include <limits>
22 #include <assert.h>
23 #include <stdint.h>
24 
25 #include <tjutils/tjcomplex.h>
26 #include <tjutils/tjtypes.h>
27 #include <tjutils/tjlog.h>
28 
34 // helper class used for debugging the odindata component
35 class OdinData {
36  public:
37  static const char* get_compName();
38 };
39 
40 
42 
46 class Converter {
47 
48 public:
49 
50 
51 
53 // get_elements function overloading
54 
55 // specializations for complex type
56 static unsigned int get_elements(const STD_complex&) {
57  return 2;
58 }
59 
63 template<typename T>
64 static unsigned int get_elements(const T&) {
65  return 1;
66 }
67 
68 
70 
71 
78 template<typename Src, typename Dst>
79 static void convert_array(const Src* src, Dst* dst, unsigned int srcsize, unsigned int dstsize, bool autoscale=true) {
80  Log<OdinData> odinlog("Converter","convert_array");
81  unsigned int srcstep=get_elements(*dst);
82  unsigned int dststep=get_elements(*src);
83  ODINLOG(odinlog,normalDebug) << "srcstep/dststep=" << srcstep << "/" << dststep << STD_endl;
84 
85  bool doScale = (autoscale && std::numeric_limits<Dst>::is_integer);
86  ODINLOG(odinlog,normalDebug) << "doScale=" << doScale << STD_endl;
87 
88  if(dststep*srcsize != srcstep*dstsize) {
89  ODINLOG(odinlog,warningLog) << "size mismatch: dststep(" << dststep << ") * srcsize(" << srcsize << ") != srcstep(" << srcstep << ") * dstsize(" << dstsize << ")" << STD_endl;
90  }
91 
92  double scale=1.0;
93  double offset=0.0;
94  if(doScale) {
95  const double domain_minus=creal(std::numeric_limits<Dst>::min());//negative value domain of this dst
96  const double domain_plus =creal(std::numeric_limits<Dst>::max());//positive value domain of this dst
97  double minval=std::numeric_limits<double>::min();
98  double maxval=std::numeric_limits<double>::max();
99  if(srcsize>0) minval=maxval=creal(src[0]);
100  for(unsigned int i=1; i<srcsize; i++) {
101  if(src[i]<minval) minval=creal(src[i]);
102  if(src[i]>maxval) maxval=creal(src[i]);
103  }
104 
105  ODINLOG(odinlog,normalDebug) << "domain_minus/domain_plus=" << domain_minus << "/" << domain_plus << STD_endl;
106  ODINLOG(odinlog,normalDebug) << "minval/maxval=" << minval << "/" << maxval << STD_endl;
107 
108  scale=secureDivision(domain_plus-domain_minus, maxval-minval);
109  offset=0.5*( (domain_plus+domain_minus) - secureDivision(maxval+minval, maxval-minval) * (domain_plus-domain_minus) );
110  ODINLOG(odinlog,normalDebug) << "scale/offset=" << scale << "/" << offset << STD_endl;
111 
112  }
113 
114 
115  if(srcstep==dststep) {//use common convert for data of same complexity
116  unsigned int count=srcsize < dstsize?srcsize:dstsize;
117  for(unsigned int i=0; i<count; i++) convert(src+i, dst+i,scale,offset);
118  } else { //do generic convert for data of different complexity
119  unsigned int srcindex=0, dstindex=0;
120  while(srcindex<srcsize && dstindex<dstsize) {
121  convert(src+srcindex, dst+dstindex,scale,offset);
122  srcindex+=srcstep;
123  dstindex+=dststep;
124  }
125  }
126 }
127 
128 
129 
130 private:
131 
133 // convert
134 
135 
136 
137 // Implementing our own round functions since lround/lroundf do not work for unsigned numbers, and they are flawed in MinGW
138 template<typename T> static T round(double x) {
139  double tobecasted=x < 0 ? x - 0.5 : x + 0.5;
140  if(std::numeric_limits<T>::is_integer) {
141  if(tobecasted<std::numeric_limits<T>::min()) tobecasted=std::numeric_limits<T>::min();
142  if(tobecasted>std::numeric_limits<T>::max()) tobecasted=std::numeric_limits<T>::max();
143  }
144  return (T)(tobecasted);
145 }
146 
147 // specialized converter functions
148 
149 // to complex
150 static void convert(const s8bit* src, STD_complex* dst,float scale,float offset) {
151  (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
152 }
153 static void convert(const u8bit* src, STD_complex* dst,float scale,float offset) {
154  (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
155 }
156 static void convert(const u16bit* src, STD_complex* dst,float scale,float offset) {
157  (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
158 }
159 static void convert(const s16bit* src, STD_complex* dst,float scale,float offset) {
160  (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
161 }
162 static void convert(const u32bit* src, STD_complex* dst,float scale,float offset) {
163  (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
164 }
165 static void convert(const s32bit* src, STD_complex* dst,float scale,float offset) {
166  (*dst)=STD_complex(src[0]*scale+offset,src[1]*scale);
167 }
168 static void convert(const float *src, STD_complex* dst,float scale,float offset) {
169  dst[0]=STD_complex(src[0]*scale+offset,src[1]*scale);
170 }
171 static void convert(const double *src, STD_complex* dst,float scale,float offset) {
172  dst[0]=STD_complex(src[0]*scale+offset,src[1]*scale);
173 }
174 
175 // from complex
176 static void convert(const STD_complex* src, s8bit* dst,float scale,float offset) {
177  dst[0]=round<s8bit>(src->real()*scale+offset);
178  dst[1]=round<s8bit>(src->imag()*scale);
179 }
180 static void convert(const STD_complex* src, u8bit* dst,float scale,float offset) {
181  dst[0]=round<u8bit>(src->real()*scale+offset);
182  dst[1]=round<u8bit>(src->imag()*scale);
183 }
184 static void convert(const STD_complex* src, s16bit* dst,float scale,float offset) {
185  dst[0]=round<s16bit>(src->real()*scale+offset);
186  dst[1]=round<s16bit>(src->imag()*scale);
187 }
188 static void convert(const STD_complex* src, u16bit* dst,float scale,float offset) {
189  dst[0]=round<u16bit>(src->real()*scale+offset);
190  dst[1]=round<u16bit>(src->imag()*scale);
191 }
192 static void convert(const STD_complex* src, s32bit* dst,float scale,float offset) {
193  dst[0]=round<s32bit>(src->real()*scale+offset);
194  dst[1]=round<s32bit>(src->imag()*scale);
195 }
196 static void convert(const STD_complex* src, u32bit* dst,float scale,float offset) {
197  dst[0]=round<u32bit>(src->real()*scale+offset);
198  dst[1]=round<u32bit>(src->imag()*scale);
199 }
200 static void convert(const STD_complex* src, float* dst,float scale,float offset) {
201  dst[0]=src->real()*scale+offset;
202  dst[1]=src->imag()*scale;
203 }
204 static void convert(const STD_complex* src, double* dst,float scale,float offset) {
205  dst[0]=src->real()*scale+offset;
206  dst[1]=src->imag()*scale;
207 }
208 
209 // from float to integer
210 static void convert(const float* src, s8bit* dst,float scale,float offset) {
211  dst[0]=round<s8bit>(src[0]*scale+offset);
212 }
213 static void convert(const float* src, u8bit* dst,float scale,float offset) {
214  dst[0]=round<u8bit>(src[0]*scale+offset);
215 }
216 static void convert(const float* src, s16bit* dst,float scale,float offset) {
217  dst[0]=round<s16bit>(src[0]*scale+offset);
218 }
219 static void convert(const float* src, u16bit* dst,float scale,float offset) {
220  dst[0]=round<u16bit>(src[0]*scale+offset);
221 }
222 static void convert(const float* src, s32bit* dst,float scale,float offset) {
223  dst[0]=round<s32bit>(src[0]*scale+offset);
224 }
225 static void convert(const float* src, u32bit* dst,float scale,float offset) {
226  dst[0]=round<u32bit>(src[0]*scale+offset);
227 }
228 
229 // from double to integer
230 static void convert(const double* src, s8bit* dst,float scale,float offset) {
231  dst[0]=round<s8bit>(src[0]*scale+offset);
232 }
233 static void convert(const double* src, u8bit* dst,float scale,float offset) {
234  dst[0]=round<u8bit>(src[0]*scale+offset);
235 }
236 static void convert(const double* src, s16bit* dst,float scale,float offset) {
237  dst[0]=round<s16bit>(src[0]*scale+offset);
238 }
239 static void convert(const double* src, u16bit* dst,float scale,float offset) {
240  dst[0]=round<u16bit>(src[0]*scale+offset);
241 }
242 static void convert(const double* src, s32bit* dst,float scale,float offset) {
243  dst[0]=round<s32bit>(src[0]*scale+offset);
244 }
245 static void convert(const double* src, u32bit* dst,float scale,float offset) {
246  dst[0]=round<u32bit>(src[0]*scale+offset);
247 }
248 
249 
250 
251 //default
252 template<typename Src, typename Dst>
253  static void convert(const Src* src, Dst* dst,float scale,float offset) {
254  dst[0]=(Dst)(src[0]*scale+offset);
255 }
256 
258 
259 Converter() {} // Do not allow instances
260 
261 };
262 
266 #endif
static unsigned int get_elements(const T &)
Definition: converter.h:64
static void convert_array(const Src *src, Dst *dst, unsigned int srcsize, unsigned int dstsize, bool autoscale=true)
Definition: converter.h:79
Definition: tjlog.h:218
double secureDivision(double numerator, double denominator)