Openholo  v1.0
Open Source Digital Holographic Library
ophLightField.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 "ophLightField.h"
47 
48 #include "include.h"
49 
50 #include "sys.h"
51 #include "tinyxml2.h"
52 
53 #define for_i(itr, oper) for(int i=0; i<itr; i++){ oper }
54 
56  : num_image(ivec2(0, 0))
57  , resolution_image(ivec2(0, 0))
58  , distanceRS2Holo(0.0)
59  , is_CPU(true)
60  , is_ViewingWindow(false)
61  , LF(nullptr)
62  , RSplane_complex_field(nullptr)
63 {
64 }
65 
66 void ophLF::setMode(bool isCPU)
67 {
68  is_CPU = isCPU;
69 }
70 
71 void ophLF::setViewingWindow(bool is_ViewingWindow)
72 {
73  this->is_ViewingWindow = is_ViewingWindow;
74 }
75 
76 bool ophLF::readConfig(const char* fname)
77 {
78  if (!ophGen::readConfig(fname))
79  return false;
80 
81  LOG("Reading....%s...", fname);
82 
83  auto start = CUR_TIME;
84 
85  using namespace tinyxml2;
86  /*XML parsing*/
87  tinyxml2::XMLDocument xml_doc;
88  XMLNode *xml_node;
89 
90  if (!checkExtension(fname, ".xml"))
91  {
92  LOG("file's extension is not 'xml'\n");
93  return false;
94  }
95  if (xml_doc.LoadFile(fname) != XML_SUCCESS)
96  {
97  LOG("Failed to load file \"%s\"\n", fname);
98  return false;
99  }
100 
101  xml_node = xml_doc.FirstChild();
102 
103  // about viewing window
104  auto next = xml_node->FirstChildElement("FieldLength");
105  if (!next || XML_SUCCESS != next->QueryDoubleText(&fieldLens))
106  return false;
107 
108  // about image
109  next = xml_node->FirstChildElement("Image_NumOfX");
110  if (!next || XML_SUCCESS != next->QueryIntText(&num_image[_X]))
111  return false;
112  next = xml_node->FirstChildElement("Image_NumOfY");
113  if (!next || XML_SUCCESS != next->QueryIntText(&num_image[_Y]))
114  return false;
115  next = xml_node->FirstChildElement("Image_Width");
116  if (!next || XML_SUCCESS != next->QueryIntText(&resolution_image[_X]))
117  return false;
118  next = xml_node->FirstChildElement("Image_Height");
119  if (!next || XML_SUCCESS != next->QueryIntText(&resolution_image[_Y]))
120  return false;
121  next = xml_node->FirstChildElement("Distance");
122  if (!next || XML_SUCCESS != next->QueryDoubleText(&distanceRS2Holo))
123  return false;
124 
125  auto end = CUR_TIME;
126  auto during = ((chrono::duration<Real>)(end - start)).count();
127  LOG("%lf (s)..done\n", during);
128 
129  initialize();
130  return true;
131 }
132 
133 int ophLF::loadLF(const char* directory, const char* exten)
134 {
135  LF_directory = directory;
136  ext = exten;
137 
138  initializeLF();
139 
140  _finddata_t data;
141 
142  string sdir = std::string(LF_directory).append("\\").append("*.").append(ext);
143  intptr_t ff = _findfirst(sdir.c_str(), &data);
144  if (ff != -1)
145  {
146  int num = 0;
147  uchar* rgbOut;
148  ivec2 sizeOut;
149  int bytesperpixel;
150 
151  while (1)
152  {
153  string imgfullname = std::string(LF_directory).append("\\").append(data.name);
154 
155  getImgSize(sizeOut[_X], sizeOut[_Y], bytesperpixel, imgfullname.c_str());
156 
157  rgbOut = loadAsImg(imgfullname.c_str());
158 
159  if (rgbOut == 0) {
160  cout << "LF load was failed." << endl;
161  return -1;
162  }
163 
164  convertToFormatGray8(rgbOut, *(LF + num), sizeOut[_X], sizeOut[_Y], bytesperpixel);
165  delete[] rgbOut; // solved memory leak.
166  num++;
167 
168  int out = _findnext(ff, &data);
169  if (out == -1)
170  break;
171  }
172  _findclose(ff);
173  cout << "LF load was successed." << endl;
174 
175  if (num_image[_X] * num_image[_Y] != num) {
176  cout << "num_image is not matched." << endl;
177  }
178  return 1;
179  }
180  else
181  {
182  cout << "LF load was failed." << endl;
183  return -1;
184  }
185 }
186 
188 {
189  initializeLF();
190 
191  _finddata_t data;
192 
193  string sdir = std::string("./").append(LF_directory).append("/").append("*.").append(ext);
194  intptr_t ff = _findfirst(sdir.c_str(), &data);
195  if (ff != -1)
196  {
197  int num = 0;
198  uchar* rgbOut;
199  ivec2 sizeOut;
200  int bytesperpixel;
201 
202  while (1)
203  {
204  string imgfullname = std::string(LF_directory).append("/").append(data.name);
205 
206  getImgSize(sizeOut[_X], sizeOut[_Y], bytesperpixel, imgfullname.c_str());
207  rgbOut = loadAsImg(imgfullname.c_str());
208 
209  if (rgbOut == 0) {
210  cout << "LF load was failed." << endl;
211  cin.get();
212  return -1;
213  }
214 
215  convertToFormatGray8(rgbOut, *(LF + num), sizeOut[_X], sizeOut[_Y], bytesperpixel);
216 
217  num++;
218 
219  int out = _findnext(ff, &data);
220  if (out == -1)
221  break;
222  }
223  _findclose(ff);
224  cout << "LF load was successed." << endl;
225 
226  if (num_image[_X] * num_image[_Y] != num) {
227  cout << "num_image is not matched." << endl;
228  cin.get();
229  }
230  return 1;
231  }
232  else
233  {
234  cout << "LF load was failed." << endl;
235  cin.get();
236  return -1;
237  }
238 }
239 
241 {
242  resetBuffer();
243 
244  LOG("1) Algorithm Method : Light Field\n");
245  LOG("2) Generate Hologram with %s\n", is_CPU ?
246 #ifdef _OPENMP
247  "Multi Core CPU" :
248 #else
249  "Single Core CPU" :
250 #endif
251  "GPU");
252  LOG("3) Transform Viewing Window : %s\n", is_ViewingWindow ? "ON" : "OFF");
253 
254  auto begin = CUR_TIME;
255  if (is_CPU)
256  {
258  for(uint ch = 0; ch < context_.waveNum; ch++)
259  fresnelPropagation(RSplane_complex_field, complex_H[ch], distanceRS2Holo, ch);
260  }
261  else
262  {
266  }
267 
268  auto end = CUR_TIME;
269  elapsedTime = ((std::chrono::duration<Real>)(end - begin)).count();
270  LOG("Total Elapsed Time: %lf (sec)\n", elapsedTime);
271 }
272 
273 //int ophLF::saveAsOhc(const char * fname)
274 //{
275 // setPixelNumberOHC(getEncodeSize());
276 //
277 // Openholo::saveAsOhc(fname);
278 //
279 // return 0;
280 //}
281 
282 
284 {
285  if (LF) {
286  for (int i = 0; i < nImages; i++) {
287  if (LF[i]) {
288  delete[] LF[i];
289  LF[i] = nullptr;
290  }
291  }
292  delete[] LF;
293  LF = nullptr;
294  }
295 
296  LF = new uchar*[num_image[_X] * num_image[_Y]];
297  for (int i = 0; i < num_image[_X] * num_image[_Y]; i++) {
298  LF[i] = new uchar[resolution_image[_X] * resolution_image[_Y]];
299  memset(LF[i], 0, resolution_image[_X] * resolution_image[_Y]);
300  }
301  nImages = num_image[_X] * num_image[_Y];
302  cout << "The Number of the Images : " << num_image[_X] * num_image[_Y] << endl;
303 }
304 
305 
307 {
308 #ifdef CHECK_PROC_TIME
309  auto begin = CUR_TIME;
310 #endif
311  const uint nX = num_image[_X];
312  const uint nY = num_image[_Y];
313  const uint nXY = nX * nY;
314  const uint rX = resolution_image[_X];
315  const uint rY = resolution_image[_Y];
316  const uint rXY = rX * rY;
317 
318  if (RSplane_complex_field) {
319  delete[] RSplane_complex_field;
320  RSplane_complex_field = nullptr;
321  }
322  RSplane_complex_field = new Complex<Real>[nXY * rXY];
323  memset(RSplane_complex_field, 0.0, sizeof(Complex<Real>) * nXY * rXY);
324 
325  //Complex<Real>* complexLF = new Complex<Real>[rXY];
326  Complex<Real>* complexLF = new Complex<Real>[nXY];
327 
328  Complex<Real>* FFTLF = new Complex<Real>[nXY];
329 
330  Real randVal;
331  Complex<Real> phase(0.0, 0.0);
332 
333  int idxrX;
334  int idxImg = 0;
335 
336  for (idxrX = 0; idxrX < rX; idxrX++) { // 192
337  for (int idxrY = 0; idxrY < rY; idxrY++) { // 108
338  memset(complexLF, 0.0, sizeof(Complex<Real>) * nXY);
339  memset(FFTLF, 0.0, sizeof(Complex<Real>) * nXY);
340 
341  for (int idxnY = 0; idxnY < nY; idxnY++) { // 10
342  for (int idxnX = 0; idxnX < nX; idxnX++) { // 10
343  // LF[img idx][pixel idx]
344  complexLF[idxnX + nX * idxnY] = (Real)(LF[idxnX + nX * idxnY][idxrX + rX * idxrY]);
345  }
346  }
347 
348  fft2(num_image, complexLF, OPH_FORWARD, OPH_ESTIMATE);
349  fftwShift(complexLF, FFTLF, nX, nY, OPH_FORWARD);
350  //fftExecute(FFTLF);
351 
352  for (int idxnX = 0; idxnX < nX; idxnX++) { // 10
353  for (int idxnY = 0; idxnY < nY; idxnY++) { // 10
354  randVal = rand((Real)0, (Real)1, idxrX * idxrY);
355  phase(0, 2 * M_PI * randVal); // random phase
356 
357  //*(RSplane_complex_field + nXY * rX*idxrY + nX * rX*idxnY + nX * idxrX + idxnX) = *(FFTLF + (idxnX + nX * idxnY))*exp(phase);
358  // 100 * 192 * 107 + 10 * 192 * 107 + 10 * 191 + 9
359  RSplane_complex_field[nXY * rX*idxrY + nX * rX*idxnY + nX * idxrX + idxnX] =
360  FFTLF[idxnX + nX * idxnY] * exp(phase);
361  //
362  // (20/5) (x:5/y:8) => 165
363  }
364  }
365  idxImg++;
366  }
367  }
368  delete[] complexLF, FFTLF;
369  fftFree();
370 #ifdef CHECK_PROC_TIME
371  auto end = CUR_TIME;
372  LOG("\n%s : %lf(s)\n\n", __FUNCTION__, ((std::chrono::duration<Real>)(end - begin)).count());
373 #endif
374 }
375 
376 void ophLF::writeIntensity_gray8_bmp(const char* fileName, int nx, int ny, Complex<Real>* complexvalue, int k)
377 {
378  const int n = nx * ny;
379 
380  double* intensity = (double*)malloc(sizeof(double)*n);
381  for (int i = 0; i < n; i++)
382  intensity[i] = complexvalue[i].real();
383  //intensity[i] = complexvalue[i].mag2();
384 
385  double min_val, max_val;
386  min_val = intensity[0];
387  max_val = intensity[0];
388 
389  for (int i = 0; i < n; ++i)
390  {
391  if (min_val > intensity[i])
392  min_val = intensity[i];
393  else if (max_val < intensity[i])
394  max_val = intensity[i];
395  }
396 
397  char fname[100];
398  strcpy_s(fname, fileName);
399  if (k != -1)
400  {
401  char num[30];
402  sprintf_s(num, "_%d", k);
403  strcat_s(fname, num);
404  }
405  strcat_s(fname, ".bmp");
406 
407  //LOG("minval %e, max val %e\n", min_val, max_val);
408 
409  unsigned char* cgh = (unsigned char*)malloc(sizeof(unsigned char)*n);
410 
411  for (int i = 0; i < n; ++i) {
412  double val = (intensity[i] - min_val) / (max_val - min_val);
413  //val = pow(val, 1.0 / 1.5);
414  val = val * 255.0;
415  unsigned char v = (uchar)val;
416 
417  cgh[i] = v;
418  }
419 
420  int ret = Openholo::saveAsImg(fname, 8, cgh, nx, ny);
421 
422  free(intensity);
423  free(cgh);
424 }
void convertLF2ComplexField()
virtual bool saveAsImg(const char *fname, uint8_t bitsperpixel, uchar *src, int width, int height)
Function for creating image files.
Definition: Openholo.cpp:90
void fftFree(void)
Definition: Openholo.cpp:508
void setViewingWindow(bool is_ViewingWindow)
Set the value of a variable is_ViewingWindow(true or false)
unsigned char uchar
Definition: typedef.h:64
int loadLF()
bool readConfig(const char *fname)
Light Field based CGH configuration file load.
float Real
Definition: typedef.h:55
void initialize(void)
Initialize variables for Hologram complex field, encoded data, normalized data.
Definition: ophGen.cpp:69
#define CUR_TIME
Definition: function.h:58
void setMode(bool is_CPU)
Set the value of a variable is_CPU(true or false)
void convertLF2ComplexField_GPU()
bool checkExtension(const char *fname, const char *ext)
Functions for extension checking.
Definition: Openholo.cpp:80
#define OPH_ESTIMATE
Definition: define.h:76
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:761
void generateHologram()
Hologram generation.
Real elapsedTime
Elapsed time of generate hologram.
Definition: ophGen.h:246
#define _Y
Definition: define.h:84
void prepareInputdataGPU()
#define _X
Definition: define.h:80
bool getImgSize(int &w, int &h, int &bytesperpixel, const char *fname)
Function for getting the image size.
Definition: Openholo.cpp:315
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:416
void convertToFormatGray8(uchar *src, uchar *dst, int w, int h, int bytesperpixel)
Function for convert image format to gray8.
Definition: Openholo.cpp:367
void fresnelPropagation(OphConfig context, Complex< Real > *in, Complex< Real > *out, Real distance)
Fresnel propagation.
Definition: ophGen.cpp:768
ophLF(void)
Constructor.
void fresnelPropagation_GPU()
uint waveNum
Definition: Openholo.h:68
bool readConfig(const char *fname)
load to configuration file.
Definition: ophGen.cpp:150
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2157
virtual uchar * loadAsImg(const char *fname)
Function for loading image files.
Definition: Openholo.cpp:199
Real rand(const Real min, const Real max, oph::ulong _SEED_VALUE=0)
Get random Real value from min to max.
Definition: function.h:287
void writeIntensity_gray8_bmp(const char *fileName, int nx, int ny, Complex< Real > *complexvalue, int k=-1)
void resetBuffer()
reset buffer
Definition: ophGen.cpp:363
void fftwShift(Complex< Real > *src, Complex< Real > *dst, int nx, int ny, int type, bool bNormalized=false)
Convert data from the spatial domain to the frequency domain using 2D FFT on CPU. ...
Definition: Openholo.cpp:530
OphConfig context_
Definition: Openholo.h:297
void initializeLF()
#define OPH_FORWARD
Definition: define.h:66
Complex< Real > ** complex_H
Definition: Openholo.h:298
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:940
unsigned int uint
Definition: typedef.h:62
#define M_PI
Definition: define.h:52