Openholo  v5.0
Open Source Digital Holographic Library
ophRec.cpp
Go to the documentation of this file.
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install, copy or use the software.
7 //
8 //
9 // License Agreement
10 // For Open Source Digital Holographic Library
11 //
12 // Openholo library is free software;
13 // you can redistribute it and/or modify it under the terms of the BSD 2-Clause license.
14 //
15 // Copyright (C) 2017-2024, Korea Electronics Technology Institute. All rights reserved.
16 // E-mail : contact.openholo@gmail.com
17 // Web : http://www.openholo.org
18 //
19 // Redistribution and use in source and binary forms, with or without modification,
20 // are permitted provided that the following conditions are met:
21 //
22 // 1. Redistribution's of source code must retain the above copyright notice,
23 // this list of conditions and the following disclaimer.
24 //
25 // 2. Redistribution's in binary form must reproduce the above copyright notice,
26 // this list of conditions and the following disclaimer in the documentation
27 // and/or other materials provided with the distribution.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the copyright holder or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 // This software contains opensource software released under GNU Generic Public License,
41 // NVDIA Software License Agreement, or CUDA supplement to Software License Agreement.
42 // Check whether software you use contains licensed software.
43 //
44 //M*/
45 
46 #include "ophRec.h"
47 #include "sys.h"
48 #include "function.h"
49 #include "tinyxml2.h"
50 #include "ImgControl.h"
51 #include <algorithm>
52 //#include "fftw3.h"
53 #include <omp.h>
54 
56  : Openholo()
57  , m_oldSimStep(0)
58  , m_nOldChannel(0)
59  , m_idx(0)
60 {
61 }
62 
64 {
65 }
66 #define IMAGE_VAL(x,y,c,w,n,mem) (mem[x*n + y*w*n + c])
67 vec3 image_sample(float xx, float yy, int c, size_t w, size_t h, double* in);
68 void circshift(Real* in, Real* out, int shift_x, int shift_y, int nx, int ny);
69 void circshift(Complex<Real>* in, Complex<Real>* out, int shift_x, int shift_y, int nx, int ny);
70 void ScaleBilnear(double* src, double* dst, int w, int h, int neww, int newh, double multiplyval = 1.0);
71 void reArrangeChannel(std::vector<double*>& src, double* dst, int pnx, int pny, int chnum);
72 void rotateCCW180(double* src, double* dst, int pnx, int pny, double mulival = 1.0);
73 
74 bool ophRec::readConfig(const char* fname)
75 {
76  bool bRet = true;
77  using namespace tinyxml2;
78  /*XML parsing*/
79  tinyxml2::XMLDocument xml_doc;
80  XMLNode *xml_node;
81 
82  if (!checkExtension(fname, ".xml"))
83  {
84  LOG("<FAILED> Wrong file ext.\n");
85  return false;
86  }
87 
88  auto ret = xml_doc.LoadFile(fname);
89  if (ret != XML_SUCCESS)
90  {
91  LOG("<FAILED> Loading file (%d)\n", ret);
92  return false;
93  }
94 
95  xml_node = xml_doc.FirstChild();
96 
97  int nWave = 1;
98  char szNodeName[32] = { 0, };
99  sprintf(szNodeName, "SLM_WaveNum");
100  auto next = xml_node->FirstChildElement(szNodeName); // OffsetInDepth
101  if (!next || XML_SUCCESS != next->QueryIntText(&nWave))
102  {
103  LOG("<FAILED> Not found node : \'%s\' (Integer) \n", szNodeName);
104  bRet = false;
105  }
106 
107  context_.waveNum = nWave;
109  context_.wave_length = new Real[nWave];
110 
111  for (int i = 1; i <= nWave; i++) {
112  sprintf(szNodeName, "SLM_WaveLength_%d", i);
113  next = xml_node->FirstChildElement(szNodeName);
114  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.wave_length[i - 1]))
115  {
116  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
117  bRet = false;
118  }
119  }
120 
121  sprintf(szNodeName, "SLM_PixelNumX");
122  next = xml_node->FirstChildElement(szNodeName);
123  if (!next || XML_SUCCESS != next->QueryIntText(&context_.pixel_number[_X]))
124  {
125  LOG("<FAILED> Not found node : \'%s\' (Integer) \n", szNodeName);
126  bRet = false;
127  }
128 
129  sprintf(szNodeName, "SLM_PixelNumY");
130  next = xml_node->FirstChildElement(szNodeName);
131  if (!next || XML_SUCCESS != next->QueryIntText(&context_.pixel_number[_Y]))
132  {
133  LOG("<FAILED> Not found node : \'%s\' (Integer) \n", szNodeName);
134  bRet = false;
135  }
136 
137  sprintf(szNodeName, "SLM_PixelPitchX");
138  next = xml_node->FirstChildElement("SLM_PixelPitchX");
139  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.pixel_pitch[_X]))
140  {
141  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
142  bRet = false;
143  }
144 
145  sprintf(szNodeName, "SLM_PixelPitchY");
146  next = xml_node->FirstChildElement("SLM_PixelPitchY");
147  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.pixel_pitch[_Y]))
148  {
149  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
150  bRet = false;
151  }
152 
153  // option
154  next = xml_node->FirstChildElement("IMG_Rotation");
155  if (!next || XML_SUCCESS != next->QueryBoolText(&imgCfg.rotate))
156  imgCfg.rotate = false;
157  next = xml_node->FirstChildElement("IMG_Merge");
158  if (!next || XML_SUCCESS != next->QueryBoolText(&imgCfg.merge))
159  imgCfg.merge = false;
160  next = xml_node->FirstChildElement("IMG_Flip");
161  if (!next || XML_SUCCESS != next->QueryIntText(&imgCfg.flip))
162  imgCfg.flip = 0;
163  next = xml_node->FirstChildElement("EyeLength");
164  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyeLength))
165  bRet = false;
166  next = xml_node->FirstChildElement("EyePupilDiameter");
167  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyePupilDiaMeter))
168  bRet = false;
169  next = xml_node->FirstChildElement("EyeBoxSizeScaleFactor");
170  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyeBoxSizeScale))
171  bRet = false;
172  next = xml_node->FirstChildElement("EyeBoxSizeX");
173  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyeBoxSize[_X]))
174  bRet = false;
175  next = xml_node->FirstChildElement("EyeBoxSizeY");
176  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyeBoxSize[_Y]))
177  bRet = false;
178  next = xml_node->FirstChildElement("EyeBoxUnit");
179  if (!next || XML_SUCCESS != next->QueryIntText(&rec_config.EyeBoxUnit))
180  bRet = false;
181  next = xml_node->FirstChildElement("EyeCenterX");
182  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyeCenter[_X]))
183  bRet = false;
184  next = xml_node->FirstChildElement("EyeCenterY");
185  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyeCenter[_Y]))
186  bRet = false;
187  next = xml_node->FirstChildElement("EyeCenterZ");
188  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyeCenter[_Z]))
189  bRet = false;
190  next = xml_node->FirstChildElement("EyeFocusDistance");
191  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.EyeFocusDistance))
192  bRet = false;
193  next = xml_node->FirstChildElement("ResultSizeScale");
194  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.ResultSizeScale))
195  bRet = false;
196  next = xml_node->FirstChildElement("SimulationTo");
197  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.SimulationTo))
198  bRet = false;
199  next = xml_node->FirstChildElement("SimulationFrom");
200  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.SimulationFrom))
201  bRet = false;
202  next = xml_node->FirstChildElement("SimulationStep");
203  if (!next || XML_SUCCESS != next->QueryIntText(&rec_config.SimulationStep))
204  bRet = false;
205  next = xml_node->FirstChildElement("SimulationMode");
206  if (!next || XML_SUCCESS != next->QueryIntText(&rec_config.SimulationMode))
207  bRet = false;
208  next = xml_node->FirstChildElement("RatioAtRetina");
209  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.RatioAtRetina))
210  bRet = false;
211  next = xml_node->FirstChildElement("RatioAtPupil");
212  if (!next || XML_SUCCESS != next->QueryDoubleText(&rec_config.RatioAtPupil))
213  bRet = false;
214  next = xml_node->FirstChildElement("CreatePupilFieldImg");
215  if (!next || XML_SUCCESS != next->QueryBoolText(&rec_config.CreatePupilFieldImg))
216  bRet = false;
217  next = xml_node->FirstChildElement("CenteringRetinalImg");
218  if (!next || XML_SUCCESS != next->QueryBoolText(&rec_config.CenteringRetinaImg))
219  bRet = false;
220 
223 
224  rec_config.EyeBoxSize = rec_config.EyeBoxSizeScale * rec_config.EyePupilDiaMeter * rec_config.EyeBoxSize;
225 
226  // 2024.04.23. mwnam
227 // set variable for resolution
229 
230  Initialize();
231 
232  LOG("**************************************************\n");
233  LOG(" Read Config (Common) \n");
234  LOG("1) SLM Number of Waves : %d\n", context_.waveNum);
235  for (uint i = 0; i < context_.waveNum; i++)
236  LOG(" 1-%d) SLM Wave length : %e\n", i + 1, context_.wave_length[i]);
237  LOG("2) SLM Resolution : %d x %d\n", context_.pixel_number[_X], context_.pixel_number[_Y]);
238  LOG("3) SLM Pixel Pitch : %e x %e\n", context_.pixel_pitch[_X], context_.pixel_pitch[_Y]);
239  LOG("4) Image Rotate : %s\n", imgCfg.rotate ? "Y" : "N");
240  LOG("5) Image Flip : %s\n", (imgCfg.flip == FLIP::NONE) ? "NONE" :
241  (imgCfg.flip == FLIP::VERTICAL) ? "VERTICAL" :
242  (imgCfg.flip == FLIP::HORIZONTAL) ? "HORIZONTAL" : "BOTH");
243  LOG("6) Image Merge : %s\n", imgCfg.merge ? "Y" : "N");
244  LOG("**************************************************\n");
245 
246  return bRet;
247 }
248 
249 bool ophRec::readImage(const char* path)
250 {
251  const int pnX = context_.pixel_number[_X];
252  const int pnY = context_.pixel_number[_Y];
253  const int N = pnX * pnY;
254 
255  int w, h, bytesperpixel;
256  bool ret = getImgSize(w, h, bytesperpixel, path);
257  uchar* imgload = new uchar[w * h * bytesperpixel];
258 
259  int nLine = ((w * bytesperpixel) + 3) & ~3;
260  int nSize = nLine * h;
261 
262  ret = loadAsImgUpSideDown(path, imgload);
263  if (!ret) {
264  LOG("Failed::Image Load: %s\n", path);
265  return false;
266  }
267  LOG("Succeed::Image Load: %s\n", path);
268 
269  uchar *tmp = new uchar[nSize];
270  memset(tmp, 0, sizeof(char) * nSize);
271 
272  if (w != pnX || h != pnY)
273  {
274  for (int ch = 0; ch < bytesperpixel; ch++)
275  imgScaleBilinear(imgload, tmp, w, h, pnX, pnY, ch);
276  }
277  else
278  memcpy(tmp, imgload, sizeof(char) * nSize);
279 
280  delete[] imgload;
281 
282  for (int ch = 0; ch < bytesperpixel; ch++)
283  {
284  int idx = bytesperpixel - 1 - ch;
285  for (int i = 0; i < N; i++)
286  {
287  int src = i * bytesperpixel;
288  complex_H[ch][i][_RE] = Real(tmp[src + idx]);
289  complex_H[ch][i][_IM] = 0.0;
290  }
291  }
292  delete[] tmp;
293  return true;
294 }
295 
296 bool ophRec::readImagePNA(const char *phase, const char *amplitude)
297 {
298  const int pnX = context_.pixel_number[_X];
299  const int pnY = context_.pixel_number[_Y];
300  const int N = pnX * pnY;
301 
302  int w, h, bytesperpixel;
303  bool ret = getImgSize(w, h, bytesperpixel, phase);
304  uchar* imgload = new uchar[w * h * bytesperpixel];
305 
306  int nLine = ((w * bytesperpixel) + 3) & ~3;
307  int nSize = nLine * h;
308 
309  ret = loadAsImgUpSideDown(phase, imgload);
310  if (!ret) {
311  LOG("Failed::Image Load: %s\n", phase);
312  return false;
313  }
314  LOG("Succeed::Image Load: %s\n", phase);
315 
316  uchar *phaseTmp = new uchar[nSize];
317  memset(phaseTmp, 0, sizeof(char) * nSize);
318 
319  if (w != pnX || h != pnY)
320  {
321  for (int ch = 0; ch < bytesperpixel; ch++)
322  imgScaleBilinear(imgload, phaseTmp, w, h, pnX, pnY, ch);
323  }
324  else
325  memcpy(phaseTmp, imgload, sizeof(char) * nSize);
326 
327  delete[] imgload;
328 
329 
330  ret = getImgSize(w, h, bytesperpixel, amplitude);
331  imgload = new uchar[w * h * bytesperpixel];
332 
333  nLine = ((w * bytesperpixel) + 3) & ~3;
334  nSize = nLine * h;
335 
336  ret = loadAsImgUpSideDown(amplitude, imgload);
337  if (!ret) {
338  LOG("Failed::Image Load: %s\n", amplitude);
339  return false;
340  }
341  LOG("Succeed::Image Load: %s\n", amplitude);
342 
343  uchar *ampTmp = new uchar[nSize];
344  memset(ampTmp, 0, sizeof(char) * nSize);
345 
346  if (w != pnX || h != pnY)
347  {
348  for (int ch = 0; ch < bytesperpixel; ch++)
349  imgScaleBilinear(imgload, ampTmp, w, h, pnX, pnY, ch);
350  }
351  else
352  memcpy(ampTmp, imgload, sizeof(char) * nSize);
353 
354  delete[] imgload;
355 
356  Real PI2 = M_PI * 2;
357 
358  for (int ch = 0; ch < bytesperpixel; ch++)
359  {
360  int idx = bytesperpixel - 1 - ch;
361  for (int i = 0; i < N; i++)
362  {
363  int src = i * bytesperpixel;
364  Real p = Real(phaseTmp[src + idx]);
365  Real a = Real(ampTmp[src + idx]);
366  p = p / 255.0 * PI2 - M_PI; // -pi ~ pi
367  a = a / 255.0; // 0 ~ 1
368  Complex<Real> tmp(0, p);
369  tmp.exp();
370  complex_H[ch][i] = a * tmp;
371 
372  }
373  }
374 
375  delete[] phaseTmp;
376  delete[] ampTmp;
377  return true;
378 }
379 
380 bool ophRec::readImageRNI(const char *real, const char *imag)
381 {
382  const int pnX = context_.pixel_number[_X];
383  const int pnY = context_.pixel_number[_Y];
384  const int N = pnX * pnY;
385 
386  int w, h, bytesperpixel;
387  bool ret = getImgSize(w, h, bytesperpixel, real);
388  uchar* imgload = new uchar[w * h * bytesperpixel];
389 
390  int nLine = ((w * bytesperpixel) + 3) & ~3;
391  int nSize = nLine * h;
392 
393  ret = loadAsImgUpSideDown(real, imgload);
394  if (!ret) {
395  LOG("Failed::Image Load: %s\n", real);
396  return false;
397  }
398  LOG("Succeed::Image Load: %s\n", real);
399 
400  uchar *realTmp = new uchar[nSize];
401  memset(realTmp, 0, sizeof(char) * nSize);
402 
403  if (w != pnX || h != pnY)
404  {
405  for (int ch = 0; ch < bytesperpixel; ch++)
406  imgScaleBilinear(imgload, realTmp, w, h, pnX, pnY, ch);
407  }
408  else
409  memcpy(realTmp, imgload, sizeof(char) * nSize);
410 
411  delete[] imgload;
412 
413 
414  ret = getImgSize(w, h, bytesperpixel, imag);
415  imgload = new uchar[w * h * bytesperpixel];
416  nLine = ((w * bytesperpixel) + 3) & ~3;
417  nSize = nLine * h;
418 
419  ret = loadAsImgUpSideDown(imag, imgload);
420  if (!ret) {
421  LOG("Failed::Image Load: %s\n", imag);
422  return false;
423  }
424  LOG("Succeed::Image Load: %s\n", imag);
425 
426  uchar *imagTmp = new uchar[nSize];
427  memset(imagTmp, 0, sizeof(char) * nSize);
428 
429  if (w != pnX || h != pnY)
430  {
431  for (int ch = 0; ch < bytesperpixel; ch++)
432  imgScaleBilinear(imgload, imagTmp, w, h, pnX, pnY, ch);
433  }
434  else
435  memcpy(imagTmp, imgload, sizeof(char) * nSize);
436 
437  delete[] imgload;
438 
439  for (int ch = 0; ch < bytesperpixel; ch++)
440  {
441  int idx = bytesperpixel - 1 - ch;
442  for (int i = 0; i < N; i++)
443  {
444  int src = i * bytesperpixel;
445  complex_H[ch][i][_RE] = (Real)realTmp[src + idx] / 255.0;
446  complex_H[ch][i][_IM] = (Real)imagTmp[src + idx] / 255.0;
447  }
448  }
449  delete[] realTmp;
450  delete[] imagTmp;
451  return true;
452 }
453 
455 {
456  LOG("Propagation to observer plane\n");
457 
458  const int channel = context_.waveNum;
459  const int pnX = context_.pixel_number[_X];
460  const int pnY = context_.pixel_number[_Y];
461  field_set_.resize(channel);
462  pp_set_.resize(channel);
463  fftw_complex *in = nullptr;
464  fftw_complex *out = nullptr;
465  fftw_plan fftw_plan_fwd = fftw_plan_dft_2d(pnY, pnX, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
466 
467  for (int ch = 0; ch < channel; ch++)
468  {
470  }
471 
472  fftw_destroy_plan(fftw_plan_fwd);
473 }
474 
476 {
477  LOG("Propagation to observer plane\n");
478 
479  const int nChannel = context_.waveNum;
480  const int pnX = context_.pixel_number[_X];
481  const int pnY = context_.pixel_number[_Y];
482  const int N = pnX * pnY;
483  const Real ppX = context_.pixel_pitch[_X];
484  const Real ppY = context_.pixel_pitch[_Y];
485 
486  field_set_.resize(nChannel);
487  pn_set_.resize(nChannel);
488  pp_set_.resize(nChannel);
489 
490  fftw_complex *in = nullptr, *out = nullptr;
491  fftw_plan fft_plan_fwd = fftw_plan_dft_2d(pnY, pnX, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
492 
493  double prop_z = rec_config.EyeCenter[_Z];
494  double f_field = rec_config.EyeCenter[_Z];
495 
496 
497  Real ssX = pnX * ppX;
498  Real ssY = pnY * ppY;
499 
500 
501  for (int ctr = 0; ctr < nChannel; ctr++)
502  {
503  LOG("Color Number: %d\n", ctr + 1);
504 
505  Complex<Real>* u = complex_H[ctr];
506  field_set_[ctr] = new Complex<Real>[N];
507  memset(field_set_[ctr], 0.0, sizeof(Complex<Real>) * N);
508 
509  Real lambda = context_.wave_length[ctr];
510 
511  Real k = 2 * M_PI / lambda;
512  Real kk = k / (prop_z * 2);
513  Real kpropz = k * prop_z;
514  Real lambdapropz = lambda * prop_z;
515  Real ss_res_x = fabs(lambdapropz / ppX);
516  Real ss_res_y = fabs(lambdapropz / ppY);
517  Real hss_res_x = ss_res_x / 2.0;
518  Real hss_res_y = ss_res_y / 2.0;
519  Real pp_res_x = ss_res_x / Real(pnX);
520  Real pp_res_y = ss_res_y / Real(pnY);
521  Real absppX = fabs(lambdapropz / (4 * ppX));
522  Real absppY = fabs(lambdapropz / (4 * ppY));
523 
524  int loopi;
525 #pragma omp parallel for private(loopi)
526  for (loopi = 0; loopi < N; loopi++)
527  {
528  int x = loopi % pnX;
529  int y = loopi / pnX;
530 
531  double xx_src = (-ssX / 2.0) + (ppX * double(x));
532  double yy_src = (ssY / 2.0) - ppY - (ppY * double(y));
533 
534  if (f_field != prop_z)
535  {
536  double effective_f = f_field * prop_z / (f_field - prop_z);
537  double sval = (xx_src*xx_src) + (yy_src*yy_src);
538  sval *= M_PI / lambda / effective_f;
539  Complex<Real> kernel(0, sval);
540  kernel.exp();
541  //exponent_complex(&kernel);
542 
543  double anti_aliasing_mask = fabs(xx_src) < fabs(lambda*effective_f / (4 * ppX)) ? 1 : 0;
544  anti_aliasing_mask *= fabs(yy_src) < fabs(lambda*effective_f / (4 * ppY)) ? 1 : 0;
545 
546  field_set_[ctr][x + y * pnX] = u[x + y * pnX] * kernel * anti_aliasing_mask;
547 
548 
549  }
550  else {
551 
552  field_set_[ctr][x + y * pnX] = u[x + y * pnX];
553 
554  }
555  }
556  //delete[] fringe_[ctr];
557  //free(fringe_[ctr]);
558 
559  fft2(field_set_[ctr], field_set_[ctr], pnX, pnY, FFTW_FORWARD, false);
560 
561 
562 
563 #pragma omp parallel for private(loopi)
564  for (loopi = 0; loopi < N; loopi++)
565  {
566  int x = loopi % pnX;
567  int y = loopi / pnX;
568 
569  double xx_res = (-ss_res_x / 2.0) + (pp_res_x * double(x));
570  double yy_res = (ss_res_y / 2.0) - pp_res_y - (pp_res_y * double(y));
571 
572  Complex<Real> tmp1(0, k*prop_z);
573  tmp1.exp();
574  //exponent_complex(&tmp1);
575 
576  Complex<Real> tmp2(0, lambda*prop_z);
577 
578  double ssval = (xx_res*xx_res) + (yy_res*yy_res);
579  ssval *= k / (2 * prop_z);
580  Complex<Real> tmp3(0, ssval);
581  //exponent_complex(&tmp3);
582  tmp3.exp();
583 
584  Complex<Real> coeff = tmp1 / tmp2 * tmp3;
585 
586  field_set_[ctr][x + y * pnX] *= coeff;
587 
588  }
589  pp_set_[ctr][0] = pp_res_x;
590  pp_set_[ctr][1] = pp_res_y;
591 
592  }
593 
594  fftw_destroy_plan(fft_plan_fwd);
595 }
596 
598 {
599  const int pnX = context_.pixel_number[_X];
600  const int pnY = context_.pixel_number[_Y];
601  const int N = pnX * pnY;
602  const int nWave = context_.waveNum;
603 
604  const Real ppX = context_.pixel_pitch[_X];
605  const Real ppY = context_.pixel_pitch[_Y];
606 
607  const Real simFrom = rec_config.SimulationFrom;
608  const Real simTo = rec_config.SimulationTo;
609  const int simStep = rec_config.SimulationStep;
610  const Real simGap = (simStep > 1) ? (simTo - simFrom) / (simStep - 1) : 0;
611 
612  const Real tx = 1 / ppX;
613  const Real ty = 1 / ppY;
614  const Real dx = tx / pnX;
615  const Real dy = ty / pnY;
616 
617  const Real htx = tx / 2;
618  const Real hty = ty / 2;
619  const Real hdx = dx / 2;
620  const Real hdy = dy / 2;
621  const Real baseX = -htx + hdx;
622  const Real baseY = -hty + hdy;
623 
624  Complex<Real>* tmp = new Complex<Real>[N];
625  Complex<Real>* src = nullptr;
626  Complex<Real>* dst = new Complex<Real>[N];
627  Complex<Real>** kernels = new Complex<Real>*[nWave];// [N];
628  for (int i = 0; i < nWave; i++)
629  {
630  kernels[i] = new Complex<Real>[N];
631  }
632 
633  LOG("%s : Get Spatial Kernel\n", __FUNCTION__);
634  auto begin = CUR_TIME;
635  for (int ch = 0; ch < nWave; ch++)
636  {
637  const Real lambda = context_.wave_length[ch];
638  const Real k = 2 * M_PI / lambda;
639  src = complex_H[ch];
640 
641  // Get Spatial Kernel
642  int i;
643 #ifdef _OPENMP
644 #pragma omp parallel for private(i) firstprivate(pnX, lambda, dx, dy, baseX, baseY)
645 #endif
646  for (i = 0; i < N; i++)
647  {
648  int x = i % pnX;
649  int y = i / pnX;
650 
651  Real curX = baseX + (x * dx);
652  Real curY = baseY + (y * dy);
653  Real xx = curX * lambda;
654  Real yy = curY * lambda;
655  Real powxx = xx * xx;
656  Real powyy = yy * yy;
657 
658  kernels[ch][i][_RE] = 0;
659  kernels[ch][i][_IM] = sqrt(1 - powxx - powyy);
660  }
661  }
662  LOG(" => %lf(s)\n", ELAPSED_TIME(begin, CUR_TIME));
663  LOG("%s : Simultation\n", __FUNCTION__);
664  begin = CUR_TIME;
665 
666  for (int step = 0; step < simStep; step++)
667  {
668  Real min = MAX_DOUBLE, max = MIN_DOUBLE;
669  for (int ch = 0; ch < nWave; ch++)
670  {
671  const Real lambda = context_.wave_length[ch];
672  const Real k = 2 * M_PI / lambda;
673  src = complex_H[ch];
674  fft2(src, tmp, pnX, pnY, FFTW_FORWARD, false);
675  Real z = simFrom + (step * simGap);
676  Real kz = k * z;
677 
678  Real* encode = new Real[N];
679  uchar* normal = new uchar[N];
680 
681  //m_vecEncoded[step] = new Real[N];
682  //m_vecNormalized[step] = new uchar[N];
683 
684  for (int i = 0; i < N; i++)
685  {
686  Complex<Real> kernel = kernels[ch][i];
687  kernel[_IM] *= kz;
688  kernel.exp();
689  tmp[i] *= kernel;
690  }
691 
692  fft2(tmp, dst, pnX, pnY, FFTW_BACKWARD, true);
693 
694  for (int i = 0; i < N; i++)
695  {
696  encode[i] = dst[i].mag();
697 
698  if (min > encode[i])
699  min = encode[i];
700  if (max < encode[i])
701  max = encode[i];
702  }
703 
704  m_vecEncoded.push_back(encode);
705  m_vecNormalized.push_back(normal);
706  }
707 
708  LOG("step: %d => max: %e / min: %e\n", step, max, min);
709  if (nWave == 3)
710  {
711  for (int ch = 0; ch < nWave; ch++)
712  {
713  int idx = step * nWave + ch;
714  normalize(m_vecEncoded[idx], m_vecNormalized[idx], pnX, pnY, max, min);
715  }
716  }
717  else
718  normalize(m_vecEncoded[step], m_vecNormalized[step], pnX, pnY);
719  }
720 
721  m_oldSimStep = simStep;
722  fftFree();
723  LOG(" => %lf(s)\n", ELAPSED_TIME(begin, CUR_TIME));
724 
725  for (int i = 0; i < nWave; i++)
726  delete[] kernels[i];
727  delete[] kernels;
728  delete[] tmp;
729  delete[] dst;
730 
731 
732 }
733 
735 {
736  LOG("Color Number: %d\n", chnum + 1);
737 
738  const int pnX = context_.pixel_number[_X];
739  const int pnY = context_.pixel_number[_Y];
740  const int N = pnX * pnY;
741  Real ppX = context_.pixel_pitch[_X];
742  Real ppY = context_.pixel_pitch[_Y];
743  Real ppX4 = ppX * 4;
744  Real ppY4 = ppY * 4;
745  Real lambda = context_.wave_length[chnum];
746  Real ssX = pnX * ppX;
747  Real ssY = pnY * ppY;
748  Real hssX = ssX / 2.0;
749  Real hssY = ssY / 2.0;
750  Real prop_z = rec_config.EyeCenter[_Z];
751  vec2 cxy = vec2(0);
752 
753  Real k = 2 * M_PI / lambda;
754  Real kk = k / (prop_z * 2);
755  Real kpropz = k * prop_z;
756  Real lambdapropz = lambda * prop_z;
757  Real ss_res_x = fabs(lambdapropz / ppX);
758  Real ss_res_y = fabs(lambdapropz / ppY);
759  Real hss_res_x = ss_res_x / 2.0;
760  Real hss_res_y = ss_res_y / 2.0;
761  Real pp_res_x = ss_res_x / Real(pnX);
762  Real pp_res_y = ss_res_y / Real(pnY);
763 
764  Complex<Real>* tmp = complex_H[chnum];
765  field_set_[chnum] = new Complex<Real>[N];
766  memset(field_set_[chnum], 0.0, sizeof(Complex<Real>) * N);
767 
768  //Real xx_src, yy_src, xx_res, yy_res;
769  //int x, y;
770 
771  Real absppX = fabs(lambdapropz / (ppX4));
772  Real absppY = fabs(lambdapropz / (ppY4));
773 
774  int i;
775 #pragma omp parallel for private(i)
776  for (i = 0; i < N; i++)
777  {
778  int x = i % pnX;
779  int y = i / pnX;
780 
781  Real xx_src = -hssX + (ppX * Real(x));
782  Real yy_src = hssY - ppY - (ppY * Real(y));
783  Real xxx = xx_src - cxy[_X];
784  Real yyy = yy_src - cxy[_Y];
785 
786  Real sval = xxx * xxx + yyy * yyy;
787  sval *= kk;
788  Complex<Real> kernel(0, sval);
789  kernel.exp();
790  //exponent_complex(&kernel);
791 
792  Real anti_aliasing_mask = fabs(xxx) < absppX ? 1 : 0;
793  anti_aliasing_mask *= fabs(yyy) < absppY ? 1 : 0;
794 
795  field_set_[chnum][x + y * pnX] = tmp[x + y * pnX] * kernel * anti_aliasing_mask;
796 
797  }
798  //free(fringe_[chnum]);
799 
800  //fftw_complex *in = nullptr, *out = nullptr;
801  fft2(field_set_[chnum], field_set_[chnum], pnX, pnY, FFTW_FORWARD, false);
802 
803 #pragma omp parallel for private(i)
804  for (i = 0; i < N; i++)
805  {
806  int x = i % pnX;
807  int y = i / pnX;
808 
809  Real xx_res = -hss_res_x + (pp_res_x * Real(x));
810  Real yy_res = hss_res_y - pp_res_y - (pp_res_y * Real(y));
811  Real xxx = xx_res - cxy[_X];
812  Real yyy = yy_res - cxy[_Y];
813 
814  Complex<Real> tmp1(0, kpropz);
815  tmp1.exp();
816  //exponent_complex(&tmp1);
817 
818  Complex<Real> tmp2(0, lambdapropz);
819 
820  Real ssval = xxx * xxx + yyy * yyy;
821  ssval *= kk;
822  Complex<Real> tmp3(0, ssval);
823  tmp3.exp();
824  //exponent_complex(&tmp3);
825 
826  Complex<Real> coeff = tmp1 / tmp2 * tmp3;
827 
828  field_set_[chnum][x + y * pnX] *= coeff;
829 
830  }
831 
832  //pn_set_[chnum] = PIXEL_NUMBER;
833  pp_set_[chnum][_X] = pp_res_x;
834  pp_set_[chnum][_Y] = pp_res_y;
835 }
836 
838 {
839  LOG("Simulation start\n");
840 
841  const int pnX = context_.pixel_number[_X];
842  const int pnY = context_.pixel_number[_Y];
843  const Real ppX = context_.pixel_pitch[_X];
844  const Real ppY = context_.pixel_pitch[_Y];
845  const int nChannel = context_.waveNum;
846  const int simStep = rec_config.SimulationStep;
847  const Real simFrom = rec_config.SimulationFrom;
848  const Real simTo = rec_config.SimulationTo;
849  const int simMode = rec_config.SimulationMode;
850  vec2 boxSize = rec_config.EyeBoxSize;
851  vec3 eyeCenter = rec_config.EyeCenter;
852  Real eyeLen = rec_config.EyeLength;
853  Real eyeFocusDistance = rec_config.EyeFocusDistance;
854  bool bCreatePupilImg = rec_config.CreatePupilFieldImg;
855  bool bCenteringRetinaImg = rec_config.CenteringRetinaImg;
856  Real resultSizeScale = rec_config.ResultSizeScale;
857  Real eyePupil = rec_config.EyePupilDiaMeter;
858  bool bSimPos[3];
859  Real ratioAtRetina = rec_config.RatioAtRetina;
860 
861  memcpy(&bSimPos[0], rec_config.SimulationPos, sizeof(bSimPos));
862 
863  vec3 var_step;
864  std::vector<vec3> var_vals;
865  var_vals.resize(simStep);
866 
867  if (simStep > 1)
868  {
869  var_step = (simTo - simFrom) / (simStep - 1);
870  for (int i = 0; i < simStep; i++)
871  var_vals[i] = simFrom + var_step * i;
872 
873  }
874  else
875  var_vals[0] = (simTo + simFrom) / 2.0;
876 
877  Real lambda, k;
878  int pn_e_x, pn_e_y;
879  Real pp_e_x, pp_e_y, ss_e_x, ss_e_y;
880  int pn_p_x, pn_p_y;
881  Real pp_p_x, pp_p_y, ss_p_x, ss_p_y;
882  vec2 eye_box_range_x, eye_box_range_y;
883  ivec2 eye_box_range_idx, eye_box_range_idy;
884  ivec2 eye_shift_by_pn;
885 
886  field_ret_set_.resize(nChannel);
887  pn_ret_set_.resize(nChannel);
888  pp_ret_set_.resize(nChannel);
889  ss_ret_set_.resize(nChannel);
890  recon_set.resize(simStep * nChannel);
891  img_set.resize(simStep * nChannel);
892  img_size.resize(simStep * nChannel);
893  focus_recon_set.resize(simStep);
894  focus_img_set.resize(simStep);
895  focus_img_size.resize(simStep);
896 
897  std::string varname2;
898 
899  for (int vtr = 0; vtr < simStep; vtr++)
900  {
901  if (simMode == 0) {
902  eyeFocusDistance = var_vals[vtr][_X];
903  }
904  else {
905  if (bSimPos[_X]) eyeCenter[_X] = var_vals[vtr][_X];
906  if (bSimPos[_Y]) eyeCenter[_Y] = var_vals[vtr][_X];
907  if (bSimPos[_Z]) eyeCenter[_Z] = var_vals[vtr][_X];
908  }
909 
910  for (int ctr = 0; ctr < nChannel; ctr++)
911  {
912  lambda = context_.wave_length[ctr];
913  k = 2 * M_PI / lambda;
914 
915  pn_e_x = pnX;
916  pn_e_y = pnY;
917  pp_e_x = pp_set_[ctr][_X];
918  pp_e_y = pp_set_[ctr][_Y];
919  ss_e_x = Real(pn_e_x) * pp_e_x;
920  ss_e_y = Real(pn_e_y) * pp_e_y;
921 
922  eye_shift_by_pn[0] = round(eyeCenter[_X] / pp_e_x);
923  eye_shift_by_pn[1] = round(eyeCenter[_Y] / pp_e_y);
924 
925  Complex<Real>* hh_e_shift = new Complex<Real>[pn_e_x * pn_e_y];
926  memset(hh_e_shift, 0.0, sizeof(Complex<Real>) * pn_e_x * pn_e_y);
927  circshift(field_set_[ctr], hh_e_shift, -eye_shift_by_pn[0], eye_shift_by_pn[1], pn_e_x, pn_e_y);
928 
929 
930  if (rec_config.EyeBoxUnit == 0)
931  {
932  eye_box_range_x[0] = -boxSize[_X] / 2.0;
933  eye_box_range_x[1] = boxSize[_X] / 2.0;
934  eye_box_range_y[0] = -boxSize[_Y] / 2.0;
935  eye_box_range_y[1] = boxSize[_Y] / 2.0;
936  eye_box_range_idx[0] = floor((eye_box_range_x[0] + ss_e_x / 2.0) / pp_e_x);
937  eye_box_range_idx[1] = floor((eye_box_range_x[1] + ss_e_x / 2.0) / pp_e_x);
938  eye_box_range_idy[0] = pn_e_y - floor((eye_box_range_y[1] + ss_e_y / 2.0) / pp_e_y);
939  eye_box_range_idy[1] = pn_e_y - floor((eye_box_range_y[0] + ss_e_y / 2.0) / pp_e_y);
940 
941  }
942  else {
943 
944  int temp = floor((pn_e_x - boxSize[_X]) / 2.0);
945  eye_box_range_idx[0] = temp;
946  eye_box_range_idx[1] = temp + boxSize[_X] - 1;
947  temp = floor((pn_e_y - boxSize[_Y]) / 2.0);
948  eye_box_range_idy[0] = temp;
949  eye_box_range_idy[1] = temp + boxSize[_Y] - 1;
950  }
951 
952  pn_p_x = eye_box_range_idx[1] - eye_box_range_idx[0] + 1;
953  pn_p_y = eye_box_range_idy[1] - eye_box_range_idy[0] + 1;
954  pp_p_x = pp_e_x;
955  pp_p_y = pp_e_y;
956  ss_p_x = pn_p_x * pp_p_x;
957  ss_p_y = pn_p_y * pp_p_y;
958 
959  int N = pn_p_x * pn_p_y;
960  int N2 = pn_e_x * pn_e_y;
961  Complex<Real>* hh_p = new Complex<Real>[N];
962  memset(hh_p, 0.0, sizeof(Complex<Real>) * N);
963 
964  int cropidx = 0;
965 
966  for (int p = 0; p < N2; p++)
967  {
968  int x = p % pn_e_x;
969  int y = p / pn_e_x;
970 
971  if (x >= eye_box_range_idx[0] - 1 && x <= eye_box_range_idx[1] - 1 && y >= eye_box_range_idy[0] - 1 && y <= eye_box_range_idy[1] - 1)
972  {
973  int xx = cropidx % pn_p_x;
974  int yy = cropidx / pn_p_x;
975  hh_p[yy*pn_p_x + xx] = hh_e_shift[p];
976  cropidx++;
977  }
978  }
979  delete[] hh_e_shift;
980 
981  Real f_eye = eyeLen * (eyeCenter[_Z] - eyeFocusDistance) / (eyeLen + (eyeCenter[_Z] - eyeFocusDistance));
982  Real effective_f = f_eye * eyeLen / (f_eye - eyeLen);
983 
984  Complex<Real>* hh_e_ = new Complex<Real>[N];
985  memset(hh_e_, 0.0, sizeof(Complex<Real>) * N);
986 
987  int loopp;
988  //#pragma omp parallel for private(loopp)
989  for (loopp = 0; loopp < N; loopp++)
990  {
991  int x = loopp % pn_p_x;
992  int y = loopp / pn_p_x;
993 
994  Real XE = -ss_p_x / 2.0 + (pp_p_x *x);
995  Real YE = ss_p_y / 2.0 - pp_p_y - (pp_p_y * y);
996 
997  Real sval = (XE*XE) + (YE*YE);
998  sval *= M_PI / lambda / effective_f;
999  Complex<Real> eye_propagation_kernel(0, sval);
1000  eye_propagation_kernel.exp();
1001 
1002  Real eye_lens_anti_aliasing_mask = fabs(XE) < fabs(lambda*effective_f / (4 * pp_e_x)) ? 1.0 : 0.0;
1003  eye_lens_anti_aliasing_mask *= fabs(YE) < fabs(lambda*effective_f / (4 * pp_e_y)) ? 1.0 : 0.0;
1004 
1005  Real eye_pupil_mask = sqrt(XE*XE + YE * YE) < (eyePupil / 2.0) ? 1.0 : 0.0;
1006 
1007  hh_e_[x + y * pn_p_x] = hh_p[x + y * pn_p_x] * eye_propagation_kernel * eye_lens_anti_aliasing_mask * eye_pupil_mask;
1008  }
1009 
1010  delete[] hh_p;
1011 
1012  fft2(hh_e_, hh_e_, pn_p_x, pn_p_y, FFTW_FORWARD, false);
1013 
1014  Real pp_ret_x, pp_ret_y;
1015  int pn_ret_x, pn_ret_y;
1016  vec2 ret_size_xy;
1017 
1018  pp_ret_x = lambda * eyeLen / ss_p_x;
1019  pp_ret_y = lambda * eyeLen / ss_p_y;
1020  pn_ret_x = pn_p_x;
1021  pn_ret_y = pn_p_y;
1022  ret_size_xy[0] = pp_ret_x * pn_ret_x;
1023  ret_size_xy[1] = pp_ret_y * pn_ret_y;
1024 
1025  field_ret_set_[ctr] = new Real[pn_p_x * pn_p_y];
1026  memset(field_ret_set_[ctr], 0.0, sizeof(Real)*pn_p_x*pn_p_y);
1027 
1028  //#pragma omp parallel for private(loopp)
1029  for (loopp = 0; loopp < pn_p_x*pn_p_y; loopp++)
1030  {
1031  int x = loopp % pn_p_x;
1032  int y = loopp / pn_p_x;
1033 
1034  Real XR = ret_size_xy[0] / 2.0 + (pp_ret_x * x);
1035  Real YR = ret_size_xy[1] / 2.0 - pp_ret_y - (pp_ret_y * y);
1036 
1037  Real sval = (XR*XR) + (YR*YR);
1038  sval *= k / (2 * eyeLen);
1039  Complex<Real> val1(0, sval);
1040  val1.exp();
1041 
1042  Complex<Real> val2(0, k * eyeLen);
1043  val2.exp();
1044  Complex<Real> val3(0, lambda * eyeLen);
1045 
1046  field_ret_set_[ctr][x + pn_p_x * y] = (hh_e_[x + pn_p_x * y] * (val1 * val2 / val3)).mag();
1047 
1048  }
1049  delete[] hh_e_;
1050 
1051  pp_ret_set_[ctr] = vec2(pp_ret_x, pp_ret_y);
1052  pn_ret_set_[ctr] = ivec2(pn_ret_x, pn_ret_y);
1053  ss_ret_set_[ctr] = pp_ret_set_[ctr] * pn_ret_set_[ctr];
1054 
1055  if (bCreatePupilImg)
1056  {
1057  Real pp_min = (pp_e_x > pp_e_y) ? pp_e_y : pp_e_x;
1058  Real ss_max = (ss_e_x > ss_e_y) ? ss_e_x : ss_e_y;
1059  Real pn_tar = ceil(ss_max / pp_min);
1060  pp_min = ss_max / pn_tar;
1061  Real pn_e_tar_x = round(ss_e_x / pp_min);
1062  Real pn_e_tar_y = round(ss_e_y / pp_min);
1063 
1064  Real resize_scale_x = pn_e_tar_x * resultSizeScale;
1065  Real resize_scale_y = pn_e_tar_y * resultSizeScale;
1066 
1067  int N = resize_scale_x * resize_scale_y;
1068 
1069  recon_set[vtr * nChannel + ctr] = new Real[N];
1070  img_set[vtr * nChannel + ctr] = new uchar[N];
1071 
1072  memset(recon_set[vtr * nChannel + ctr], 0.0, sizeof(Real) * N);
1073  memset(img_set[vtr * nChannel + ctr], 0, sizeof(uchar) * N);
1074 
1075  GetPupilFieldImage(field_set_[ctr], recon_set[vtr * nChannel + ctr]
1076  , pn_e_x, pn_e_y, pp_e_x, pp_e_y, resize_scale_x, resize_scale_y);
1077 
1078  std::string fname = std::string("./").append("").append("/FIELD/");
1079  fname = fname.append("FIELD_COLOR_").append(std::to_string(ctr + 1)).append("_").append("").append("_SAT_").append("").append("_").append(std::to_string(vtr + 1)).append(".bmp");
1080  normalize(recon_set[vtr * nChannel + ctr], img_set[vtr * nChannel + ctr], (int)resize_scale_x, (int)resize_scale_y);
1081  img_size[vtr * nChannel + ctr][_X] = (int)resize_scale_x;
1082  img_size[vtr * nChannel + ctr][_Y] = (int)resize_scale_y;
1083  }
1084 
1085  } // end of ctr
1086 
1087  Real pnx_max = 0.0, pny_max = 0.0;
1088  for (int i = 0; i < nChannel; i++)
1089  {
1090  pnx_max = (pn_ret_set_[i][0] > pnx_max ? pn_ret_set_[i][0] : pnx_max);
1091  pny_max = (pn_ret_set_[i][1] > pny_max ? pn_ret_set_[i][1] : pny_max);
1092  }
1093 
1094  Real retinal_image_shift_x = eyeCenter[_X] * eyeLen / eyeCenter[_Z];
1095  Real retinal_image_shift_y = eyeCenter[_Y] * eyeLen / eyeCenter[_Z];
1096 
1097  res_set_.resize(nChannel);
1098  res_set_norm_255_.resize(nChannel);
1099 
1100  int loopi;
1101  //#pragma omp parallel for private(loopi)
1102  for (loopi = 0; loopi < nChannel; loopi++)
1103  {
1104  Real lambda = context_.wave_length[loopi];
1105  Real* hh_ret_ = new Real[pn_ret_set_[loopi][0] * pn_ret_set_[loopi][1]];
1106  memset(hh_ret_, 0.0, sizeof(Real)*pn_ret_set_[loopi][0] * pn_ret_set_[loopi][1]);
1107 
1108  if (bCenteringRetinaImg)
1109  {
1110  Real retinal_image_shift_by_pn_x = round(retinal_image_shift_x / pp_ret_set_[loopi][0]);
1111  Real retinal_image_shift_by_pn_y = round(retinal_image_shift_y / pp_ret_set_[loopi][1]);
1112 
1113  circshift(field_ret_set_[loopi], hh_ret_, -retinal_image_shift_by_pn_x, retinal_image_shift_by_pn_y, pn_ret_set_[loopi][0], pn_ret_set_[loopi][1]);
1114 
1115  }
1116  else
1117  hh_ret_ = field_ret_set_[loopi];
1118 
1119  delete[] field_ret_set_[loopi];
1120 
1121  int size = (int)(pnx_max * pny_max);
1122  res_set_[loopi] = new Real[size];
1123  memset(res_set_[loopi], 0.0, sizeof(Real) * size);
1124  ScaleBilnear(hh_ret_, res_set_[loopi], pn_ret_set_[loopi][0], pn_ret_set_[loopi][1], pnx_max, pny_max, lambda * lambda);
1125 
1126  }
1127 
1128  Real maxvalue = res_set_[0][0];
1129  Real minvalue = res_set_[0][0];
1130  for (int i = 0; i < nChannel; i++)
1131  {
1132  for (int j = 0; j < pnx_max*pny_max; j++)
1133  {
1134  maxvalue = res_set_[i][j] > maxvalue ? res_set_[i][j] : maxvalue;
1135  minvalue = res_set_[i][j] < minvalue ? res_set_[i][j] : minvalue;
1136  }
1137  }
1138 
1139  for (int j = 0; j < pnx_max*pny_max; j++)
1140  {
1141  res_set_[0][j] = (res_set_[0][j] - minvalue) / (maxvalue - minvalue) * 255;
1142  }
1143 
1144  //#pragma omp parallel for private(loopi)
1145  for (loopi = 0; loopi < nChannel; loopi++)
1146  {
1147  for (int j = 0; j < pnx_max*pny_max; j++)
1148  {
1149  if (res_set_[loopi][j] > ratioAtRetina * maxvalue)
1150  res_set_[loopi][j] = ratioAtRetina * maxvalue;
1151 
1152  res_set_[loopi][j] = (res_set_[loopi][j] - minvalue) / (ratioAtRetina*maxvalue - minvalue);
1153 
1154  }
1155  }
1156 
1157  Real ret_size_x = pnx_max * resultSizeScale;
1158  Real ret_size_y = pny_max * resultSizeScale;
1159 
1160  int size = (int)(ret_size_x * ret_size_y);
1161 
1162  //#pragma omp parallel for private(loopi)
1163  for (loopi = 0; loopi < nChannel; loopi++)
1164  {
1165  Real* res_set_norm = new Real[size];
1166  memset(res_set_norm, 0.0, sizeof(Real) * size);
1167 
1168  ScaleBilnear(res_set_[loopi], res_set_norm, pnx_max, pny_max, ret_size_x, ret_size_y);
1169 
1170  res_set_norm_255_[loopi] = new Real[size];
1171  memset(res_set_norm_255_[loopi], 0.0, sizeof(Real) * size);
1172 
1173  rotateCCW180(res_set_norm, res_set_norm_255_[loopi], ret_size_x, ret_size_y, 255.0);
1174 
1175  delete[] res_set_norm;
1176  }
1177 
1178  for (int i = 0; i < nChannel; i++)
1179  delete[] res_set_[i];
1180 
1181  int N = ret_size_x * ret_size_y;
1182 
1183  focus_recon_set[vtr] = new Real[N * nChannel];
1184  focus_img_set[vtr] = new uchar[N * nChannel];
1185  memset(focus_recon_set[vtr], 0.0, sizeof(Real) * N * nChannel);
1186  memset(focus_img_set[vtr], 0, sizeof(uchar) * N * nChannel);
1187 
1188  if (nChannel == 1)
1189  memcpy(focus_recon_set[vtr], res_set_norm_255_[0], sizeof(Real)*ret_size_x*ret_size_y);
1190  else
1191  reArrangeChannel(res_set_norm_255_, focus_recon_set[vtr], ret_size_x, ret_size_y, nChannel);
1192 
1193  std::string fname = std::string("./").append("").append("/").append("").append("_SAT_").append("").append("_").append(varname2).append("_").append(std::to_string(vtr + 1)).append(".bmp");
1194 
1195  normalize(focus_recon_set[vtr], focus_img_set[vtr], ret_size_x, ret_size_y);
1196 
1197  focus_img_size[vtr][_X] = (int)ret_size_x;
1198  focus_img_size[vtr][_Y] = (int)ret_size_y;
1199 
1200  m_vecEncoded.push_back(focus_recon_set[vtr]);
1201  m_vecNormalized.push_back(focus_img_set[vtr]);
1202 
1203 
1204  for (int i = 0; i < nChannel; i++)
1205  delete[] res_set_norm_255_[i];
1206  } // end of vtr
1207 }
1208 
1209 bool ophRec::save(const char * fname, uint8_t bitsperpixel, uchar* src, uint px, uint py)
1210 {
1211  bool bOK = false;
1212 
1213  if (fname == nullptr) return bOK;
1214 
1215  uchar* source = src;
1216  bool bAlloc = false;
1217  const uint nChannel = context_.waveNum;
1218 
1219  ivec2 p(px, py);
1220  if (px == 0 && py == 0)
1222 
1223 
1224  std::string file = fname;
1225  std::replace(file.begin(), file.end(), '\\', '/');
1226 
1227  // split path
1228  std::vector<std::string> components;
1229  std::stringstream ss(file);
1230  std::string item;
1231  char token = '/';
1232 
1233  while (std::getline(ss, item, token)) {
1234  components.push_back(item);
1235  }
1236 
1237  std::string dir;
1238 
1239  for (size_t i = 0; i < components.size() - 1; i++)
1240  {
1241  dir += components[i];
1242  dir += "/";
1243  }
1244 
1245  std::string filename = components[components.size() - 1];
1246 
1247  // find extension
1248  bool hasExt;
1249  size_t ext_pos = file.rfind(".");
1250  hasExt = (ext_pos == string::npos) ? false : true;
1251 
1252  if (!hasExt)
1253  filename.append(".bmp");
1254 
1255  std::string fullpath = dir + filename;
1256 
1257  if (nChannel == 1) {
1258  saveAsImg(fullpath.c_str(), bitsperpixel, src, p[_X], p[_Y]);
1259  }
1260  else if (nChannel == 3) {
1261  if (imgCfg.merge) {
1262  uint nSize = (((p[_X] * bitsperpixel >> 3) + 3) & ~3) * p[_Y];
1263  uchar *source = new uchar[nSize];
1264  bAlloc = true;
1265  for (uint i = 0; i < nChannel; i++) {
1266  mergeColor(i, p[_X], p[_Y], src, source);
1267  }
1268  saveAsImg(fullpath.c_str(), bitsperpixel, source, p[_X], p[_Y]);
1269  if (bAlloc) delete[] source;
1270  }
1271  else {
1272  char path[FILENAME_MAX] = { 0, };
1273  sprintf(path, "%s%s", dir.c_str(), filename.c_str());
1274  saveAsImg(path, bitsperpixel / nChannel, src, p[_X], p[_Y]);
1275  }
1276  }
1277  else return false;
1278 
1279  return bOK;
1280 }
1281 
1282 void ophRec::SaveImage(const char *path, const char *ext)
1283 {
1284  int nSimStep = rec_config.SimulationStep;
1285  int nChannel = context_.waveNum;
1286  bool bCreatePupilImg = rec_config.CreatePupilFieldImg;
1287  Real simTo = rec_config.SimulationTo;
1288  Real simFrom = rec_config.SimulationFrom;
1289  Real step = 0.0;
1290 
1291  int pnX;
1292  int pnY;
1293 
1294  if (m_idx == 0)
1295  {
1296  pnX = context_.pixel_number[_X];
1297  pnY = context_.pixel_number[_Y];
1298  }
1299  else
1300  {
1301  pnX = focus_img_size[0][_X];
1302  pnY = focus_img_size[0][_Y];
1303  }
1304  if (nSimStep > 1)
1305  {
1306  step = (simTo - simFrom) / (nSimStep - 1);
1307  }
1308 
1309  char tmpPath[FILENAME_MAX] = { 0, };
1310  bool bMultiStep = nSimStep > 1 ? true : false;
1311  uint nSize = (((pnX * nChannel) + 3) & ~3) * pnY;
1312  uchar *tmp = new uchar[nSize];
1313 
1314  for (int i = 0; i < nSimStep; i++)
1315  {
1316  sprintf(tmpPath, "%s\\FOCUS_%.4f.%s", path, bMultiStep ?
1317  simFrom + (step * i) : (simFrom + simTo) / 2, ext);
1318 
1319  if (nChannel == 3)
1320  {
1321  if (imgCfg.merge)
1322  {
1323  for (int ch = 0; ch < nChannel; ch++)
1324  {
1325  mergeColor(ch, pnX, pnY, m_vecNormalized[i * nChannel + ch], tmp);
1326  }
1327  saveAsImg(tmpPath, 8 * nChannel, tmp, pnX, pnY); // save RGB
1328  }
1329  else
1330  {
1331  for (int ch = 0; ch < nChannel; ch++)
1332  {
1333  memset(tmp, 0, sizeof(uchar) * nSize);
1334  sprintf(tmpPath, "%s\\FOCUS_%.4f (%d).%s", path, bMultiStep ? simFrom + step * i : (simFrom + simTo) / 2, ch, ext);
1335  mergeColor(ch, pnX, pnY, m_vecNormalized[i * nChannel + ch], tmp);
1336  saveAsImg(tmpPath, 8 * nChannel, tmp, pnX, pnY); // save RGB
1337  }
1338  }
1339  }
1340  else
1341  {
1342  memcpy(tmp, m_vecNormalized[i], sizeof(uchar) * nSize);
1343  saveAsImg(tmpPath, 8 * nChannel, tmp, pnX, pnY); // save Grayscale
1344  }
1345  }
1346  delete[] tmp;
1347 }
1348 
1349 void ophRec::GetPupilFieldImage(Complex<Real>* src, Real* dst, int pnx, int pny, Real ppx, Real ppy, Real scaleX, Real scaleY)
1350 {
1351  const int N = pnx * pny;
1352  Real ratioAtPupil = rec_config.RatioAtPupil;
1353  Real eyePupil = rec_config.EyePupilDiaMeter;
1354  vec3 eyeCenter = rec_config.EyeCenter;
1355 
1356 
1357  Real* dimg = new Real[N];
1358  memset(dimg, 0.0, sizeof(Real) * N);
1359 
1360  Real maxvalue = src[0].mag();
1361  for (int k = 0; k < N; k++)
1362  {
1363  Real val = src[k].mag();
1364  maxvalue = val > maxvalue ? val : maxvalue;
1365  dimg[k] = val;
1366  }
1367 
1368  Real SAT_VAL = maxvalue * ratioAtPupil;
1369  Real hss_x = (pnx * ppx) / 2.0;
1370  Real hss_y = (pny * ppy) / 2.0;
1371  Real halfPupil = eyePupil / 2.0;
1372 
1373  Real maxv = dimg[0], minv = dimg[0];
1374  for (int k = 0; k < N; k++)
1375  {
1376  if (dimg[k] > SAT_VAL)
1377  dimg[k] = SAT_VAL;
1378 
1379  maxv = (dimg[k] > maxv) ? dimg[k] : maxv;
1380  minv = (dimg[k] < minv) ? dimg[k] : minv;
1381  }
1382 
1383  for (int k = 0; k < N; k++)
1384  {
1385  int x = k % pnx;
1386  int y = k / pnx;
1387 
1388  Real xx = -hss_x + (ppx * x);
1389  Real yy = -hss_y + (pny - 1) * ppy - (ppy * y);
1390  Real xxx = xx - eyeCenter[_X];
1391  Real yyy = yy - eyeCenter[_Y];
1392  bool eye_pupil_mask = sqrt(xxx * xxx + yyy * yyy) < halfPupil ? 1.0 : 0.0;
1393 
1394  Real val = dimg[k];
1395  Real field_out = (val - minv) / (maxv - minv) * 255.0;
1396  Real field_in = (val - minv) / (maxv - minv) * 127.0 + 128.0;
1397  dimg[k] = field_in * eye_pupil_mask + field_out * (1 - eye_pupil_mask);
1398  //dimg[k] = field_in * eye_pupil_mask;
1399 
1400  }
1401  ScaleBilnear(dimg, dst, pnx, pny, scaleX, scaleY);
1402 
1403  delete[] dimg;
1404 }
1405 
1406 void ophRec::getVarname(int vtr, vec3& var_vals, std::string& varname2)
1407 {
1408  bool bSimPos[3];
1409  memcpy(&bSimPos[0], rec_config.SimulationPos, sizeof(bSimPos));
1410 
1411  std::string varname;
1412  varname.clear();
1413  varname2.clear();
1414  if (rec_config.SimulationMode == 0) {
1415 
1416  varname.append("FOCUS");
1417 
1418  LOG("Step # %d %s = %.8f \n", vtr + 1, varname.c_str(), var_vals[0]);
1419  char temp[100];
1420  sprintf(temp, "%.5f", var_vals[0]);
1421  varname2.clear();
1422  varname2.append(varname).append("_").append(temp);
1423  varname2.replace(varname2.find('.'), 1, "_");
1424 
1425  }
1426  else {
1427 
1428  varname.append("POSITION");
1429 
1430  if (bSimPos[_X]) varname.append("_X");
1431  if (bSimPos[_Y]) varname.append("_Y");
1432  if (bSimPos[_Z]) varname.append("_Z");
1433 
1434  LOG("Step # %d %s = ", vtr + 1, varname.c_str());
1435  varname2.clear();
1436  varname2.append(varname);
1437 
1438  if (bSimPos[_X]) {
1439  LOG("%.8f ", var_vals[0]);
1440  char temp[100];
1441  sprintf(temp, "%.5f", var_vals[0]);
1442  varname2.append("_").append(temp);
1443  varname2.replace(varname2.find('.'), 1, "_");
1444  }
1445  if (bSimPos[_Y]) {
1446  LOG("%.8f ", var_vals[1]);
1447  char temp[100];
1448  sprintf(temp, "%.5f", var_vals[1]);
1449  varname2.append("_").append(temp);
1450  varname2.replace(varname2.find('.'), 1, "_");
1451  }
1452  if (bSimPos[_Z]) {
1453  LOG("%.8f ", var_vals[2]);
1454  char temp[100];
1455  sprintf(temp, "%.5f", var_vals[2]);
1456  varname2.append("_").append(temp);
1457  varname2.replace(varname2.find('.'), 1, "_");
1458  }
1459  LOG("\n");
1460  }
1461 }
1462 
1464 {
1465  for (vector<Real*>::iterator it = m_vecEncoded.begin(); it != m_vecEncoded.end(); it++)
1466  {
1467  delete[](*it);
1468  }
1469 
1470  for (vector<uchar*>::iterator it = m_vecNormalized.begin(); it != m_vecNormalized.end(); it++)
1471  {
1472  delete[](*it);
1473  }
1474  m_vecEncoded.clear();
1475  m_vecNormalized.clear();
1476 }
1477 
1479 {
1480 
1481  Clear();
1482  auto begin = CUR_TIME;
1483 
1484  LOG("1) Algorithm Method : Angular Spectrum\n");
1485  LOG("2) Reconstruct Image with %s\n", m_mode & MODE_GPU ?
1486  "GPU" :
1487 #ifdef _OPENMP
1488  "Multi Core CPU"
1489 #else
1490  "Single Core CPU"
1491 #endif
1492  );
1493 
1494  m_mode & MODE_GPU ? ASM_Propagation_GPU() : ASM_Propagation();
1495 
1496  LOG("Total Elapsed Time: %lf (s)\n", ELAPSED_TIME(begin, CUR_TIME));
1497  return true;
1498 }
1499 
1501 {
1502  const int nChannel = context_.waveNum;
1503  const int N = context_.pixel_number[_X] * context_.pixel_number[_Y];
1504 
1505  // Memory Location for Result Image
1506  if (complex_H != nullptr) {
1507  for (int i = 0; i < m_nOldChannel; i++) {
1508  if (complex_H[i] != nullptr) {
1509  delete[] complex_H[i];
1510  complex_H[i] = nullptr;
1511  }
1512  }
1513  delete[] complex_H;
1514  complex_H = nullptr;
1515  }
1516  complex_H = new Complex<Real>*[nChannel];
1517  for (int i = 0; i < nChannel; i++) {
1518  complex_H[i] = new Complex<Real>[N];
1519  memset(complex_H[i], 0, sizeof(Complex<Real>) * N);
1520  }
1521  m_nOldChannel = nChannel;
1522 }
1523 
1525 {
1527 
1528  for (vector<Real*>::iterator it = m_vecEncoded.begin(); it != m_vecEncoded.end(); it++)
1529  {
1530  delete (*it);
1531  }
1532  m_vecEncoded.clear();
1533 
1534  for (vector<uchar*>::iterator it = m_vecNormalized.begin(); it != m_vecNormalized.end(); it++)
1535  {
1536  delete (*it);
1537  }
1538  m_vecNormalized.clear();
1539 }
1540 
1541 void circshift(Real* in, Real* out, int shift_x, int shift_y, int nx, int ny)
1542 {
1543  int ti, tj;
1544  for (int i = 0; i < nx; i++)
1545  {
1546  for (int j = 0; j < ny; j++)
1547  {
1548  ti = (i + shift_x) % nx;
1549  if (ti < 0)
1550  ti = ti + nx;
1551  tj = (j + shift_y) % ny;
1552  if (tj < 0)
1553  tj = tj + ny;
1554 
1555  out[ti + tj * nx] = in[i + j * nx];
1556  }
1557  }
1558 }
1559 
1560 void circshift(Complex<Real>* in, Complex<Real>* out, int shift_x, int shift_y, int nx, int ny)
1561 {
1562  int ti, tj;
1563  for (int i = 0; i < nx; i++)
1564  {
1565  for (int j = 0; j < ny; j++)
1566  {
1567  ti = (i + shift_x) % nx;
1568  if (ti < 0)
1569  ti = ti + nx;
1570  tj = (j + shift_y) % ny;
1571  if (tj < 0)
1572  tj = tj + ny;
1573 
1574  out[ti + tj * nx] = in[i + j * nx];
1575  }
1576  }
1577 }
1578 
1579 vec3 image_sample(float xx, float yy, int c, size_t w, size_t h, double* in)
1580 {
1581  int x1 = (int)floor(xx);
1582  int x2 = (int)ceil(xx);
1583  int y1 = (int)floor(yy);
1584  int y2 = (int)ceil(yy);
1585 
1586  if (x1 < 0 || x1 >= (int)w || x2 < 0 || x2 >= (int)w) return vec3(0);
1587  if (y1 < 0 || y1 >= (int)h || y2 < 0 || y2 >= (int)h) return vec3(0);
1588 
1589  vec3 ret(0);
1590  double v1, v2, v3, v4, tvx, tvy;
1591 
1592  tvx = xx - floor(xx);
1593  tvy = yy - floor(yy);
1594  int tc = min(c, 3);
1595  for (int i = 0; i < tc; i++) {
1596  v1 = IMAGE_VAL(x1, y1, i, w, c, in);
1597  v2 = IMAGE_VAL(x2, y1, i, w, c, in);
1598  v3 = IMAGE_VAL(x1, y2, i, w, c, in);
1599  v4 = IMAGE_VAL(x2, y2, i, w, c, in);
1600  v1 = (1.0 - tvx)*v1 + tvx * v2;
1601  v3 = (1.0 - tvx)*v3 + tvx * v4;
1602  v1 = (1.0 - tvy)*v1 + tvy * v3;
1603 
1604  ret[i] = v1;
1605  }
1606 
1607  return ret;
1608 }
1609 
1610 void ScaleBilnear(double* src, double* dst, int w, int h, int neww, int newh, double multiplyval)
1611 {
1612  for (int y = 0; y < newh; y++)
1613  {
1614  for (int x = 0; x < neww; x++)
1615  {
1616  float gx = (x / (float)neww) * (w - 1);
1617  float gy = (y / (float)newh) * (h - 1);
1618 
1619  vec3 ret = multiplyval * image_sample(gx, gy, 1, w, h, src);
1620  dst[x + y * neww] = ret[0];
1621 
1622  /*
1623  int gxi = (int)gx;
1624  int gyi = (int)gy;
1625 
1626  double a00 = src[gxi + 0 + gyi * w];
1627  double a01 = src[gxi + 1 + gyi * w];
1628  double a10 = src[gxi + 0 + (gyi + 1)*w];
1629  double a11 = src[gxi + 1 + (gyi + 1)*w];
1630 
1631  float dx = gx - gxi;
1632  float dy = gy - gyi;
1633 
1634  dst[x + y * neww] = multiplyval * (a00 * (1 - dx)*(1 - dy) + a01 * dx*(1 - dy) + a10 * (1 - dx)*dy + a11 * dx*dy);
1635  */
1636 
1637  }
1638  }
1639 }
1640 
1641 
1642 
1643 void rotateCCW180(double* src, double* dst, int pnx, int pny, double mulival)
1644 {
1645  for (int i = 0; i < pnx*pny; i++)
1646  {
1647  int x = i % pnx;
1648  int y = i / pnx;
1649 
1650  int newx = pnx - x - 1;
1651  int newy = pny - y - 1;
1652 
1653  dst[newx + newy * pnx] = mulival * src[x + y * pnx];
1654 
1655  }
1656 
1657 }
1658 
1659 void reArrangeChannel(std::vector<double*>& src, double* dst, int pnx, int pny, int chnum)
1660 {
1661  for (int k = 0; k < pnx*pny; k++)
1662  {
1663  for (int c = 0; c < chnum; c++)
1664  {
1665  if (c == 0)
1666  dst[k*chnum + 2] = src[c][k];
1667  else if (c == 2)
1668  dst[k*chnum + 0] = src[c][k];
1669  else
1670  dst[k*chnum + c] = src[c][k];
1671  }
1672 
1673  }
1674 }
Real SimulationTo
Definition: ophRec.h:78
bytesperpixel
Definition: Openholo.cpp:431
Real RatioAtRetina
Definition: ophRec.h:82
void GetPupilFieldImage(Complex< Real > *src, Real *dst, int pnx, int pny, Real ppx, Real ppy, Real scaleX, Real scaleY)
Definition: ophRec.cpp:1349
Abstract class.
Definition: Openholo.h:145
virtual bool saveAsImg(const char *fname, uint8_t bitsperpixel, uchar *src, int width, int height)
Function for creating image files.
Definition: Openholo.cpp:135
ResolutionConfig resCfg
Definition: Openholo.h:487
int SimulationStep
Definition: ophRec.h:80
NONE
Definition: ImgControl.h:25
void fftFree(void)
Resource release method.
Definition: Openholo.cpp:677
#define IMAGE_VAL(x, y, c, w, n, mem)
Definition: ophRec.cpp:66
Real SimulationFrom
Definition: ophRec.h:79
void GetPupilFieldFromVWHologram()
Definition: ophRec.cpp:475
Real * wave_length
Definition: Openholo.h:106
vec3 image_sample(float xx, float yy, int c, size_t w, size_t h, double *in)
Definition: ophRec.cpp:1579
void Clear()
Definition: ophRec.cpp:1463
unsigned char uchar
Definition: typedef.h:64
VERTICAL
Definition: ImgControl.h:25
void SaveImage(const char *path, const char *ext="bmp")
Definition: ophRec.cpp:1282
#define MODE_GPU
Definition: define.h:156
void reArrangeChannel(std::vector< double *> &src, double *dst, int pnx, int pny, int chnum)
Definition: ophRec.cpp:1659
float Real
Definition: typedef.h:55
void Initialize()
Definition: ophRec.cpp:1500
vec3 EyeCenter
Definition: ophRec.h:75
#define CUR_TIME
Definition: function.h:58
vec2 ss
Definition: Openholo.h:104
HORIZONTAL
Definition: ImgControl.h:25
bool checkExtension(const char *fname, const char *ext)
Functions for extension checking.
Definition: Openholo.cpp:86
structure for 2-dimensional integer vector and its arithmetic.
Definition: ivec.h:66
void rotateCCW180(double *src, double *dst, int pnx, int pny, double mulival=1.0)
Definition: ophRec.cpp:1643
void getVarname(int vtr, vec3 &var_vals, std::string &varname2)
Definition: ophRec.cpp:1406
virtual void ophFree(void)
Pure virtual function for override in child classes.
Definition: ophRec.cpp:1524
void circshift(Real *in, Real *out, int shift_x, int shift_y, int nx, int ny)
Definition: ophRec.cpp:1541
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:761
bool readImage(const char *path)
Definition: ophRec.cpp:249
virtual ~ophRec(void)
Destructor.
Definition: ophRec.cpp:63
bool rotate
Definition: Openholo.h:124
#define MIN_DOUBLE
Definition: define.h:148
#define _Y
Definition: define.h:96
#define _IM
Definition: complex.h:58
vec2 EyeBoxSize
Definition: ophRec.h:73
ImageConfig imgCfg
Definition: Openholo.h:488
bool CreatePupilFieldImg
Definition: ophRec.h:84
vec2 pixel_pitch
Definition: Openholo.h:101
void GetPupilFieldFromHologram()
Definition: ophRec.cpp:454
Real RatioAtPupil
Definition: ophRec.h:83
bool SimulationPos[3]
Definition: ophRec.h:87
void ASM_Propagation()
Definition: ophRec.cpp:597
#define _X
Definition: define.h:92
return true
Definition: Openholo.cpp:434
bool ReconstructImage()
Definition: ophRec.cpp:1478
Real EyeFocusDistance
Definition: ophRec.h:76
void imgScaleBilinear(uchar *src, uchar *dst, int w, int h, int neww, int newh, int channels=1)
Function for change image size.
Definition: Openholo.cpp:437
#define FFTW_FORWARD
Definition: fftw3.h:379
bool getImgSize(int &w, int &h, int &bytesperpixel, const char *fname)
Function for getting the image size.
Definition: Openholo.cpp:402
bool readImagePNA(const char *phase, const char *amplitude)
Definition: ophRec.cpp:296
#define _RE
Definition: complex.h:55
Real EyePupilDiaMeter
Definition: ophRec.h:71
bool readImageRNI(const char *real, const char *imaginary)
Definition: ophRec.cpp:380
void fft2(ivec2 n, Complex< Real > *in, int sign=OPH_FORWARD, uint flag=OPH_ESTIMATE)
Functions for performing fftw 2-dimension operations inside Openholo.
Definition: Openholo.cpp:559
ophRec(void)
Constructor.
Definition: ophRec.cpp:55
structure for 2-dimensional Real type vector and its arithmetic.
Definition: vec.h:66
void ScaleBilnear(double *src, double *dst, int w, int h, int neww, int newh, double multiplyval=1.0)
Definition: ophRec.cpp:1610
int SimulationMode
Definition: ophRec.h:81
#define MAX_DOUBLE
Definition: define.h:140
#define ELAPSED_TIME(x, y)
Definition: function.h:59
uint waveNum
Definition: Openholo.h:105
structure for 3-dimensional Real type vector and its arithmetic.
Definition: vec.h:466
Complex< T > & exp()
Definition: complex.h:395
ivec2 pixel_number
Definition: Openholo.h:99
Real EyeLength
Definition: ophRec.h:70
bool save(const char *fname, uint8_t bitsperpixel, uchar *src, uint px, uint py)
Definition: ophRec.cpp:1209
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2150
bool CenteringRetinaImg
Definition: ophRec.h:85
void ASM_Propagation_GPU()
Definition: ophRec_GPU.cpp:49
bool readConfig(const char *fname)
Definition: ophRec.cpp:74
int EyeBoxUnit
Definition: ophRec.h:74
w
Definition: Openholo.cpp:429
void Perform_Simulation()
Definition: ophRec.cpp:837
#define FFTW_ESTIMATE
Definition: fftw3.h:392
OphConfig context_
Definition: Openholo.h:486
#define FFTW_BACKWARD
Definition: fftw3.h:380
void Propagation_Fresnel_FFT(int chnum)
Definition: ophRec.cpp:734
Complex< Real > ** complex_H
Definition: Openholo.h:490
T mag() const
Definition: complex.h:368
Real ResultSizeScale
Definition: ophRec.h:77
#define _Z
Definition: define.h:100
bool loadAsImgUpSideDown(const char *fname, uchar *dst)
Function for loading image files | Output image data upside down.
Definition: Openholo.cpp:353
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:940
bool mergeColor(int idx, int width, int height, uchar *src, uchar *dst)
Function for generate RGB image from each grayscale image.
Definition: Openholo.cpp:103
unsigned int uint
Definition: typedef.h:62
virtual void ophFree(void)
Pure virtual function for override in child classes.
Definition: Openholo.cpp:811
void normalize(T *src, uchar *dst, int x, int y)
Definition: ophRec.h:177
bool merge
Definition: Openholo.h:125
#define M_PI
Definition: define.h:52
h
Definition: Openholo.cpp:430