Openholo  v4.0
Open Source Digital Holographic Library
ophGen.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 "ophGen.h"
47 #include "sys.h"
48 #include "function.h"
49 #include <cuda_runtime_api.h>
50 #include <cufft.h>
51 #include <omp.h>
52 #include <iostream>
53 #include <sstream>
54 #include <algorithm>
55 #include "ImgControl.h"
56 #include "tinyxml2.h"
57 #include "PLYparser.h"
58 
59 extern "C"
60 {
73  void cudaFFT(CUstream_st* stream, int nx, int ny, cufftDoubleComplex* in_filed, cufftDoubleComplex* output_field, int direction, bool bNormailized = false);
74 
89  void cudaCropFringe(CUstream_st* stream, int nx, int ny, cufftDoubleComplex* in_field, cufftDoubleComplex* out_field, int cropx1, int cropx2, int cropy1, int cropy2);
90 
108  void cudaGetFringe(CUstream_st* stream, int pnx, int pny, cufftDoubleComplex* in_field, cufftDoubleComplex* out_field, int sig_locationx, int sig_locationy,
109  Real ssx, Real ssy, Real ppx, Real ppy, Real PI);
110 }
111 
113  : Openholo()
114  , m_vecEncodeSize()
115  , ENCODE_METHOD(0)
116  , SSB_PASSBAND(0)
117  , m_elapsedTime(0.0)
118  , m_lpEncoded(nullptr)
119  , m_lpNormalized(nullptr)
120  , m_nOldChannel(0)
121  , m_precision(PRECISION::DOUBLE)
122  , m_dFieldLength(0.0)
123  , m_nStream(1)
124  , m_mode(0)
125  , AS(nullptr)
126  , normalized(nullptr)
127  , fftTemp(nullptr)
128  , weight(nullptr)
129  , weightC(nullptr)
130  , freqW(nullptr)
131  , realEnc(nullptr)
132  , binary(nullptr)
133  , maskSSB(nullptr)
134  , maskHP(nullptr)
135  , m_bRandomPhase(false)
136 {
137 
138 }
139 
141 {
142 
143 }
144 
146 {
147  // Output Image Size
148  const long long int pnXY = context_.pixel_number[_X] * context_.pixel_number[_Y];
149  const uint nChannel = context_.waveNum;
150 
151  // Memory Location for Result Image
152  if (complex_H != nullptr) {
153  for (uint i = 0; i < m_nOldChannel; i++) {
154  if (complex_H[i] != nullptr) {
155  delete[] complex_H[i];
156  complex_H[i] = nullptr;
157  }
158  }
159  delete[] complex_H;
160  complex_H = nullptr;
161  }
162 
163  complex_H = new Complex<Real>*[nChannel];
164  for (uint i = 0; i < nChannel; i++) {
165  complex_H[i] = new Complex<Real>[pnXY];
166  memset(complex_H[i], 0, sizeof(Complex<Real>) * pnXY);
167  }
168 
169  if (m_lpEncoded != nullptr) {
170  for (uint i = 0; i < m_nOldChannel; i++) {
171  if (m_lpEncoded[i] != nullptr) {
172  delete[] m_lpEncoded[i];
173  m_lpEncoded[i] = nullptr;
174  }
175  }
176  delete[] m_lpEncoded;
177  m_lpEncoded = nullptr;
178  }
179  m_lpEncoded = new Real*[nChannel];
180  for (uint i = 0; i < nChannel; i++) {
181  m_lpEncoded[i] = new Real[pnXY];
182  memset(m_lpEncoded[i], 0, sizeof(Real) * pnXY);
183  }
184 
185  if (m_lpNormalized != nullptr) {
186  for (uint i = 0; i < m_nOldChannel; i++) {
187  if (m_lpNormalized[i] != nullptr) {
188  delete[] m_lpNormalized[i];
189  m_lpNormalized[i] = nullptr;
190  }
191  }
192  delete[] m_lpNormalized;
193  m_lpNormalized = nullptr;
194  }
195  m_lpNormalized = new uchar*[nChannel];
196  for (uint i = 0; i < nChannel; i++) {
197  m_lpNormalized[i] = new uchar[pnXY];
198  memset(m_lpNormalized[i], 0, sizeof(uchar) * pnXY);
199  }
200 
201  m_nOldChannel = nChannel;
204 }
205 
206 int ophGen::loadPointCloud(const char* pc_file, OphPointCloudData *pc_data_)
207 {
208  int n_points = 0;
209  auto begin = CUR_TIME;
210 
211  PLYparser plyIO;
212  if (!plyIO.loadPLY(pc_file, pc_data_->n_points, &pc_data_->vertices))
213  n_points = -1;
214  else
215  n_points = pc_data_->n_points;
216  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
217  return n_points;
218 }
219 
220 bool ophGen::readConfig(const char* fname)
221 {
222  bool bRet = true;
223  using namespace tinyxml2;
224  tinyxml2::XMLDocument xml_doc;
225  XMLNode *xml_node = nullptr;
226 
227  if (!checkExtension(fname, ".xml"))
228  {
229  LOG("<FAILED> Wrong file ext.\n");
230  return false;
231  }
232  auto ret = xml_doc.LoadFile(fname);
233  if (ret != XML_SUCCESS)
234  {
235  LOG("<FAILED> Loading file (%d)\n", ret);
236  return false;
237  }
238  xml_node = xml_doc.FirstChild();
239 
240  int nWave = 1;
241  char szNodeName[32] = { 0, };
242 
243  sprintf(szNodeName, "SLM_WaveNum");
244  auto next = xml_node->FirstChildElement(szNodeName); // OffsetInDepth
245  if (!next || XML_SUCCESS != next->QueryIntText(&nWave))
246  {
247  LOG("<FAILED> Not found node : \'%s\' (Integer) \n", szNodeName);
248  bRet = false;
249  }
250  context_.waveNum = nWave;
252  context_.wave_length = new Real[nWave];
253 
254  for (int i = 1; i <= nWave; i++) {
255  sprintf(szNodeName, "SLM_WaveLength_%d", i);
256  next = xml_node->FirstChildElement(szNodeName);
257  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.wave_length[i - 1]))
258  {
259  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
260  bRet = false;
261  }
262  }
263 
264  sprintf(szNodeName, "SLM_PixelNumX");
265  next = xml_node->FirstChildElement(szNodeName);
266  if (!next || XML_SUCCESS != next->QueryIntText(&context_.pixel_number[_X]))
267  {
268  LOG("<FAILED> Not found node : \'%s\' (Integer) \n", szNodeName);
269  bRet = false;
270  }
271 
272  sprintf(szNodeName, "SLM_PixelNumY");
273  next = xml_node->FirstChildElement(szNodeName);
274  if (!next || XML_SUCCESS != next->QueryIntText(&context_.pixel_number[_Y]))
275  {
276  LOG("<FAILED> Not found node : \'%s\' (Integer) \n", szNodeName);
277  bRet = false;
278  }
279 
280  sprintf(szNodeName, "SLM_PixelPitchX");
281  next = xml_node->FirstChildElement("SLM_PixelPitchX");
282  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.pixel_pitch[_X]))
283  {
284  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
285  bRet = false;
286  }
287 
288  sprintf(szNodeName, "SLM_PixelPitchY");
289  next = xml_node->FirstChildElement("SLM_PixelPitchY");
290  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.pixel_pitch[_Y]))
291  {
292  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
293  bRet = false;
294  }
295 
296  // option
297  next = xml_node->FirstChildElement("IMG_Rotation");
298  if (!next || XML_SUCCESS != next->QueryBoolText(&imgCfg.rotate))
299  imgCfg.rotate = false;
300  next = xml_node->FirstChildElement("IMG_Merge");
301  if (!next || XML_SUCCESS != next->QueryBoolText(&imgCfg.merge))
302  imgCfg.merge = false;
303  next = xml_node->FirstChildElement("IMG_Flip");
304  if (!next || XML_SUCCESS != next->QueryIntText(&imgCfg.flip))
305  imgCfg.flip = 0;
306  next = xml_node->FirstChildElement("DoublePrecision");
307  if (!next || XML_SUCCESS != next->QueryBoolText(&context_.bUseDP))
308  context_.bUseDP = true;
309  next = xml_node->FirstChildElement("ShiftX");
310  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.shift[_X]))
311  context_.shift[_X] = 0.0;
312  next = xml_node->FirstChildElement("ShiftY");
313  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.shift[_Y]))
314  context_.shift[_Y] = 0.0;
315  next = xml_node->FirstChildElement("ShiftZ");
316  if (!next || XML_SUCCESS != next->QueryDoubleText(&context_.shift[_Z]))
317  context_.shift[_Z] = 0.0;
318  next = xml_node->FirstChildElement("FieldLength");
319  if (!next || XML_SUCCESS != next->QueryDoubleText(&m_dFieldLength))
320  m_dFieldLength = 0.0;
321  next = xml_node->FirstChildElement("RandomPhase");
322  if (!next || XML_SUCCESS != next->QueryBoolText(&m_bRandomPhase))
323  m_bRandomPhase = false;
324  next = xml_node->FirstChildElement("NumOfStream");
325  if (!next || XML_SUCCESS != next->QueryIntText(&m_nStream))
326  m_nStream = 1;
327 
330 
333 
335  for (int i = 0; i < nWave; i++)
337 
338  LOG("**************************************************\n");
339  LOG(" Read Config (Common) \n");
340  LOG("1) SLM Number of Waves : %d\n", context_.waveNum);
341  for (uint i = 0; i < context_.waveNum; i++)
342  LOG(" 1-%d) SLM Wave length : %e\n", i + 1, context_.wave_length[i]);
343  LOG("2) SLM Resolution : %d x %d\n", context_.pixel_number[_X], context_.pixel_number[_Y]);
344  LOG("3) SLM Pixel Pitch : %e x %e\n", context_.pixel_pitch[_X], context_.pixel_pitch[_Y]);
345  LOG("4) Image Rotate : %s\n", imgCfg.rotate ? "Y" : "N");
346  LOG("5) Image Flip : %s\n", (imgCfg.flip == FLIP::NONE) ? "NONE" :
347  (imgCfg.flip == FLIP::VERTICAL) ? "VERTICAL" :
348  (imgCfg.flip == FLIP::HORIZONTAL) ? "HORIZONTAL" : "BOTH");
349  LOG("6) Image Merge : %s\n", imgCfg.merge ? "Y" : "N");
350  LOG("**************************************************\n");
351 
352  return bRet;
353 }
354 
355 
356 void ophGen::RS_Diffraction(Point src, Complex<Real> *dst, Real lambda, Real distance, Real amplitude)
357 {
358  OphConfig *pConfig = &context_;
359  const int pnX = pConfig->pixel_number[_X];
360  const int pnY = pConfig->pixel_number[_Y];
361  const int pnXY = pnX * pnY;
362  const Real ppX = pConfig->pixel_pitch[_X];
363  const Real ppY = pConfig->pixel_pitch[_Y];
364  const Real ssX = pConfig->ss[_X] = pnX * ppX;
365  const Real ssY = pConfig->ss[_Y] = pnY * ppY;
366  const int offsetX = pConfig->offset[_X];
367  const int offsetY = pConfig->offset[_Y];
368 
369  const Real tx = lambda / (2 * ppX);
370  const Real ty = lambda / (2 * ppY);
371  const Real sqrtX = sqrt(1 - (tx * tx));
372  const Real sqrtY = sqrt(1 - (ty * ty));
373  const Real x = -ssX / 2;
374  const Real y = -ssY / 2;
375  const Real k = (2 * M_PI) / lambda;
376  Real z = src.pos[_Z] + distance;
377  Real zz = z * z;
378  Real ampZ = amplitude * z;
379 
380  Real _xbound[2] = {
381  src.pos[_X] + abs(tx / sqrtX * z),
382  src.pos[_X] - abs(tx / sqrtX * z)
383  };
384 
385  Real _ybound[2] = {
386  src.pos[_Y] + abs(ty / sqrtY * z),
387  src.pos[_Y] - abs(ty / sqrtY * z)
388  };
389 
390  Real Xbound[2] = {
391  floor((_xbound[_X] - x) / ppX) + 1,
392  floor((_xbound[_Y] - x) / ppX) + 1
393  };
394 
395  Real Ybound[2] = {
396  pnY - floor((_ybound[_Y] - y) / ppY),
397  pnY - floor((_ybound[_X] - y) / ppY)
398  };
399 
400  if (Xbound[_X] > pnX) Xbound[_X] = pnX;
401  if (Xbound[_Y] < 0) Xbound[_Y] = 0;
402  if (Ybound[_X] > pnY) Ybound[_X] = pnY;
403  if (Ybound[_Y] < 0) Ybound[_Y] = 0;
404 
405 
406  for (int yytr = Ybound[_Y]; yytr < Ybound[_X]; ++yytr)
407  {
408  int offset = yytr * pnX;
409  Real yyy = y + ((pnY - yytr + offsetY) * ppY);
410 
411  Real range_x[2] = {
412  src.pos[_X] + abs(tx / sqrtX * sqrt((yyy - src.pos[_Y]) * (yyy - src.pos[_Y]) + zz)),
413  src.pos[_X] - abs(tx / sqrtX * sqrt((yyy - src.pos[_Y]) * (yyy - src.pos[_Y]) + zz))
414  };
415 
416  for (int xxtr = Xbound[_Y]; xxtr < Xbound[_X]; ++xxtr)
417  {
418  Real xxx = x + ((xxtr - 1 + offsetX) * ppX);
419  Real r = sqrt((xxx - src.pos[_X]) * (xxx - src.pos[_X]) + (yyy - src.pos[_Y]) * (yyy - src.pos[_Y]) + zz);
420  Real range_y[2] = {
421  src.pos[_Y] + abs(ty / sqrtY * sqrt((xxx - src.pos[_X]) * (xxx - src.pos[_X]) + zz)),
422  src.pos[_Y] - abs(ty / sqrtY * sqrt((xxx - src.pos[_X]) * (xxx - src.pos[_X]) + zz))
423  };
424 
425  if (((xxx < range_x[_X]) && (xxx > range_x[_Y])) && ((yyy < range_y[_X]) && (yyy > range_y[_Y]))) {
426  Real kr = k * r;
427  Real operand = lambda * r * r;
428  Real res_real = (ampZ * sin(kr)) / operand;
429  Real res_imag = (-ampZ * cos(kr)) / operand;
430 #ifdef _OPENMP
431 #pragma omp atomic
432  dst[offset + xxtr][_RE] += res_real;
433 #endif
434 #ifdef _OPENMP
435 #pragma omp atomic
436  dst[offset + xxtr][_IM] += res_imag;
437 #endif
438  }
439  }
440  }
441 }
442 
443 void ophGen::Fresnel_Diffraction(Point src, Complex<Real> *dst, Real lambda, Real distance, Real amplitude)
444 {
445  OphConfig *pConfig = &context_;
446  const int pnX = pConfig->pixel_number[_X];
447  const int pnY = pConfig->pixel_number[_Y];
448  const int pnXY = pnX * pnY;
449  const Real ppX = pConfig->pixel_pitch[_X];
450  const Real ppY = pConfig->pixel_pitch[_Y];
451  const Real ssX = pConfig->ss[_X] = pnX * ppX;
452  const Real ssY = pConfig->ss[_Y] = pnY * ppY;
453  const int offsetX = pConfig->offset[_X];
454  const int offsetY = pConfig->offset[_Y];
455  const Real k = (2 * M_PI) / lambda;
456 
457  // for performance
458  Real x = -ssX / 2;
459  Real y = -ssY / 2;
460  Real z = src.pos[_Z] + distance;
461  Real zz = z * z;
462  Real operand = lambda * z;
463 
464  Real _xbound[2] = {
465  src.pos[_X] + abs(operand / (2 * ppX)),
466  src.pos[_X] - abs(operand / (2 * ppX))
467  };
468 
469  Real _ybound[2] = {
470  src.pos[_Y] + abs(operand / (2 * ppY)),
471  src.pos[_Y] - abs(operand / (2 * ppY))
472  };
473 
474  Real Xbound[2] = {
475  floor((_xbound[_X] - x) / ppX) + 1,
476  floor((_xbound[_Y] - x) / ppX) + 1
477  };
478 
479  Real Ybound[2] = {
480  pnY - floor((_ybound[_Y] - y) / ppY),
481  pnY - floor((_ybound[_X] - y) / ppY)
482  };
483 
484  if (Xbound[_X] > pnX) Xbound[_X] = pnX;
485  if (Xbound[_Y] < 0) Xbound[_Y] = 0;
486  if (Ybound[_X] > pnY) Ybound[_X] = pnY;
487  if (Ybound[_Y] < 0) Ybound[_Y] = 0;
488 
489  for (int yytr = Ybound[_Y]; yytr < Ybound[_X]; ++yytr)
490  {
491  Real yyy = (y + (pnY - yytr + offsetY) * ppY) - src.pos[_Y];
492  int offset = yytr * pnX;
493  for (int xxtr = Xbound[_Y]; xxtr < Xbound[_X]; ++xxtr)
494  {
495  Real xxx = (x + (xxtr - 1 + offsetX) * ppX) - src.pos[_X];
496  Real p = k * (xxx * xxx + yyy * yyy + 2 * zz) / (2 * z);
497 
498  Real res_real = amplitude * sin(p) / operand;
499  Real res_imag = amplitude * (-cos(p)) / operand;
500 
501 #ifdef _OPENMP
502 #pragma omp atomic
503 #endif
504  dst[offset + xxtr][_RE] += res_real;
505 #ifdef _OPENMP
506 #pragma omp atomic
507 #endif
508  dst[offset + xxtr][_IM] += res_imag;
509  }
510  }
511 }
512 
513 void ophGen::Fresnel_FFT(Complex<Real> *src, Complex<Real> *dst, Real lambda, Real waveRatio, Real distance)
514 {
515  OphConfig *pConfig = &context_;
516  const int pnX = pConfig->pixel_number[_X];
517  const int pnY = pConfig->pixel_number[_Y];
518  const int pnXY = pnX * pnY;
519  const Real ppX = pConfig->pixel_pitch[_X];
520  const Real ppY = pConfig->pixel_pitch[_Y];
521  const Real ssX = pConfig->ss[_X] = pnX * ppX;
522  const Real ssY = pConfig->ss[_Y] = pnY * ppY;
523  const Real ssX2 = ssX * 2;
524  const Real ssY2 = ssY * 2;
525  const Real k = (2 * M_PI) / lambda;
526 
527  int newSize = pnXY * 4;// *waveRatio;
528  Complex<Real>* in2x = new Complex<Real>[newSize];
529  memset(in2x, 0, sizeof(Complex<Real>) * newSize);
530 
531  uint idxIn = 0;
532  int half_pnX = pnX >> 1;
533  int half_pnY = pnY >> 1;
534  int pnX2 = pnX * 2;
535  int pnY2 = pnY * 2;
536 
537  for (int i = 0; i < pnY; i++) {
538  for (int j = 0; j < pnX; j++) {
539  in2x[(i + half_pnY) * pnX2 + (j + half_pnX)] = src[idxIn++];
540  }
541  }
542 
543  Complex<Real>* temp1 = new Complex<Real>[newSize];
544 
545  fft2({ pnX2, pnY2 }, in2x, OPH_FORWARD, OPH_ESTIMATE); // fft spatial domain
546  fft2(in2x, temp1, pnX2, pnY2, OPH_FORWARD, false); //
547 
548  Real* fx = new Real[newSize];
549  Real* fy = new Real[newSize];
550 
551  uint i = 0;
552 
553  for (int idxFy = -pnY; idxFy < pnY; idxFy++) {
554  for (int idxFx = -pnX; idxFx < pnX; idxFx++) {
555  fx[i] = idxFx / ssX2;
556  fy[i] = idxFy / ssY2;
557  i++;
558  }
559  }
560 
561  Complex<Real>* prop = new Complex<Real>[newSize];
562  memset(prop, 0, sizeof(Complex<Real>) * newSize);
563 
564  Real sqrtPart;
565 
566  Complex<Real>* temp2 = new Complex<Real>[newSize];
567  Real lambda_square = lambda * lambda;
568  Real tmp = 2 * M_PI * distance;
569 
570  for (int i = 0; i < newSize; i++) {
571  sqrtPart = sqrt(1 / lambda_square - fx[i] * fx[i] - fy[i] * fy[i]);
572  prop[i][_IM] = tmp;
573  prop[i][_IM] *= sqrtPart;
574  temp2[i] = temp1[i] * exp(prop[i]);
575  }
576 
577  Complex<Real>* temp3 = new Complex<Real>[newSize];
578  fft2({ pnX2, pnY2 }, temp2, OPH_BACKWARD, OPH_ESTIMATE);
579  fft2(temp2, temp3, pnX2, pnY2, OPH_BACKWARD, false);
580 
581  uint idxOut = 0;
582  for (int i = 0; i < pnY; i++) {
583  for (int j = 0; j < pnX; j++) {
584  dst[idxOut++] = temp3[(i + half_pnY) * pnX2 + (j + half_pnX)];
585  }
586  }
587 
588  delete[] in2x;
589  delete[] temp1;
590  delete[] fx;
591  delete[] fy;
592  delete[] prop;
593  delete[] temp2;
594  delete[] temp3;
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 Real ppX = context_.pixel_pitch[_X];
603  const Real ppY = context_.pixel_pitch[_Y];
604  const Real ssX = context_.ss[_X] = pnX * ppX;
605  const Real ssY = context_.ss[_Y] = pnY * ppY;
606 
607  Real dfx = 1 / ssX;
608  Real dfy = 1 / ssY;
609 
610  Real k = context_.k = (2 * M_PI / lambda);
611  Real kk = k * k;
612  Real kd = k * distance;
613  Real fx = -1 / (ppX * 2);
614  Real fy = 1 / (ppY * 2);
615 
616 #ifdef _OPENMP
617 #pragma omp parallel for firstprivate(pnX, dfx, dfy, lambda, kd, kk)
618 #endif
619  for (int i = 0; i < N; i++)
620  {
621  Real x = i % pnX;
622  Real y = i / pnX;
623 
624  Real fxx = fx + dfx * x;
625  Real fyy = fy - dfy - dfy * y;
626 
627  Real fxxx = lambda * fxx;
628  Real fyyy = lambda * fyy;
629 
630  Real sval = sqrt(1 - (fxxx * fxxx) - (fyyy * fyyy));
631  sval = sval * kd;
632  Complex<Real> kernel(0, sval);
633  kernel.exp();
634 
635  bool prop_mask = ((fxx * fxx + fyy * fyy) < kk) ? true : false;
636 
637  Complex<Real> u_frequency;
638  if (prop_mask) {
639  u_frequency = kernel * src[i];
640  dst[i][_RE] += u_frequency[_RE];
641  dst[i][_IM] += u_frequency[_IM];
642  }
643  }
644 }
645 
647 {
648  int N = size[_X] * size[_Y];
649  if (N <= 0) return;
650 
651  Complex<Real>* src1FT = new Complex<Real>[N];
652  Complex<Real>* src2FT = new Complex<Real>[N];
653  Complex<Real>* dstFT = new Complex<Real>[N];
654 
655  fft2(src1, src1FT, size[_X], size[_Y], OPH_FORWARD, (bool)OPH_ESTIMATE);
656  fft2(src2, src2FT, size[_X], size[_Y], OPH_FORWARD, (bool)OPH_ESTIMATE);
657 
658  for (int i = 0; i < N; i++)
659  dstFT[i] = src1FT[i] * src2FT[i];
660 
661  fft2(dstFT, dst, size[_X], size[_Y], OPH_BACKWARD, (bool)OPH_ESTIMATE);
662 
663  delete[] src1FT;
664  delete[] src2FT;
665  delete[] dstFT;
666 }
667 
669 {
670  const uint pnX = context_.pixel_number[_X];
671  const uint pnY = context_.pixel_number[_Y];
672  oph::normalize((Real *)m_lpEncoded[ch], m_lpNormalized[ch], pnX, pnY);
673 }
674 
676 {
677  const int pnX = context_.pixel_number[_X];
678  const int pnY = context_.pixel_number[_Y];
679  const uint nWave = context_.waveNum;
680  const long long int N = pnX * pnY;
681 
682  Real min = MAX_DOUBLE, max = MIN_DOUBLE, gap = 0;
683  for (uint ch = 0; ch < nWave; ch++)
684  {
685  Real minTmp = minOfArr(m_lpEncoded[ch], N);
686  Real maxTmp = maxOfArr(m_lpEncoded[ch], N);
687 
688  if (min > minTmp)
689  min = minTmp;
690  if (max < maxTmp)
691  max = maxTmp;
692  }
693 
694  gap = max - min;
695  for (uint ch = 0; ch < nWave; ch++)
696  {
697 #ifdef _OPENMP
698 #pragma omp parallel for firstprivate(min, gap, pnX)
699 #endif
700  for (int j = 0; j < pnY; j++) {
701  for (int i = 0; i < pnX; i++) {
702  int idx = j * pnX + i;
703  m_lpNormalized[ch][idx] = (((m_lpEncoded[ch][idx] - min) / gap) * 255 + 0.5);
704  }
705  }
706  }
707 }
708 
709 bool ophGen::save(const char* fname, uint8_t bitsperpixel, uchar* src, uint px, uint py)
710 {
711  bool bOK = false;
712 
713  if (fname == nullptr) return bOK;
714 
715  uchar* source = src;
716  bool bAlloc = false;
717  const uint nChannel = context_.waveNum;
718 
719  ivec2 p(px, py);
720  if (px == 0 && py == 0)
722 
723 
724  std::string file = fname;
725  std::replace(file.begin(), file.end(), '\\', '/');
726 
727  // split path
728  std::vector<std::string> components;
729  std::stringstream ss(file);
730  std::string item;
731  char token = '/';
732 
733  while (std::getline(ss, item, token)) {
734  components.push_back(item);
735  }
736 
737  std::string dir;
738 
739  for (size_t i = 0; i < components.size() - 1; i++)
740  {
741  dir += components[i];
742  dir += "/";
743  }
744 
745  std::string filename = components[components.size() - 1];
746 
747  // find extension
748  bool hasExt;
749  size_t ext_pos = file.rfind(".");
750  hasExt = (ext_pos == string::npos) ? false : true;
751 
752  if (!hasExt)
753  filename.append(".bmp");
754 
755  std::string fullpath = dir + filename;
756 
757  if (src == nullptr) {
758  if (nChannel == 1) {
759  source = m_lpNormalized[0];
760  saveAsImg(fullpath.c_str(), bitsperpixel, source, p[_X], p[_Y]);
761  }
762  else if (nChannel == 3) {
763  if (imgCfg.merge) {
764  uint nSize = (((p[_X] * bitsperpixel >> 3) + 3) & ~3) * p[_Y];
765  source = new uchar[nSize];
766  bAlloc = true;
767  for (uint i = 0; i < nChannel; i++) {
768  mergeColor(i, p[_X], p[_Y], m_lpNormalized[i], source);
769  }
770 
771  saveAsImg(fullpath.c_str(), bitsperpixel, source, p[_X], p[_Y]);
772  if (bAlloc) delete[] source;
773  }
774  else {
775  for (uint i = 0; i < nChannel; i++) {
776  char path[FILENAME_MAX] = { 0, };
777  sprintf(path, "%s%d_%s", dir.c_str(), i, filename.c_str());
778  source = m_lpNormalized[i];
779  saveAsImg(path, bitsperpixel / nChannel, source, p[_X], p[_Y]);
780  }
781  }
782  }
783  else return false;
784  }
785  else
786  saveAsImg(fullpath.c_str(), bitsperpixel, source, p[_X], p[_Y]);
787 
788  return true;
789 }
790 
791 void* ophGen::load(const char * fname)
792 {
793  if (checkExtension(fname, ".bmp")) {
794  return Openholo::loadAsImg(fname);
795  }
796  else { // when extension is not .bmp
797  return nullptr;
798  }
799 
800  return nullptr;
801 }
802 
803 bool ophGen::loadAsOhc(const char * fname)
804 {
805  if (!Openholo::loadAsOhc(fname)) return false;
806 
807  const uint nChannel = context_.waveNum;
808  const long long int pnXY = context_.pixel_number[_X] * context_.pixel_number[_Y];
809 
810  m_lpEncoded = new Real*[nChannel];
811  m_lpNormalized = new uchar*[nChannel];
812  for (uint ch = 0; ch < nChannel; ch++) {
813  m_lpEncoded[ch] = new Real[pnXY];
814  memset(m_lpEncoded[ch], 0, sizeof(Real) * pnXY);
815  m_lpNormalized[ch] = new uchar[pnXY];
816  memset(m_lpNormalized[ch], 0, sizeof(uchar) * pnXY);
817  }
818  return true;
819 }
820 
822 {
824  int N2 = m_vecEncodeSize[_X] * m_vecEncodeSize[_Y];
825 
826  for (uint ch = 0; ch < context_.waveNum; ch++) {
827  if (complex_H[ch])
828  memset(complex_H[ch], 0., sizeof(Complex<Real>) * N);
829  if (m_lpEncoded[ch])
830  memset(m_lpEncoded[ch], 0., sizeof(Real) * N2);
831  if (m_lpNormalized[ch])
832  memset(m_lpNormalized[ch], 0, sizeof(uchar) * N2);
833  }
834 }
835 
836 void ophGen::encoding(unsigned int ENCODE_FLAG)
837 {
838  auto begin = CUR_TIME;
839 
840  // func pointer
841  void (ophGen::*encodeFunc) (Complex<Real>*, Real*, const int) = nullptr;
842 
843  Complex<Real> *holo = nullptr;
844  Real *encoded = nullptr;
845  const long long int pnXY = context_.pixel_number[_X] * context_.pixel_number[_Y];
847 
848  switch (ENCODE_FLAG)
849  {
850  case ENCODE_PHASE: encodeFunc = &ophGen::Phase; LOG("ENCODE_PHASE\n"); break;
851  case ENCODE_AMPLITUDE: encodeFunc = &ophGen::Amplitude; LOG("ENCODE_AMPLITUDE\n"); break;
852  case ENCODE_REAL: encodeFunc = &ophGen::RealPart; LOG("ENCODE_REAL\n"); break;
853  case ENCODE_IMAGINARY: encodeFunc = &ophGen::ImaginaryPart; LOG("ENCODE_IMAGINARY\n"); break;
854  case ENCODE_SIMPLENI: encodeFunc = &ophGen::SimpleNI; LOG("ENCODE_SIMPLENI\n"); break;
855  case ENCODE_BURCKHARDT: encodeFunc = &ophGen::Burckhardt; LOG("ENCODE_BURCKHARDT\n"); break;
856  case ENCODE_TWOPHASE: encodeFunc = &ophGen::TwoPhase; LOG("ENCODE_TWOPHASE\n"); break;
857  default:
858  LOG("<FAILED> WRONG PARAMETERS.\n");
859  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
860  return;
861  }
862 
863  for (uint ch = 0; ch < context_.waveNum; ch++) {
864  holo = complex_H[ch];
865  encoded = m_lpEncoded[ch];
866  (this->*encodeFunc)(holo, encoded, m_vecEncodeSize[_X] * m_vecEncodeSize[_Y]);
867  }
868  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
869 }
870 
871 //template <typename T>
872 //void ophGen::encoding(unsigned int ENCODE_FLAG, Complex<T>* holo, T* encoded)
873 void ophGen::encoding(unsigned int ENCODE_FLAG, Complex<Real>* holo, Real* encoded)
874 {
875  auto begin = CUR_TIME;
876  // func pointer
877  void (ophGen::*encodeFunc) (Complex<Real>*, Real*, const int) = nullptr;
878 
879  const long long int pnXY = context_.pixel_number[_X] * context_.pixel_number[_Y];
881 
882  switch (ENCODE_FLAG)
883  {
884  case ENCODE_PHASE: encodeFunc = &ophGen::Phase; LOG("ENCODE_PHASE\n"); break;
885  case ENCODE_AMPLITUDE: encodeFunc = &ophGen::Amplitude; LOG("ENCODE_AMPLITUDE\n"); break;
886  case ENCODE_REAL: encodeFunc = &ophGen::RealPart; LOG("ENCODE_REAL\n"); break;
887  case ENCODE_IMAGINARY: encodeFunc = &ophGen::ImaginaryPart; LOG("ENCODE_IMAGINARY\n"); break;
888  case ENCODE_SIMPLENI: encodeFunc = &ophGen::SimpleNI; LOG("ENCODE_SIMPLENI\n"); break;
889  case ENCODE_BURCKHARDT: encodeFunc = &ophGen::Burckhardt; LOG("ENCODE_BURCKHARDT\n"); break;
890  case ENCODE_TWOPHASE: encodeFunc = &ophGen::TwoPhase; LOG("ENCODE_TWOPHASE\n"); break;
891  default: LOG("<FAILED> WRONG PARAMETERS.\n"); return;
892  }
893 
894  if (holo == nullptr) holo = complex_H[0];
895  if (encoded == nullptr) encoded = m_lpEncoded[0];
896 
897  (this->*encodeFunc)(holo, encoded, m_vecEncodeSize[_X] * m_vecEncodeSize[_Y]);
898 
899  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
900 }
901 
902 void ophGen::encoding(unsigned int ENCODE_FLAG, unsigned int passband, Complex<Real>* holo, Real* encoded)
903 {
904  holo == nullptr ? holo = *complex_H : holo;
905  encoded == nullptr ? encoded = *m_lpEncoded : encoded;
906 
908  const long long int pnXY = context_.pixel_number[_X] * context_.pixel_number[_Y];
909  const uint nChannel = context_.waveNum;
910 
911  for (uint ch = 0; ch < nChannel; ch++) {
912  /* initialize */
913  long long int m_vecEncodeSize = pnXY;
914  if (m_lpEncoded[ch] != nullptr) delete[] m_lpEncoded[ch];
915  m_lpEncoded[ch] = new Real[m_vecEncodeSize];
916  memset(m_lpEncoded[ch], 0, sizeof(Real) * m_vecEncodeSize);
917 
918  if (m_lpNormalized[ch] != nullptr) delete[] m_lpNormalized[ch];
920  memset(m_lpNormalized[ch], 0, sizeof(uchar) * m_vecEncodeSize);
921 
922  switch (ENCODE_FLAG)
923  {
924  case ENCODE_SSB:
925  LOG("ENCODE_SSB");
926  singleSideBand((holo), m_lpEncoded[ch], context_.pixel_number, passband);
927  break;
928  case ENCODE_OFFSSB:
929  {
930  LOG("ENCODE_OFFSSB");
931  Complex<Real> *tmp = new Complex<Real>[pnXY];
932  memcpy(tmp, holo, sizeof(Complex<Real>) * pnXY);
933  freqShift(tmp, tmp, context_.pixel_number, 0, 100);
934  singleSideBand(tmp, m_lpEncoded[ch], context_.pixel_number, passband);
935  delete[] tmp;
936  break;
937  }
938  default:
939  LOG("<FAILED> WRONG PARAMETERS.\n");
940  return;
941  }
942  }
943 }
944 
945 void ophGen::encoding(unsigned int BIN_ENCODE_FLAG, unsigned int ENCODE_FLAG, Real threshold, Complex<Real>* holo, Real* encoded)
946 {
947  auto begin = CUR_TIME;
948  const uint nChannel = context_.waveNum;
949  const long long int pnXY = context_.pixel_number[_X] * context_.pixel_number[_Y];
950 
951  switch (BIN_ENCODE_FLAG) {
952  case ENCODE_SIMPLEBINARY:
953  LOG("ENCODE_SIMPLEBINARY\n");
954  if (holo == nullptr || encoded == nullptr)
955  for (uint ch = 0; ch < nChannel; ch++) {
956  binarization(complex_H[ch], m_lpEncoded[ch], pnXY, ENCODE_FLAG, threshold);
957  }
958  else
959  binarization(holo, encoded, pnXY, ENCODE_FLAG, threshold);
960  break;
961  case ENCODE_EDBINARY:
962  LOG("ENCODE_EDBINARY\n");
963  if (ENCODE_FLAG != ENCODE_REAL) {
964  LOG("<FAILED> WRONG PARAMETERS : %d\n", ENCODE_FLAG);
965  return;
966  }
967  if (holo == nullptr || encoded == nullptr)
968  for (uint ch = 0; ch < nChannel; ch++) {
970  }
971  else
972  binaryErrorDiffusion(holo, encoded, pnXY, FLOYD_STEINBERG, threshold);
973  break;
974  default:
975  LOG("<FAILED> WRONG PARAMETERS.\n");
976  return;
977  }
978 
979  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
980 }
981 
983 {
984  const long long int pnXY = context_.pixel_number[_X] * context_.pixel_number[_Y];
985  const uint nChannel = context_.waveNum;
986 
988  else if (ENCODE_METHOD == ENCODE_TWOPHASE) m_vecEncodeSize[_X] *= 2;
989 
990  for (uint ch = 0; ch < nChannel; ch++) {
991  /* initialize */
992  if (m_lpEncoded[ch] != nullptr) delete[] m_lpEncoded[ch];
994  memset(m_lpEncoded[ch], 0, sizeof(Real) * m_vecEncodeSize[_X] * m_vecEncodeSize[_Y]);
995 
996  if (m_lpNormalized[ch] != nullptr) delete[] m_lpNormalized[ch];
998  memset(m_lpNormalized[ch], 0, sizeof(uchar) * m_vecEncodeSize[_X] * m_vecEncodeSize[_Y]);
999 
1000 
1001  switch (ENCODE_METHOD)
1002  {
1003  case ENCODE_SIMPLENI:
1004  LOG("ENCODE_SIMPLENI\n");
1005  SimpleNI(complex_H[ch], m_lpEncoded[ch], pnXY);
1006  break;
1007  case ENCODE_REAL:
1008  LOG("ENCODE_REAL\n");
1009  realPart<Real>(complex_H[ch], m_lpEncoded[ch], pnXY);
1010  break;
1011  case ENCODE_BURCKHARDT:
1012  LOG("ENCODE_BURCKHARDT\n");
1013  Burckhardt(complex_H[ch], m_lpEncoded[ch], pnXY);
1014  break;
1015  case ENCODE_TWOPHASE:
1016  LOG("ENCODE_TWOPHASE\n");
1017  TwoPhase(complex_H[ch], m_lpEncoded[ch], pnXY);
1018  break;
1019  case ENCODE_PHASE:
1020  LOG("ENCODE_PHASE\n");
1021  Phase(complex_H[ch], m_lpEncoded[ch], pnXY);
1022  break;
1023  case ENCODE_AMPLITUDE:
1024  LOG("ENCODE_AMPLITUDE\n");
1025  getAmplitude(complex_H[ch], m_lpEncoded[ch], pnXY);
1026  break;
1027  case ENCODE_SSB:
1028  LOG("ENCODE_SSB\n");
1030  break;
1031  case ENCODE_OFFSSB:
1032  LOG("ENCODE_OFFSSB\n");
1033  freqShift(complex_H[ch], complex_H[ch], context_.pixel_number, 0, 100);
1035  break;
1036  default:
1037  LOG("<FAILED> WRONG PARAMETERS.\n");
1038  return;
1039  }
1040  }
1041 }
1042 
1043 void ophGen::singleSideBand(Complex<Real>* src, Real* dst, const ivec2 holosize, int SSB_PASSBAND)
1044 {
1045  const int nX = holosize[_X];
1046  const int nY = holosize[_Y];
1047  const int half_nX = nX >> 1;
1048  const int half_nY = nY >> 1;
1049 
1050  const long long int N = nX * nY;
1051  const long long int half_N = N >> 1;
1052 
1053  Complex<Real>* AS = new Complex<Real>[N];
1054  //fft2(holosize, holo, OPH_FORWARD, OPH_ESTIMATE);
1055  fft2(src, AS, nX, nY, OPH_FORWARD, false);
1056  //fftExecute(temp);
1057 
1058 
1059  switch (SSB_PASSBAND)
1060  {
1061  case SSB_LEFT:
1062  for (int i = 0; i < nY; i++)
1063  {
1064  int k = i * nX;
1065  for (int j = half_nX; j < nX; j++)
1066  {
1067  AS[k + j] = 0;
1068  }
1069  }
1070  break;
1071  case SSB_RIGHT:
1072  for (int i = 0; i < nY; i++)
1073  {
1074  int k = i * nX;
1075  for (int j = 0; j < half_nX; j++)
1076  {
1077  AS[k + j] = 0;
1078  }
1079  }
1080  break;
1081  case SSB_TOP:
1082  memset(&AS[half_N], 0, sizeof(Complex<Real>) * half_N);
1083  break;
1084 
1085  case SSB_BOTTOM:
1086  memset(&AS[0], 0, sizeof(Complex<Real>) * half_N);
1087  break;
1088  }
1089 
1090  Complex<Real>* filtered = new Complex<Real>[N];
1091  //fft2(holosize, AS, OPH_BACKWARD, OPH_ESTIMATE);
1092  fft2(AS, filtered, nX, nY, OPH_BACKWARD, false);
1093 
1094  //fftExecute(filtered);
1095 
1096 
1097  Real* realFiltered = new Real[N];
1098  oph::realPart<Real>(filtered, realFiltered, N);
1099 
1100  oph::normalize(realFiltered, dst, N);
1101 
1102  delete[] AS;
1103  delete[] filtered;
1104  delete[] realFiltered;
1105 }
1106 
1107 void ophGen::freqShift(Complex<Real>* src, Complex<Real>* dst, const ivec2 holosize, int shift_x, int shift_y)
1108 {
1109  int N = holosize[_X] * holosize[_Y];
1110 
1111  Complex<Real>* AS = new Complex<Real>[N];
1112  //fft2(holosize, src, OPH_FORWARD, OPH_ESTIMATE);
1113  fft2(src, AS, holosize[_X], holosize[_Y], OPH_FORWARD);
1114  //fftExecute(AS);
1115 
1116  Complex<Real>* shifted = new Complex<Real>[N];
1117  circShift<Complex<Real>>(AS, shifted, shift_x, shift_y, holosize.v[_X], holosize.v[_Y]);
1118 
1119  //fft2(holosize, shifted, OPH_BACKWARD, OPH_ESTIMATE);
1120  fft2(shifted, dst, holosize[_X], holosize[_Y], OPH_BACKWARD);
1121  //fftExecute(dst);
1122 
1123  delete[] AS;
1124  delete[] shifted;
1125 }
1126 
1127 
1128 bool ophGen::saveRefImages(char* fnameW, char* fnameWC, char* fnameAS, char* fnameSSB, char* fnameHP, char* fnameFreq, char* fnameReal, char* fnameBin, char* fnameReconBin, char* fnameReconErr, char* fnameReconNo)
1129 {
1130  ivec2 holosize = context_.pixel_number;
1131  int nx = holosize[_X], ny = holosize[_Y];
1132  int ss = nx*ny;
1133 
1134  Real* temp1 = new Real[ss];
1135  uchar* temp2 = new uchar[ss];
1136 
1137  oph::normalize(weight, temp2, nx, ny);
1138  saveAsImg(fnameW, 8, temp2, nx, ny);
1139  cout << "W saved" << endl;
1140 
1141  oph::absCplxArr<Real>(weightC, temp1, ss);
1142  oph::normalize(temp1, temp2, nx, ny);
1143  saveAsImg(fnameWC, 8, temp2, nx, ny);
1144  cout << "WC saved" << endl;
1145 
1146  oph::absCplxArr<Real>(AS, temp1, ss);
1147  oph::normalize(temp1, temp2, nx, ny);
1148  saveAsImg(fnameAS, 8, temp2, nx, ny);
1149  cout << "AS saved" << endl;
1150 
1151  oph::normalize(maskSSB, temp2, nx, ny);
1152  saveAsImg(fnameSSB, 8, temp2, nx, ny);
1153  cout << "SSB saved" << endl;
1154 
1155  oph::normalize(maskHP, temp2, nx, ny);
1156  saveAsImg(fnameHP, 8, temp2, nx, ny);
1157  cout << "HP saved" << endl;
1158 
1159  oph::absCplxArr<Real>(freqW, temp1, ss);
1160  oph::normalize(temp1, temp2, nx, ny);
1161  saveAsImg(fnameFreq, 8, temp2, nx, ny);
1162  cout << "Freq saved" << endl;
1163 
1164  oph::normalize(realEnc, temp2, nx, ny);
1165  saveAsImg(fnameReal, 8, temp2, nx, ny);
1166  cout << "Real saved" << endl;
1167 
1168  oph::normalize(binary, temp2, nx, ny);
1169  saveAsImg(fnameBin, 8, temp2, nx, ny);
1170  cout << "Bin saved" << endl;
1171 
1172 
1173  Complex<Real>* temp = new Complex<Real>[ss];
1174  for (int i = 0; i < ss; i++) {
1175  temp[i][_RE] = binary[i];
1176  temp[i][_IM] = 0;
1177  }
1178  fft2(ivec2(nx, ny), temp, OPH_FORWARD);
1179  fft2(temp, temp, nx, ny, OPH_FORWARD);
1180  for (int i = 0; i < ss; i++) {
1181  temp[i][_RE] *= maskSSB[i];
1182  temp[i][_IM] *= maskSSB[i];
1183  }
1184  fft2(ivec2(nx, ny), temp, OPH_BACKWARD);
1185  fft2(temp, temp, nx, ny, OPH_BACKWARD);
1186 
1187  Complex<Real>* reconBin = new Complex<Real>[ss];
1188  memset(reconBin, 0, sizeof(Complex<Real>) * ss);
1189  fresnelPropagation(temp, reconBin, 0.001, 0);
1190 
1191  oph::absCplxArr<Real>(reconBin, temp1, ss);
1192  for (int i = 0; i < ss; i++) {
1193  temp1[i] = temp1[i] * temp1[i];
1194  }
1195  oph::normalize(temp1, temp2, nx, ny);
1196  saveAsImg(fnameReconBin, 8, temp2, nx, ny);
1197  cout << "recon bin saved" << endl;
1198 
1199 
1200  temp = new Complex<Real>[ss];
1201  for (int i = 0; i < ss; i++) {
1202  temp[i][_RE] = m_lpEncoded[0][i];
1203  temp[i][_IM] = 0;
1204  }
1205  fft2(ivec2(nx, ny), temp, OPH_FORWARD);
1206  fft2(temp, temp, holosize[_X], holosize[_Y], OPH_FORWARD);
1207  for (int i = 0; i < ss; i++) {
1208  temp[i][_RE] *= maskHP[i];
1209  temp[i][_IM] *= maskHP[i];
1210  }
1211  fft2(ivec2(nx, ny), temp, OPH_BACKWARD);
1212  fft2(temp, temp, nx, ny, OPH_BACKWARD);
1213 
1214  reconBin = new Complex<Real>[ss];
1215  fresnelPropagation(temp, reconBin, 0.001, 0);
1216 
1217  oph::absCplxArr<Real>(reconBin, temp1, ss);
1218  for (int i = 0; i < ss; i++) {
1219  temp1[i] = temp1[i] * temp1[i];
1220  }
1221  oph::normalize(temp1, temp2, nx, ny);
1222  saveAsImg(fnameReconErr, 8, temp2, nx, ny);
1223  cout << "recon error saved" << endl;
1224 
1225 
1226 
1227 
1228  temp = new Complex<Real>[ss];
1229  for (int i = 0; i < ss; i++) {
1230  temp[i][_RE] = normalized[i][_RE];
1231  temp[i][_IM] = normalized[i][_IM];
1232  }
1233  fft2(ivec2(nx, ny), temp, OPH_FORWARD);
1234  fft2(temp, temp, holosize[_X], holosize[_Y], OPH_FORWARD);
1235  for (int i = 0; i < ss; i++) {
1236  temp[i][_RE] *= maskSSB[i];
1237  temp[i][_IM] *= maskSSB[i];
1238  }
1239  fft2(ivec2(nx, ny), temp, OPH_BACKWARD);
1240  fft2(temp, temp, nx, ny, OPH_BACKWARD);
1241 
1242  reconBin = new Complex<Real>[ss];
1243  fresnelPropagation(temp, reconBin, 0.001, 0);
1244 
1245  oph::absCplxArr<Real>(reconBin, temp1, ss);
1246  for (int i = 0; i < ss; i++) {
1247  temp1[i] = temp1[i] * temp1[i];
1248  }
1249  oph::normalize(temp1, temp2, nx, ny);
1250  saveAsImg(fnameReconNo, 8, temp2, nx, ny);
1251 
1252 
1253  return true;
1254 }
1255 
1256 bool ophGen::binaryErrorDiffusion(Complex<Real>* holo, Real* encoded, const ivec2 holosize, const int type, Real threshold)
1257 {
1258 
1259  //cout << "\nin?" << endl;
1260  int ss = holosize[_X] * holosize[_Y];
1261  weight = new Real[ss];
1262  //cout << "?" << endl;
1263  weightC = new Complex<Real>[ss];
1264  //cout << "??" << endl;
1265  ivec2 Nw;
1266  memsetArr<Real>(weight, 0.0, 0, ss - 1);
1267  //cout << "???" << endl;
1268  if (!getWeightED(holosize, type, &Nw))
1269  return false;
1270  //cout << "1?" << endl;
1271  AS = new Complex<Real>[ss];
1272  fft2(ivec2(holosize[_X], holosize[_Y]), holo, OPH_FORWARD);
1273  fft2(holo, AS, holosize[_X], holosize[_Y], OPH_FORWARD);
1274  //cout << "2?" << endl;
1275  // SSB mask generation
1276  maskSSB = new Real[ss];
1277  for (int i = 0; i < ss; i++) {
1278  if (((Real)i / (Real)holosize[_X]) < ((Real)holosize[_Y] / 2.0))
1279  maskSSB[i] = 1;
1280  else
1281  maskSSB[i] = 0;
1282  AS[i] *= maskSSB[i];
1283  }
1284 
1285  //cout << "3?" << endl;
1286  Complex<Real>* filtered = new Complex<Real>[ss];
1287  fft2(ivec2(holosize[_X], holosize[_Y]), AS, OPH_BACKWARD);
1288  fft2(AS, filtered, holosize[_X], holosize[_Y], OPH_BACKWARD);
1289  //cout << "4?" << endl;
1290  normalized = new Complex<Real>[ss];
1291  oph::normalize(filtered, normalized, ss);
1292  LOG("normalize finishied..\n");
1293  if (encoded == nullptr)
1294  encoded = new Real[ss];
1295 
1296  shiftW(holosize);
1297  LOG("shiftW finishied..\n");
1298 
1299  // HP mask generation
1300  maskHP = new Real[ss];
1301  Real absFW;
1302  for (int i = 0; i < ss; i++) {
1303  oph::absCplx<Real>(freqW[i], absFW);
1304  if (((Real)i / (Real)holosize[_X]) < ((Real)holosize[_Y] / 2.0) && absFW < 0.6)
1305  maskHP[i] = 1;
1306  else
1307  maskHP[i] = 0;
1308  }
1309  //cout << "5?" << endl;
1310 
1311  // For checking
1312  binary = new Real[ss];
1313  realEnc = new Real[ss];
1314  for (int i = 0; i < ss; i++) {
1315  realEnc[i] = normalized[i][_RE];
1316  if (normalized[i][_RE] > threshold)
1317  binary[i] = 1;
1318  else
1319  binary[i] = 0;
1320  }
1321 
1322  Complex<Real>* toBeBin = new Complex<Real>[ss];
1323  for (int i = 0; i < ss; i++) {
1324  toBeBin[i] = normalized[i];
1325  }
1326  int ii, iii, jjj;
1327  int cx = (holosize[_X] + 1) / 2, cy = (holosize[_Y] + 1) / 2;
1328  Real error;
1329  for (int iy = 0; iy < holosize[_Y] - Nw[_Y]; iy++) {
1330  for (int ix = Nw[_X]; ix < holosize[_X] - Nw[_X]; ix++) {
1331 
1332  ii = ix + iy*holosize[_X];
1333  if (ix >= Nw[_X] && ix < (holosize[_X] - Nw[_X]) && iy < (holosize[_Y] - Nw[_Y])) {
1334 
1335  if (toBeBin[ii][_RE] > threshold)
1336  encoded[ii] = 1;
1337  else
1338  encoded[ii] = 0;
1339 
1340  error = toBeBin[ii][_RE] - encoded[ii];
1341 
1342  for (int iwy = 0; iwy < Nw[_Y] + 1; iwy++) {
1343  for (int iwx = -Nw[_X]; iwx < Nw[_X] + 1; iwx++) {
1344  iii = (ix + iwx) + (iy + iwy)*holosize[_X];
1345  jjj = (cx + iwx) + (cy + iwy)*holosize[_X];
1346 
1347  toBeBin[iii] += weightC[jjj] * error;
1348  }
1349  }
1350  }
1351  else {
1352  encoded[ii] = 0;
1353  }
1354  }
1355  }
1356  LOG("binary finishied..\n");
1357 
1358  return true;
1359 }
1360 
1361 
1362 bool ophGen::getWeightED(const ivec2 holosize, const int type, ivec2* pNw)
1363 {
1364 
1365  int cx = (holosize[_X] + 1) / 2;
1366  int cy = (holosize[_Y] + 1) / 2;
1367 
1368  ivec2 Nw;
1369 
1370  switch (type) {
1371  case FLOYD_STEINBERG:
1372  LOG("ERROR DIFFUSION : FLOYD_STEINBERG\n");
1373  weight[(cx + 1) + cy*holosize[_X]] = 7.0 / 16.0;
1374  weight[(cx - 1) + (cy + 1)*holosize[_X]] = 3.0 / 16.0;
1375  weight[(cx)+(cy + 1)*holosize[_X]] = 5.0 / 16.0;
1376  weight[(cx + 1) + (cy + 1)*holosize[_X]] = 1.0 / 16.0;
1377  Nw[_X] = 1; Nw[_Y] = 1;
1378  break;
1379  case SINGLE_RIGHT:
1380  LOG("ERROR DIFFUSION : SINGLE_RIGHT\n");
1381  weight[(cx + 1) + cy*holosize[_X]] = 1.0;
1382  Nw[_X] = 1; Nw[_Y] = 0;
1383  break;
1384  case SINGLE_DOWN:
1385  LOG("ERROR DIFFUSION : SINGLE_DOWN\n");
1386  weight[cx + (cy + 1)*holosize[_X]] = 1.0;
1387  Nw[_X] = 0; Nw[_Y] = 1;
1388  break;
1389  default:
1390  LOG("<FAILED> WRONG PARAMETERS.\n");
1391  return false;
1392  }
1393 
1394  *pNw = Nw;
1395  return true;
1396 
1397 }
1398 
1399 bool ophGen::shiftW(ivec2 holosize)
1400 {
1401  int ss = holosize[_X] * holosize[_Y];
1402 
1403  Complex<Real> term(0, 0);
1404  Complex<Real> temp(0, 0);
1405  int x, y;
1406  for (int i = 0; i < ss; i++) {
1407 
1408  x = i % holosize[_X] - holosize[_X] / 2; y = i / holosize[_X] - holosize[_Y];
1409  term[_IM] = 2.0 * M_PI*((1.0 / 4.0)*(Real)x + (0.0)*(Real)y);
1410  temp[_RE] = weight[i];
1411  weightC[i] = temp *exp(term);
1412  }
1413 
1414  freqW = new Complex<Real>[ss];
1415 
1416  fft2(ivec2(holosize[_X], holosize[_Y]), weightC, OPH_FORWARD);
1417  fft2(weightC, freqW, holosize[_X], holosize[_Y], OPH_FORWARD);
1418  for (int i = 0; i < ss; i++) {
1419  freqW[i][_RE] -= 1.0;
1420  }
1421  return true;
1422 
1423 }
1424 
1425 void ophGen::binarization(Complex<Real>* src, Real* dst, const int size, int ENCODE_FLAG, Real threshold)
1426 {
1427  oph::normalize(src, src, size);
1429 
1430 #ifdef _OPENMP
1431 #pragma omp parallel for firstprivate(threshold)
1432 #endif
1433  for (int i = 0; i < size; i++) {
1434  if (src[i][_RE] > threshold)
1435  dst[i] = 1;
1436  else
1437  dst[i] = 0;
1438  }
1439 }
1440 
1442 {
1443  const int pnX = context.pixel_number[_X];
1444  const int pnY = context.pixel_number[_Y];
1445  const long long int pnXY = pnX * pnY;
1446 
1447  Complex<Real>* in2x = new Complex<Real>[pnXY * 4];
1448  Complex<Real> zero(0, 0);
1449  memset(in2x, 0, sizeof(Complex<Real>) * pnXY * 4);
1450 
1451  uint idxIn = 0;
1452  int beginY = pnY >> 1;
1453  int beginX = pnX >> 1;
1454  int endY = pnY + beginY;
1455  int endX = pnX + beginX;
1456 
1457  for (int idxnY = beginY; idxnY < endY; idxnY++) {
1458  for (int idxnX = beginX; idxnX < endX; idxnX++) {
1459  in2x[idxnY * pnX * 2 + idxnX] = in[idxIn++];
1460  }
1461  }
1462 
1463 
1464  Complex<Real>* temp1 = new Complex<Real>[pnXY * 4];
1465 
1466  fft2({ pnX * 2, pnY * 2 }, in2x, OPH_FORWARD, OPH_ESTIMATE);
1467  fft2(in2x, temp1, pnX * 2, pnY * 2, OPH_FORWARD);
1468  //fftExecute(temp1);
1469  Real* fx = new Real[pnXY * 4];
1470  Real* fy = new Real[pnXY * 4];
1471 
1472  uint i = 0;
1473  for (int idxFy = -pnY; idxFy < pnY; idxFy++) {
1474  for (int idxFx = -pnX; idxFx < pnX; idxFx++) {
1475  fx[i] = idxFx / (2 * pnX * context.pixel_pitch[_X]);
1476  fy[i] = idxFy / (2 * pnY * context.pixel_pitch[_Y]);
1477  i++;
1478  }
1479  }
1480 
1481  Complex<Real>* prop = new Complex<Real>[pnXY * 4];
1482  memsetArr<Complex<Real>>(prop, zero, 0, pnXY * 4 - 1);
1483 
1484  Real sqrtPart;
1485 
1486  Complex<Real>* temp2 = new Complex<Real>[pnXY * 4];
1487 
1488  for (int i = 0; i < pnXY * 4; i++) {
1489  sqrtPart = sqrt(1 / (context.wave_length[0] * context.wave_length[0]) - fx[i] * fx[i] - fy[i] * fy[i]);
1490  prop[i][_IM] = 2 * M_PI * distance;
1491  prop[i][_IM] *= sqrtPart;
1492  temp2[i] = temp1[i] * exp(prop[i]);
1493  }
1494 
1495  Complex<Real>* temp3 = new Complex<Real>[pnXY * 4];
1496  fft2({ pnX * 2, pnY * 2 }, temp2, OPH_BACKWARD, OPH_ESTIMATE);
1497  fft2(temp2, temp3, pnX * 2, pnY * 2, OPH_BACKWARD);
1498  //fftExecute(temp3);
1499 
1500  uint idxOut = 0;
1501 
1502  for (int idxNy = pnY / 2; idxNy < pnY + (pnY / 2); idxNy++) {
1503  for (int idxNx = pnX / 2; idxNx < pnX + (pnX / 2); idxNx++) {
1504  out[idxOut] = temp3[idxNy * pnX * 2 + idxNx];
1505  idxOut++;
1506  }
1507  }
1508 
1509  delete[] in2x;
1510  delete[] temp1;
1511  delete[] fx;
1512  delete[] fy;
1513  delete[] prop;
1514  delete[] temp2;
1515  delete[] temp3;
1516 }
1517 
1519 {
1520  const int pnX = context_.pixel_number[_X];
1521  const int pnY = context_.pixel_number[_Y];
1522  const Real ppX = context_.pixel_pitch[_X];
1523  const Real ppY = context_.pixel_pitch[_Y];
1524  const int pnXY = pnX * pnY;
1525  const Real lambda = context_.wave_length[channel];
1526  const Real ssX = pnX * ppX * 2;
1527  const Real ssY = pnY * ppY * 2;
1528  const Real z = 2 * M_PI * distance;
1529  const Real v = 1 / (lambda * lambda);
1530  const int hpnX = pnX / 2;
1531  const int hpnY = pnY / 2;
1532  const int pnX2 = pnX * 2;
1533  const int pnY2 = pnY * 2;
1534 
1535  Complex<Real>* temp = new Complex<Real>[pnXY * 4];
1536  memset(temp, 0, sizeof(Complex<Real>) * pnXY * 4);
1537 
1538 #ifdef _OPENMP
1539 #pragma omp parallel for firstprivate(pnX, pnX2, hpnX, hpnY)
1540 #endif
1541  for (int i = 0; i < pnY; i++)
1542  {
1543  int src = pnX * i;
1544  int dst = pnX2 * (i + hpnY) + hpnX;
1545  memcpy(&temp[dst], &in[src], sizeof(Complex<Real>) * pnX);
1546  }
1547 
1548  fft2(temp, temp, pnX2, pnY2, OPH_FORWARD, false);
1549 
1550 #ifdef _OPENMP
1551 #pragma omp parallel for firstprivate(ssX, ssY, z, v)
1552 #endif
1553  for (int j = 0; j < pnY2; j++)
1554  {
1555  Real fy = (-pnY + j) / ssY;
1556  Real fyy = fy * fy;
1557  int iWidth = j * pnX2;
1558  for (int i = 0; i < pnX2; i++)
1559  {
1560  Real fx = (-pnX + i) / ssX;
1561  Real fxx = fx * fx;
1562 
1563  Real sqrtPart = sqrt(v - fxx - fyy);
1564  Complex<Real> prop(0, z * sqrtPart);
1565  temp[iWidth + i] *= prop.exp();
1566  }
1567  }
1568 
1569  fft2(temp, temp, pnX2, pnY2, OPH_BACKWARD, true);
1570 
1571 #ifdef _OPENMP
1572 #pragma omp parallel for firstprivate(pnX, pnX2, hpnX, hpnY)
1573 #endif
1574  for (int i = 0; i < pnY; i++)
1575  {
1576  int src = pnX2 * (i + hpnY) + hpnX;
1577  int dst = pnX * i;
1578  memcpy(&out[dst], &temp[src], sizeof(Complex<Real>) * pnX);
1579  }
1580  delete[] temp;
1581 
1582 }
1583 
1585 {
1586  if (x == 0.0 && y == 0.0) return false;
1587 
1588  bool bAxisX = (x == 0.0) ? false : true;
1589  bool bAxisY = (y == 0.0) ? false : true;
1590  const uint nChannel = context_.waveNum;
1591  const int pnX = context_.pixel_number[_X];
1592  const int pnY = context_.pixel_number[_Y];
1593  const Real ppX = context_.pixel_pitch[_X];
1594  const Real ppY = context_.pixel_pitch[_Y];
1595  const vec2 ss = context_.ss;
1596  Real ppY2 = ppY * 2;
1597  Real ppX2 = ppX * 2;
1598  Real ssX = -ss[_X] / 2;
1599  Real ssY = -ss[_Y] / 2;
1600 
1601  Real *waveRatio = new Real[nChannel];
1602 
1603  Complex<Real> pi2(0.0, -2 * M_PI);
1604 
1605  for (uint i = 0; i < nChannel; i++) {
1606  waveRatio[i] = context_.wave_length[nChannel - 1] / context_.wave_length[i];
1607 
1608  Real ratioX = x * waveRatio[i];
1609  Real ratioY = y * waveRatio[i];
1610 
1611 #ifdef _OPENMP
1612 #pragma omp parallel for firstprivate(ppX, ppY, ppX2, ppY2, ssX, ssY, pi2)
1613 #endif
1614  for (int y = 0; y < pnY; y++) {
1615  Complex<Real> yy(0, 0);
1616  if (bAxisY) {
1617  Real startY = ssY + (ppY * y);
1618  Real shiftY = startY / ppY2 * ratioY;
1619  yy = (pi2 * shiftY).exp();
1620  }
1621  int offset = y * pnX;
1622 
1623  for (int x = 0; x < pnX; x++) {
1624  if (bAxisY) {
1625  complex_H[i][offset + x] = complex_H[i][offset + x] * yy;
1626  }
1627  if (bAxisX) {
1628  Real startX = ssX + (ppX * x);
1629  Real shiftX = startX / ppX2 * ratioX;
1630  Complex<Real> xx = (pi2 * shiftX).exp();
1631  complex_H[i][offset + x] = complex_H[i][offset + x] * xx;
1632  }
1633  }
1634  }
1635  }
1636  return true;
1637 }
1638 
1639 void ophGen::waveCarry(Real carryingAngleX, Real carryingAngleY, Real distance)
1640 {
1641  const int pnX = context_.pixel_number[_X];
1642  const int pnY = context_.pixel_number[_Y];
1643  const Real ppX = context_.pixel_pitch[_X];
1644  const Real ppY = context_.pixel_pitch[_Y];
1645  const long long int pnXY = pnX * pnY;
1646  const uint nChannel = context_.waveNum;
1647  Real dfx = 1 / ppX / pnX;
1648  Real dfy = 1 / ppY / pnY;
1649 
1650  int beginX = -pnX >> 1;
1651  int endX = pnX >> 1;
1652  int beginY = pnY >> 1;
1653  int endY = -pnY >> 1;
1654 
1655  Real carryX = distance * tan(carryingAngleX);
1656  Real carryY = distance * tan(carryingAngleY);
1657 
1658  for (uint ch = 0; ch < nChannel; ch++) {
1659  int k = 0;
1660  for (int i = beginY; i > endY; i--)
1661  {
1662  Real _carryY = carryY * i * dfy;
1663 
1664  for (int j = beginX; j < endX; j++)
1665  {
1666  Real x = j * dfx;
1667  Complex<Real> carrier(0, carryX * x + _carryY);
1668  complex_H[ch][k] = complex_H[ch][k] * exp(carrier);
1669 
1670  k++;
1671  }
1672  }
1673  }
1674 }
1675 
1676 void ophGen::waveCarry(Complex<Real>* src, Complex<Real>* dst, Real wavelength, int carryIdxX, int carryIdxY)
1677 {
1678  const int pnX = context_.pixel_number[_X];
1679  const int pnY = context_.pixel_number[_Y];
1680  const Real ppX = context_.pixel_pitch[_X];
1681  const Real ppY = context_.pixel_pitch[_Y];
1682  const long long int pnXY = pnX * pnY;
1683  Real dfx = 1 / ppX / pnX;
1684  Real dfy = 1 / ppY / pnY;
1685 
1686  int beginX = -pnX >> 1;
1687  int endX = pnX >> 1;
1688  int beginY = pnY >> 1;
1689  int endY = -pnY >> 1;
1690  Real pi2 = M_PI * 2;
1691 
1692  int k = 0;
1693  for (int i = beginY; i > endY; i--)
1694  {
1695  Real y = i * dfy * ppY * carryIdxY;
1696 
1697  for (int j = beginX; j < endX; j++)
1698  {
1699  Real x = j * dfx * ppX * carryIdxX;
1700 
1701  Complex<Real> carrier(0, pi2 * (x + y));
1702  dst[k] = src[k] * exp(carrier);
1703 
1704  k++;
1705  }
1706  }
1707 }
1708 
1709 void ophGen::encodeSideBand(bool bCPU, ivec2 sig_location)
1710 {
1711  if (complex_H == nullptr) {
1712  LOG("Not found diffracted data.");
1713  return;
1714  }
1715 
1716  const uint pnX = context_.pixel_number[_X];
1717  const uint pnY = context_.pixel_number[_Y];
1718 
1719  int cropx1, cropx2, cropx, cropy1, cropy2, cropy;
1720  if (sig_location[1] == 0) { //Left or right half
1721  cropy1 = 1;
1722  cropy2 = pnY;
1723  }
1724  else {
1725  cropy = (int)floor(((Real)pnY) / 2);
1726  cropy1 = cropy - (int)floor(((Real)cropy) / 2);
1727  cropy2 = cropy1 + cropy - 1;
1728  }
1729 
1730  if (sig_location[0] == 0) { // Upper or lower half
1731  cropx1 = 1;
1732  cropx2 = pnX;
1733  }
1734  else {
1735  cropx = (int)floor(((Real)pnX) / 2);
1736  cropx1 = cropx - (int)floor(((Real)cropx) / 2);
1737  cropx2 = cropx1 + cropx - 1;
1738  }
1739 
1740  cropx1 -= 1;
1741  cropx2 -= 1;
1742  cropy1 -= 1;
1743  cropy2 -= 1;
1744 
1745  if (bCPU)
1746  encodeSideBand_CPU(cropx1, cropx2, cropy1, cropy2, sig_location);
1747  else
1748  encodeSideBand_GPU(cropx1, cropx2, cropy1, cropy2, sig_location);
1749 }
1750 
1751 void ophGen::encodeSideBand_CPU(int cropx1, int cropx2, int cropy1, int cropy2, oph::ivec2 sig_location)
1752 {
1753  const uint pnX = context_.pixel_number[_X];
1754  const uint pnY = context_.pixel_number[_Y];
1755  const long long int pnXY = pnX * pnY;
1756  const uint nChannel = context_.waveNum;
1757 
1758  Complex<Real>* h_crop = new Complex<Real>[pnXY];
1759 
1760  for (uint ch = 0; ch < nChannel; ch++) {
1761 
1762  memset(h_crop, 0.0, sizeof(Complex<Real>) * pnXY);
1763 #ifdef _OPENMP
1764 #pragma omp parallel for firstprivate(cropx1, cropx2, cropy1, cropy2, pnX)
1765 #endif
1766  for (int p = 0; p < pnXY; p++)
1767  {
1768  int x = p % pnX;
1769  int y = p / pnX;
1770  if (x >= cropx1 && x <= cropx2 && y >= cropy1 && y <= cropy2)
1771  h_crop[p] = complex_H[ch][p];
1772  }
1773 
1774  Complex<Real> *in = nullptr;
1775 
1776  fft2(ivec2(pnX, pnY), in, OPH_BACKWARD);
1777  fft2(h_crop, h_crop, pnX, pnY, OPH_BACKWARD, true);
1778 
1779  memset(m_lpEncoded[ch], 0.0, sizeof(Real) * pnXY);
1780 #ifdef _OPENMP
1781 #pragma omp parallel for firstprivate(sig_location)
1782 #endif
1783  for (int i = 0; i < pnXY; i++) {
1784  Complex<Real> shift_phase(1, 0);
1785  getShiftPhaseValue(shift_phase, i, sig_location);
1786 
1787  m_lpEncoded[ch][i] = (h_crop[i] * shift_phase).real();
1788  }
1789  }
1790  delete[] h_crop;
1791 }
1792 
1793 void ophGen::encodeSideBand_GPU(int cropx1, int cropx2, int cropy1, int cropy2, oph::ivec2 sig_location)
1794 {
1795  const int pnX = context_.pixel_number[_X];
1796  const int pnY = context_.pixel_number[_Y];
1797  const long long int pnXY = pnX * pnY;
1798  const Real ppX = context_.pixel_pitch[_X];
1799  const Real ppY = context_.pixel_pitch[_Y];
1800  const Real ssX = context_.ss[_X] = pnX * ppX;
1801  const Real ssY = context_.ss[_Y] = pnY * ppY;
1802  const uint nChannel = context_.waveNum;
1803 
1804  cufftDoubleComplex *k_temp_d_, *u_complex_gpu_;
1805  cudaStream_t stream_;
1806  cudaStreamCreate(&stream_);
1807 
1808  cudaMalloc((void**)&u_complex_gpu_, sizeof(cufftDoubleComplex) * pnXY);
1809  cudaMalloc((void**)&k_temp_d_, sizeof(cufftDoubleComplex) * pnXY);
1810 
1811  for (uint ch = 0; ch < nChannel; ch++) {
1812  cudaMemcpy(u_complex_gpu_, complex_H[ch], sizeof(cufftDoubleComplex) * pnXY, cudaMemcpyHostToDevice);
1813 
1814  cudaMemsetAsync(k_temp_d_, 0, sizeof(cufftDoubleComplex) * pnXY, stream_);
1815  cudaCropFringe(stream_, pnX, pnY, u_complex_gpu_, k_temp_d_, cropx1, cropx2, cropy1, cropy2);
1816 
1817  cudaMemsetAsync(u_complex_gpu_, 0, sizeof(cufftDoubleComplex) * pnXY, stream_);
1818  cudaFFT(stream_, pnX, pnY, k_temp_d_, u_complex_gpu_, 1, true);
1819 
1820  cudaMemsetAsync(k_temp_d_, 0, sizeof(cufftDoubleComplex) * pnXY, stream_);
1821  cudaGetFringe(stream_, pnX, pnY, u_complex_gpu_, k_temp_d_, sig_location[0], sig_location[1], ssX, ssY, ppX, ppY, M_PI);
1822 
1823  cufftDoubleComplex* sample_fd = (cufftDoubleComplex*)malloc(sizeof(cufftDoubleComplex) * pnXY);
1824  memset(sample_fd, 0.0, sizeof(cufftDoubleComplex) * pnXY);
1825 
1826  cudaMemcpyAsync(sample_fd, k_temp_d_, sizeof(cufftDoubleComplex) * pnXY, cudaMemcpyDeviceToHost, stream_);
1827  memset(m_lpEncoded[ch], 0.0, sizeof(Real) * pnXY);
1828 
1829  for (int i = 0; i < pnX * pnY; i++)
1830  m_lpEncoded[ch][i] = sample_fd[i].x;
1831 
1832  cudaFree(sample_fd);
1833  }
1834  cudaStreamDestroy(stream_);
1835 }
1836 
1837 void ophGen::getShiftPhaseValue(oph::Complex<Real>& shift_phase_val, int idx, oph::ivec2 sig_location)
1838 {
1839  const int pnX = context_.pixel_number[_X];
1840  const int pnY = context_.pixel_number[_Y];
1841  const Real ppX = context_.pixel_pitch[_X];
1842  const Real ppY = context_.pixel_pitch[_Y];
1843  const Real ssX = context_.ss[_X] = pnX * ppX;
1844  const Real ssY = context_.ss[_Y] = pnY * ppY;
1845 
1846  if (sig_location[1] != 0)
1847  {
1848  int r = idx / pnX;
1849  int c = idx % pnX;
1850  Real yy = (ssY / 2.0) - (ppY)*r - ppY;
1851 
1852  oph::Complex<Real> val;
1853  if (sig_location[1] == 1)
1854  val[_IM] = 2 * M_PI * (yy / (4 * ppY));
1855  else
1856  val[_IM] = 2 * M_PI * (-yy / (4 * ppY));
1857 
1858  val.exp();
1859  shift_phase_val *= val;
1860  }
1861 
1862  if (sig_location[0] != 0)
1863  {
1864  int r = idx / pnX;
1865  int c = idx % pnX;
1866  Real xx = (-ssX / 2.0) - (ppX)*c - ppX;
1867 
1868  oph::Complex<Real> val;
1869  if (sig_location[0] == -1)
1870  val[_IM] = 2 * M_PI * (-xx / (4 * ppX));
1871  else
1872  val[_IM] = 2 * M_PI * (xx / (4 * ppX));
1873 
1874  val.exp();
1875  shift_phase_val *= val;
1876  }
1877 }
1878 
1879 void ophGen::GetRandomPhaseValue(Complex<Real>& rand_phase_val, bool rand_phase)
1880 {
1881  if (rand_phase)
1882  {
1883  rand_phase_val[_RE] = 0.0;
1884  Real min, max;
1885 #if REAL_IS_DOUBLE & true
1886  min = 0.0;
1887  max = 1.0;
1888 #else
1889  min = 0.f;
1890  max = 1.f;
1891 #endif
1892  rand_phase_val[_IM] = 2 * M_PI * oph::rand(min, max);
1893  rand_phase_val.exp();
1894 
1895  }
1896  else {
1897  rand_phase_val[_RE] = 1.0;
1898  rand_phase_val[_IM] = 0.0;
1899  }
1900 }
1901 
1903 {
1904  // ±âÁ¸ ÇØ»óµµ¿Í ´Ù¸£¸é ¹öÆÛ¸¦ ´Ù½Ã »ý¼º.
1905  if (context_.pixel_number != resolution) {
1906  setPixelNumber(resolution);
1907  Openholo::setPixelNumberOHC(resolution);
1908  initialize();
1909  }
1910 }
1911 
1912 template <typename T>
1913 void ophGen::RealPart(Complex<T> *holo, T *encoded, const int size)
1914 {
1915 #ifdef _OPENMP
1916 #pragma omp parallel for
1917 #endif
1918  for (int i = 0; i < size; i++) {
1919  encoded[i] = real(holo[i]);
1920  }
1921 }
1922 
1923 template <typename T>
1924 void ophGen::ImaginaryPart(Complex<T> *holo, T *encoded, const int size)
1925 {
1926 #ifdef _OPENMP
1927 #pragma omp parallel for
1928 #endif
1929  for (int i = 0; i < size; i++) {
1930  encoded[i] = imag(holo[i]);
1931  }
1932 }
1933 
1934 template <typename T>
1935 void ophGen::Phase(Complex<T> *holo, T *encoded, const int size)
1936 {
1937  double pi2 = M_PI * 2;
1938 #ifdef _OPENMP
1939 #pragma omp parallel for firstprivate(pi2)
1940 #endif
1941  for (int i = 0; i < size; i++) {
1942  encoded[i] = (holo[i].angle() + M_PI) / pi2; // 0 ~ 1
1943  }
1944 }
1945 
1946 template <typename T>
1947 void ophGen::Amplitude(Complex<T> *holo, T *encoded, const int size)
1948 {
1949 #ifdef _OPENMP
1950 #pragma omp parallel for
1951 #endif
1952  for (int i = 0; i < size; i++) {
1953  encoded[i] = holo[i].mag();
1954  }
1955 }
1956 
1957 template <typename T>
1958 void ophGen::TwoPhase(Complex<T>* holo, T* encoded, const int size)
1959 {
1960  int resize = size >> 1;
1961  Complex<T>* normCplx = new Complex<T>[resize];
1962 
1963 #ifdef _OPENMP
1964 #pragma omp parallel for
1965 #endif
1966  for (int i = 0; i < resize; i++) {
1967  normCplx[i] = holo[i * 2];
1968  }
1969 
1970  oph::normalize<T>(normCplx, normCplx, resize);
1971 
1972  T* ampl = new T[resize];
1973  Amplitude(normCplx, ampl, resize);
1974 
1975  T* phase = new T[resize];
1976  Phase(normCplx, phase, resize);
1977 
1978 #ifdef _OPENMP
1979 #pragma omp parallel for
1980 #endif
1981  for (int i = 0; i < resize; i++) {
1982  T delPhase = acos(ampl[i]);
1983  encoded[i * 2] = (phase[i] + M_PI) + delPhase;
1984  encoded[i * 2 + 1] = (phase[i] + M_PI) - delPhase;
1985  }
1986 
1987  delete[] normCplx;
1988  delete[] ampl;
1989  delete[] phase;
1990 }
1991 
1992 template <typename T>
1993 void ophGen::Burckhardt(Complex<T>* holo, T* encoded, const int size)
1994 {
1995  int resize = size / 3;
1996  Complex<T>* norm = new Complex<T>[resize];
1997 #ifdef _OPENMP
1998 #pragma omp parallel for
1999 #endif
2000  for (int i = 0; i < resize; i++) {
2001  norm[i] = holo[i * 3];
2002  }
2003 
2004  oph::normalize(norm, norm, resize);
2005 
2006  T* phase = new T[resize];
2007  Phase(norm, phase, resize);
2008 
2009  T* ampl = new T[resize];
2010  Amplitude(norm, ampl, resize);
2011 
2012  T sqrt3 = sqrt(3);
2013  T pi2 = 2 * M_PI;
2014  T pi4 = 4 * M_PI;
2015 
2016 #ifdef _OPENMP
2017 #pragma omp parallel for firstprivate(pi2, pi4, sqrt3)
2018 #endif
2019  for (int i = 0; i < resize; i++) {
2020  int idx = 3 * i;
2021  if (phase[i] >= 0 && phase[i] < (pi2 / 3))
2022  {
2023  encoded[idx] = ampl[i] * (cos(phase[i]) + sin(phase[i]) / sqrt3);
2024  encoded[idx + 1] = 2 * sin(phase[i]) / sqrt3;
2025  }
2026  else if (phase[i] >= (pi2 / 3) && phase[i] < (pi4 / 3))
2027  {
2028  encoded[idx + 1] = ampl[i] * (cos(phase[i] - (pi2 / 3)) + sin(phase[i] - (pi2 / 3)) / sqrt3);
2029  encoded[idx + 2] = 2 * sin(phase[i] - (pi2 / 3)) / sqrt3;
2030  }
2031  else if (phase[i] >= (pi4 / 3) && phase[i] < (pi2))
2032  {
2033  encoded[idx + 2] = ampl[i] * (cos(phase[i] - (pi4 / 3)) + sin(phase[i] - (pi4 / 3)) / sqrt3);
2034  encoded[idx] = 2 * sin(phase[i] - (pi4 / 3)) / sqrt3;
2035  }
2036  }
2037 
2038  delete[] ampl;
2039  delete[] phase;
2040  delete[] norm;
2041 }
2042 
2043 
2044 template <typename T>
2045 void ophGen::SimpleNI(Complex<T>* holo, T* encoded, const int size)
2046 {
2047  T* tmp1 = new T[size];
2048 #ifdef _OPENMP
2049 #pragma omp parallel for
2050 #endif
2051  for (int i = 0; i < size; i++) {
2052  tmp1[i] = holo[i].mag();
2053  }
2054 
2055  T max = maxOfArr(tmp1, size);
2056  delete[] tmp1;
2057 
2058 #ifdef _OPENMP
2059 #pragma omp parallel for firstprivate(max)
2060 #endif
2061  for (int i = 0; i < size; i++) {
2062  T tmp = (holo[i] + max).mag();
2063  encoded[i] = tmp * tmp;
2064  }
2065 }
2066 
2067 void ophGen::transVW(int nVertex, Vertex* dst, Vertex* src)
2068 {
2069  Real fieldLens = m_dFieldLength;
2070  for (int i = 0; i < nVertex; i++)
2071  {
2072  dst[i].point.pos[_X] = -fieldLens * src[i].point.pos[_X] / (src[i].point.pos[_X] - fieldLens);
2073  dst[i].point.pos[_Y] = -fieldLens * src[i].point.pos[_Y] / (src[i].point.pos[_Y] - fieldLens);
2074  dst[i].point.pos[_Z] = -fieldLens * src[i].point.pos[_Z] / (src[i].point.pos[_Z] - fieldLens);
2075  }
2076 }
2077 
2078 void ophGen::transVW(int nVertex, Real *dst, Real *src)
2079 {
2080  Real fieldLens = m_dFieldLength;
2081  for (int i = 0; i < nVertex; i++) {
2082  dst[i] = -fieldLens * src[i] / (src[i] - fieldLens);
2083  }
2084 }
2085 
2086 void ophGen::ScaleChange(Real *src, Real *dst, int nSize, Real scaleX, Real scaleY, Real scaleZ)
2087 {
2088  Real x = scaleX;
2089  Real y = scaleY;
2090  Real z = scaleZ;
2091 
2092 #ifdef _OPENMP
2093 #pragma omp parallel for firstprivate(x, y, z)
2094 #endif
2095  for (int i = 0; i < nSize; i++) {
2096  dst[i + 0] = src[i + 0] * x;
2097  dst[i + 1] = src[i + 1] * y;
2098  dst[i + 2] = src[i + 2] * z;
2099  }
2100 }
2101 
2102 void ophGen::GetMaxMin(Real *src, int len, Real& max, Real& min)
2103 {
2104  Real maxTmp = MIN_DOUBLE;
2105  Real minTmp = MAX_DOUBLE;
2106 
2107  for (int i = 0; i < len; i++) {
2108  if (src[i] > maxTmp)
2109  maxTmp = src[i];
2110  if (src[i] < minTmp)
2111  minTmp = src[i];
2112  }
2113  max = maxTmp;
2114  min = minTmp;
2115 }
2116 
2117 
2118 void ophGen::CorrectionChromaticAberration(uchar* src, uchar* dst, int width, int height, int ch)
2119 {
2120  if (ch < 2)
2121  {
2122  const uint nWave = context_.waveNum;
2123  const int pnXY = width * height;
2124  const Real lambda = context_.wave_length[ch];
2125  const Real waveRatio = nWave > 1 ? context_.wave_length[nWave - 1] / lambda : 1.0;
2126 
2127  int scaleX = round(width * 4 * waveRatio);
2128  int scaleY = round(height * 4 * waveRatio);
2129 
2130  int ww = width * 4;
2131  int hh = height * 4;
2132  int nSize = ww * hh;
2133  int nScaleSize = scaleX * scaleY;
2134  uchar *img_tmp = new uchar[nSize];
2135  uchar *imgScaled = new uchar[nScaleSize];
2136  imgScaleBilinear(src, imgScaled, width, height, scaleX, scaleY);
2137 
2138  memset(img_tmp, 0, sizeof(uchar) * nSize);
2139 
2140  int h1 = round((hh - scaleY) / 2);
2141  int w1 = round((ww - scaleX) / 2);
2142 #ifdef _OPENMP
2143 #pragma omp parallel for firstprivate(w1, h1, scaleX, ww)
2144 #endif
2145  for (int y = 0; y < scaleY; y++) {
2146  for (int x = 0; x < scaleX; x++) {
2147  img_tmp[(y + h1)*ww + x + w1] = imgScaled[y*scaleX + x];
2148  }
2149  }
2150  imgScaleBilinear(img_tmp, dst, ww, hh, width, height);
2151 
2152  delete[] img_tmp;
2153  delete[] imgScaled;
2154  }
2155 }
2156 
2157 
2159 {
2161 
2162  const uint nChannel = context_.waveNum;
2163 
2164  if (m_lpEncoded != nullptr) {
2165  for (uint i = 0; i < nChannel; i++) {
2166  if (m_lpEncoded[i] != nullptr) {
2167  delete[] m_lpEncoded[i];
2168  m_lpEncoded[i] = nullptr;
2169  }
2170  }
2171  delete[] m_lpEncoded;
2172  m_lpEncoded = nullptr;
2173  }
2174 
2175  if (m_lpNormalized != nullptr) {
2176  for (uint i = 0; i < nChannel; i++) {
2177  if (m_lpNormalized[i] != nullptr) {
2178  delete[] m_lpNormalized[i];
2179  m_lpNormalized[i] = nullptr;
2180  }
2181  }
2182  delete[] m_lpNormalized;
2183  m_lpNormalized = nullptr;
2184  }
2185 
2186  if (freqW != nullptr) delete[] freqW;
2187 }
#define OPH_BACKWARD
Definition: define.h:67
bool loadPLY(const std::string &fileName, ulonglong &n_points, Vertex **vertices)
Definition: PLYparser.cpp:142
ENCODE_FLAG
Definition: ophGen.h:84
void abs(const oph::Complex< T > &src, oph::Complex< T > &dst)
Definition: function.h:113
void Phase(Complex< T > *holo, T *encoded, const int size)
Definition: ophGen.cpp:1935
void RS_Diffraction(Point src, Complex< Real > *dst, Real lambda, Real distance, Real amplitude)
RS-diffraction method.
Definition: ophGen.cpp:356
Abstract class.
Definition: Openholo.h:109
Point point
Definition: struct.h:103
virtual bool saveAsImg(const char *fname, uint8_t bitsperpixel, uchar *src, int width, int height)
Function for creating image files.
Definition: Openholo.cpp:135
Real k
Definition: Openholo.h:67
void cudaCropFringe(CUstream_st *stream, int nx, int ny, cufftDoubleComplex *in_field, cufftDoubleComplex *out_field, int cropx1, int cropx2, int cropy1, int cropy2)
Crop input data according to x, y coordinates on GPU.
T angle(void)
Definition: complex.h:387
void setResolution(ivec2 resolution)
Function for setting buffer size.
Definition: ophGen.cpp:1902
NONE
Definition: ImgControl.h:24
void conv_fft2(Complex< Real > *src1, Complex< Real > *src2, Complex< Real > *dst, ivec2 size)
Convolution between Complex arrays which have same size.
Definition: ophGen.cpp:646
void GetMaxMin(Real *src, int len, Real &max, Real &min)
Definition: ophGen.cpp:2102
vec3 shift
Definition: Openholo.h:66
bool getWeightED(const ivec2 holosize, const int type, ivec2 *pNw)
Definition: ophGen.cpp:1362
void AngularSpectrumMethod(Complex< Real > *src, Complex< Real > *dst, Real lambda, Real distance)
Angular spectrum propagation method.
Definition: ophGen.cpp:597
void encodeSideBand_CPU(int cropx1, int cropx2, int cropy1, int cropy2, ivec2 sig_location)
Encode the CGH according to a signal location parameter on the CPU.
Definition: ophGen.cpp:1751
void binarization(Complex< Real > *src, Real *dst, const int size, int ENCODE_FLAG, Real threshold)
Definition: ophGen.cpp:1425
Real * wave_length
Definition: Openholo.h:70
Real * weight
Definition: ophGen.h:430
void GetRandomPhaseValue(Complex< Real > &rand_phase_val, bool rand_phase)
Assign random phase value if random_phase == 1.
Definition: ophGen.cpp:1879
ulonglong n_points
Number of points.
Definition: ophGen.h:585
void setPixelNumberOHC(const ivec2 pixel_number)
getter/setter for OHC file read and write
Definition: Openholo.h:464
SSB_PASSBAND
Definition: ophGen.h:296
unsigned char uchar
Definition: typedef.h:64
Complex< Real > * weightC
Definition: ophGen.h:431
VERTICAL
Definition: ImgControl.h:24
Real m_dFieldLength
Definition: ophGen.h:349
Real ** m_lpEncoded
buffer to encoded.
Definition: ophGen.h:339
float Real
Definition: typedef.h:55
void initialize(void)
Initialize variables for Hologram complex field, encoded data, normalized data.
Definition: ophGen.cpp:145
#define CUR_TIME
Definition: function.h:58
Real norm(const vec2 &a)
Definition: vec.h:417
Definition: struct.h:86
void RealPart(Complex< T > *holo, T *encoded, const int size)
Encoding method.
Definition: ophGen.cpp:1913
void setPixelPitchOHC(const vec2 pixel_pitch)
Definition: Openholo.h:467
bool shiftW(ivec2 holosize)
Definition: ophGen.cpp:1399
vec2 ss
Definition: Openholo.h:68
void cudaFFT(CUstream_st *stream, int nx, int ny, cufftDoubleComplex *in_filed, cufftDoubleComplex *output_field, int direction, bool bNormailized=false)
Convert data from the spatial domain to the frequency domain using 2D FFT on GPU. ...
HORIZONTAL
Definition: ImgControl.h:24
void TwoPhase(Complex< T > *holo, T *encoded, const int size)
Definition: ophGen.cpp:1958
bool checkExtension(const char *fname, const char *ext)
Functions for extension checking.
Definition: Openholo.cpp:86
#define OPH_ESTIMATE
Definition: define.h:76
structure for 2-dimensional integer vector and its arithmetic.
Definition: ivec.h:66
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:761
ivec2 offset
Definition: Openholo.h:64
void normalize(const Complex< T > *src, Complex< T > *dst, const int &size)
Normalize all elements of Complex<T>* src from 0 to 1.
Definition: function.h:176
#define PI
Definition: ophACPAS.h:9
bool rotate
Definition: Openholo.h:88
#define MIN_DOUBLE
Definition: define.h:148
#define _Y
Definition: define.h:96
#define _IM
Definition: complex.h:58
void Burckhardt(Complex< T > *holo, T *encoded, const int size)
Definition: ophGen.cpp:1993
ImageConfig imgCfg
Definition: Openholo.h:450
void setWavelengthOHC(const Real wavelength, const LenUnit wavelength_unit)
Definition: Openholo.h:470
ImgEncoderOhc * OHC_encoder
OHC file format Variables for read and write.
Definition: Openholo.h:457
vec2 pixel_pitch
Definition: Openholo.h:65
void ImaginaryPart(Complex< T > *holo, T *encoded, const int size)
Definition: ophGen.cpp:1924
void encodeSideBand(bool bCPU, ivec2 sig_location)
Encode the CGH according to a signal location parameter.
Definition: ophGen.cpp:1709
PRECISION
Definition: ophGen.h:79
bool Shift(Real x, Real y)
Definition: ophGen.cpp:1584
void normalize(void)
Normalization function to save as image file after hologram creation.
Definition: ophGen.cpp:675
bool binaryErrorDiffusion(Complex< Real > *holo, Real *encoded, const ivec2 holosize, const int type, Real threshold)
Definition: ophGen.cpp:1256
bool save(const char *fname, uint8_t bitsperpixel=8, uchar *src=nullptr, uint px=0, uint py=0)
Function for saving image files.
Definition: ophGen.cpp:709
ivec2 m_vecEncodeSize
Encoded hologram size, varied from encoding type.
Definition: ophGen.h:331
#define _X
Definition: define.h:92
Complex< Real > * freqW
Definition: ophGen.h:432
return true
Definition: Openholo.cpp:434
void singleSideBand(Complex< Real > *holo, Real *encoded, const ivec2 holosize, int passband)
Encoding method.
Definition: ophGen.cpp:1043
void encodeSideBand_GPU(int cropx1, int cropx2, int cropy1, int cropy2, ivec2 sig_location)
Encode the CGH according to a signal location parameter on the GPU.
Definition: ophGen.cpp:1793
void getShiftPhaseValue(Complex< Real > &shift_phase_val, int idx, ivec2 sig_location)
Calculate the shift phase value.
Definition: ophGen.cpp:1837
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
void * load(const char *fname)
Function for loading image files.
Definition: ophGen.cpp:791
void SimpleNI(Complex< T > *holo, T *encoded, const int size)
Definition: ophGen.cpp:2045
bool m_bRandomPhase
Definition: ophGen.h:437
void CorrectionChromaticAberration(uchar *src, uchar *dst, int width, int height, int ch)
Definition: ophGen.cpp:2118
#define _RE
Definition: complex.h:55
void waveCarry(Real carryingAngleX, Real carryingAngleY, Real distance)
Wave carry.
Definition: ophGen.cpp:1639
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
structure for 2-dimensional Real type vector and its arithmetic.
Definition: vec.h:66
void fresnelPropagation(OphConfig context, Complex< Real > *in, Complex< Real > *out, Real distance)
Fresnel propagation.
Definition: ophGen.cpp:1441
Definition: struct.h:102
Real pos[3]
Definition: struct.h:87
#define MAX_DOUBLE
Definition: define.h:140
#define ELAPSED_TIME(x, y)
Definition: function.h:59
int flip
Definition: Openholo.h:90
Real * realEnc
Definition: ophGen.h:433
void cudaGetFringe(CUstream_st *stream, int pnx, int pny, cufftDoubleComplex *in_field, cufftDoubleComplex *out_field, int sig_locationx, int sig_locationy, Real ssx, Real ssy, Real ppx, Real ppy, Real PI)
Encode the CGH according to a signal location parameter on the GPU.
uint waveNum
Definition: Openholo.h:69
void Fresnel_FFT(Complex< Real > *src, Complex< Real > *dst, Real lambda, Real waveRatio, Real distance)
Fresnel-fft method.
Definition: ophGen.cpp:513
void Amplitude(Complex< T > *holo, T *encoded, const int size)
Definition: ophGen.cpp:1947
Complex< T > & exp()
Definition: complex.h:395
ivec2 pixel_number
Definition: Openholo.h:63
bool saveRefImages(char *fnameW, char *fnameWC, char *fnameAS, char *fnameSSB, char *fnameHP, char *fnameFreq, char *fnameReal, char *fnameBin, char *fnameReconBin, char *fnameReconErr, char *fnameReconNo)
Definition: ophGen.cpp:1128
Vertex * vertices
Data of point clouds.
Definition: ophGen.h:589
virtual bool loadAsOhc(const char *fname)
Function to read OHC file.
Definition: Openholo.cpp:280
bool readConfig(const char *fname)
load to configuration file.
Definition: ophGen.cpp:220
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2150
bool bUseDP
Definition: Openholo.h:62
virtual uchar * loadAsImg(const char *fname)
Function for loading image files.
Definition: Openholo.cpp:321
Real rand(const Real min, const Real max, oph::ulong _SEED_VALUE=0)
Get random Real value from min to max.
Definition: function.h:294
void getAmplitude(oph::Complex< Real > *src, Real *dst, const int &size)
Definition: function.h:330
void ScaleChange(Real *src, Real *dst, int nSize, Real scaleX, Real scaleY, Real scaleZ)
Definition: ophGen.cpp:2086
uchar ** m_lpNormalized
buffer to normalized.
Definition: ophGen.h:341
Complex< Real > * AS
Binary Encoding - Error diffusion.
Definition: ophGen.h:427
Real minOfArr(const std::vector< Real > &arr)
Definition: function.h:73
Data for Point Cloud.
Definition: ophGen.h:583
Real maxOfArr(const std::vector< Real > &arr)
Definition: function.h:87
void encoding()
Definition: ophGen.cpp:982
void resetBuffer()
reset buffer
Definition: ophGen.cpp:821
void setPixelNumber(ivec2 n)
Function for setting the output resolution.
Definition: Openholo.h:206
Complex< Real > * normalized
Definition: ophGen.h:428
int m_nStream
Definition: ophGen.h:350
ophGen(void)
Constructor.
Definition: ophGen.cpp:112
OphConfig context_
Definition: Openholo.h:449
#define OPH_FORWARD
Definition: define.h:66
void Fresnel_Diffraction(Point src, Complex< Real > *dst, Real lambda, Real distance, Real amplitude)
Fresnel-diffraction method.
Definition: ophGen.cpp:443
Complex< Real > ** complex_H
Definition: Openholo.h:452
virtual bool loadAsOhc(const char *fname)
Function to read OHC file.
Definition: ophGen.cpp:803
void transVW(int nVertex, Vertex *dst, Vertex *src)
Definition: ophGen.cpp:2067
T mag() const
Definition: complex.h:368
#define _Z
Definition: define.h:100
int ENCODE_METHOD
Encoding method flag.
Definition: ophGen.h:333
void freqShift(Complex< Real > *holo, Complex< Real > *encoded, const ivec2 holosize, int shift_x, int shift_y)
Frequency shift.
Definition: ophGen.cpp:1107
int loadPointCloud(const char *pc_file, OphPointCloudData *pc_data_)
load to point cloud data.
Definition: ophGen.cpp:206
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:805
Real * maskHP
Definition: ophGen.h:436
bool merge
Definition: Openholo.h:89
#define M_PI
Definition: define.h:52
Definition: ophGen.h:76
virtual void ophFree(void)
Pure virtual function for override in child classes.
Definition: ophGen.cpp:2158
virtual ~ophGen(void)=0
Destructor.
Definition: ophGen.cpp:140
Real * binary
Definition: ophGen.h:434
Real * maskSSB
Definition: ophGen.h:435