Openholo  v4.2
Open Source Digital Holographic Library
Openholo.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 "Openholo.h"
47 #include <omp.h>
48 #include <limits.h>
49 #include "sys.h"
50 #include "ImgCodecOhc.h"
51 #include "ImgControl.h"
52 
54  : Base()
55  , plan_fwd(nullptr)
56  , plan_bwd(nullptr)
57  , fft_in(nullptr)
58  , fft_out(nullptr)
59  , pnx(1)
60  , pny(1)
61  , pnz(1)
62  , fft_sign(OPH_FORWARD)
63  , OHC_encoder(nullptr)
64  , OHC_decoder(nullptr)
65  , complex_H(nullptr)
66 {
67  fftw_init_threads();
68  fftw_plan_with_nthreads(omp_get_max_threads());
71 }
72 
74 {
75  if (OHC_encoder) {
76  delete OHC_encoder;
77  OHC_encoder = nullptr;
78  }
79  if (OHC_decoder) {
80  delete OHC_decoder;
81  OHC_decoder = nullptr;
82  }
83  fftw_cleanup_threads();
84 }
85 
86 bool Openholo::checkExtension(const char * fname, const char * ext)
87 {
88  string filename(fname);
89  string fext(ext);
90  size_t find = filename.find_last_of(".");
91  size_t len = filename.length();
92 
93  if (find > len)
94  return false;
95 
96  if (!filename.substr(find).compare(fext))
97  return true;
98  else
99  return false;
100 }
101 
102 
103 bool Openholo::mergeColor(int idx, int width, int height, uchar *src, uchar *dst)
104 {
105  if (idx < 0 || idx > 2) return false;
106 
107  int N = width * height;
108  int a = 2 - idx;
109 #ifdef _OPENMP
110 #pragma omp parallel for firstprivate(a)
111 #endif
112  for (int i = 0; i < N; i++) {
113  dst[i * 3 + a] = src[i];
114  }
115 
116  return true;
117 }
118 
119 bool Openholo::separateColor(int idx, int width, int height, uchar *src, uchar *dst)
120 {
121  if (idx < 0 || idx > 2) return false;
122 
123  int N = width * height;
124  int a = 2 - idx;
125 #ifdef _OPENMP
126 #pragma omp parallel for firstprivate(a)
127 #endif
128  for (int i = 0; i < N; i++) {
129  dst[i] = src[i * 3 + a];
130  }
131 
132  return true;
133 }
134 
135 bool Openholo::saveAsImg(const char * fname, uint8_t bitsperpixel, uchar* src, int width, int height)
136 {
137  bool bOK = true;
138  auto begin = CUR_TIME;
139 
140  int padding = 0;
141  int _byteperline = ((width * bitsperpixel >> 3) + 3) & ~3;
142  int _pixelbytesize = height * _byteperline;
143  int _filesize = _pixelbytesize;
144  bool hasColorTable = (bitsperpixel <= 8) ? true : false;
145  int _headersize = sizeof(bitmap);
146  int _iColor = (hasColorTable) ? 256 : 0;
147 
148  int mod = width % 4;
149  if (mod != 0) {
150  padding = 4 - mod;
151  }
152 
153  rgbquad *table = nullptr;
154 
155  if (hasColorTable) {
156  _headersize += _iColor * sizeof(rgbquad);
157  table = new rgbquad[_iColor];
158  memset(table, 0, sizeof(rgbquad) * _iColor);
159  for (int i = 0; i < _iColor; i++) { // for gray-scale
160  table[i].rgbBlue = i;
161  table[i].rgbGreen = i;
162  table[i].rgbRed = i;
163  }
164  }
165 
166  _filesize += _headersize;
167 
168  uchar *pBitmap = new uchar[_filesize];
169  memset(pBitmap, 0x00, _filesize);
170 
171  bitmap bitmap;
172  memset(&bitmap, 0, sizeof(bitmap));
173  int iCur = 0;
174 
175  bitmap._fileheader.signature[0] = 'B';
176  bitmap._fileheader.signature[1] = 'M';
177  bitmap._fileheader.filesize = _filesize;
179 
184  bitmap._bitmapinfoheader.bitsperpixel = bitsperpixel;
186  bitmap._bitmapinfoheader.imagesize = _pixelbytesize;
187  bitmap._bitmapinfoheader.ypixelpermeter = 0;// Y_PIXEL_PER_METER;
188  bitmap._bitmapinfoheader.xpixelpermeter = 0;// X_PIXEL_PER_METER;
190 
191  memcpy(&pBitmap[iCur], &bitmap._fileheader, sizeof(fileheader));
192  iCur += sizeof(fileheader);
193  memcpy(&pBitmap[iCur], &bitmap._bitmapinfoheader, sizeof(bitmapinfoheader));
194  iCur += sizeof(bitmapinfoheader);
195 
196  if (hasColorTable) {
197  memcpy(&pBitmap[iCur], table, sizeof(rgbquad) * _iColor);
198  iCur += sizeof(rgbquad) * _iColor;
199  }
200 
201  ImgControl *pControl = ImgControl::getInstance();
202  uchar *pTmp = new uchar[_pixelbytesize];
203  memcpy(pTmp, src, _pixelbytesize);
204 
205  if (imgCfg.flip)
206  {
207  pControl->Flip((oph::FLIP)imgCfg.flip, pTmp, pTmp, width + padding, height, bitsperpixel >> 3);
208  }
209 
210  if (imgCfg.rotate) {
211  pControl->Rotate(180.0, pTmp, pTmp, width + padding, height, width + padding, height, bitsperpixel >> 3);
212  }
213 
214  if (padding != 0)
215  {
216  for (int i = 0; i < height; i++)
217  {
218  memcpy(&pBitmap[iCur], &pTmp[width * i], width);
219  iCur += width;
220  memset(&pBitmap[iCur], 0x00, padding);
221  iCur += padding;
222  }
223  }
224  else
225  {
226  memcpy(&pBitmap[iCur], pTmp, _pixelbytesize);
227  iCur += _pixelbytesize;
228  }
229  delete[] pTmp;
230 
231  if (iCur != _filesize)
232  bOK = false;
233  else {
234  FILE* fp = fopen(fname, "wb");
235  if (fp == nullptr)
236  bOK = false;
237  else {
238  fwrite(pBitmap, 1, _filesize, fp);
239  fclose(fp);
240  }
241  }
242 
243  if (hasColorTable && table) delete[] table;
244  delete[] pBitmap;
245 
246  LOG("%s \'%s\' => %.5lf (sec)\n", __FUNCTION__, fname, ELAPSED_TIME(begin, CUR_TIME));
247 
248  return bOK;
249 }
250 
251 
252 bool Openholo::saveAsOhc(const char * fname)
253 {
254  bool bRet = true;
255  auto begin = CUR_TIME;
256 
257  std::string fullname = fname;
258  if (!checkExtension(fname, ".ohc")) fullname.append(".ohc");
259  OHC_encoder->setFileName(fullname.c_str());
260 
261  // Clear vector
263 
264  ohcHeader header;
265  OHC_encoder->getOHCheader(header);
266  auto wavelength_num = header.fieldInfo.wavlenNum;
267 
268  for (uint i = 0; i < wavelength_num; i++)
270 
271  if (!OHC_encoder->save())
272  {
273  bRet = false;
274  LOG("<FAILED> Saving ohc file: %s\n", fname);
275  }
276  LOG("%s => %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
277  return bRet;
278 }
279 
280 bool Openholo::loadAsOhc(const char * fname)
281 {
282  auto begin = CUR_TIME;
283 
284  std::string fullname = fname;
285  if (!checkExtension(fname, ".ohc")) fullname.append(".ohc");
286  OHC_decoder->setFileName(fullname.c_str());
287  if (!OHC_decoder->load())
288  {
289  LOG("<FAILED> Load ohc : %s\n", fname);
290  LOG("%.5lf (sec)\n", ELAPSED_TIME(begin, CUR_TIME));
291  return false;
292  }
296 
297  vector<Real> wavelengthArray;
298  OHC_decoder->getWavelength(wavelengthArray);
299  size_t nWave = wavelengthArray.size();
300  if (nWave < 1)
301  {
302  LOG("<FAILED> Do not load wavelength size.\n");
303  return false;
304  }
305 
306  context_.wave_length = new Real[nWave];
307  for (int i = 0; i < nWave; i++)
308  context_.wave_length[i] = wavelengthArray[i];
309 
311 
312  context_.k = (2 * M_PI) / context_.wave_length[0];
315 
316  LOG("%s => %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
317  return true;
318 }
319 
320 
321 uchar* Openholo::loadAsImg(const char * fname)
322 {
323  FILE *infile = fopen(fname, "rb");
324  if (infile == nullptr)
325  {
326  LOG("<FAILED> No such file.\n");
327  return nullptr;
328  }
329 
330  // BMP Header Information
331  fileheader hf;
333  size_t nRead = fread(&hf, sizeof(fileheader), 1, infile);
334  if (hf.signature[0] != 'B' || hf.signature[1] != 'M')
335  {
336  LOG("<FAILED> Not BMP file.\n");
337  fclose(infile);
338  return nullptr;
339  }
340 
341  nRead = fread(&hInfo, sizeof(bitmapinfoheader), 1, infile);
342  fseek(infile, hf.fileoffset_to_pixelarray, SEEK_SET);
343 
344  uint size = hInfo.imagesize != 0 ? hInfo.imagesize : (((hInfo.width * hInfo.bitsperpixel >> 3) + 3) & ~3) * hInfo.height;
345 
346  oph::uchar* img_tmp = new uchar[size];
347  nRead = fread(img_tmp, sizeof(uchar), size, infile);
348  fclose(infile);
349 
350  return img_tmp;
351 }
352 
353 bool Openholo::loadAsImgUpSideDown(const char * fname, uchar* dst)
354 {
355  FILE *infile = fopen(fname, "rb");
356 
357  if (infile == nullptr)
358  {
359  LOG("<FAILED> No such file.\n");
360  return false;
361  }
362 
363  // BMP Header Information
364  fileheader hf;
366  size_t nRead = fread(&hf, sizeof(fileheader), 1, infile);
367  if (hf.signature[0] != 'B' || hf.signature[1] != 'M')
368  {
369  LOG("<FAILED> Not BMP file.\n");
370  return false;
371  }
372 
373  nRead = fread(&hInfo, sizeof(bitmapinfoheader), 1, infile);
374  fseek(infile, hf.fileoffset_to_pixelarray, SEEK_SET);
375 
376  oph::uchar* img_tmp;
377  if (hInfo.imagesize == 0) {
378  img_tmp = new oph::uchar[hInfo.width*hInfo.height*(hInfo.bitsperpixel >> 3)];
379  nRead = fread(img_tmp, sizeof(oph::uchar), hInfo.width*hInfo.height*(hInfo.bitsperpixel >> 3), infile);
380  }
381  else {
382  img_tmp = new oph::uchar[hInfo.imagesize];
383  nRead = fread(img_tmp, sizeof(oph::uchar), hInfo.imagesize, infile);
384  }
385  fclose(infile);
386 
387  // data upside down
389  uint cRow = ((hInfo.width * bytesperpixel) + 3) & ~3;
390  uint cImg = hInfo.height * cRow;
391 
392  for (oph::uint k = 0; k < cImg; k++) {
393  uint r = k / cRow;
394  uint c = k % cRow;
395  ((oph::uchar*)dst)[(hInfo.height - r - 1) * cRow + c] = img_tmp[r * cRow + c];
396  }
397 
398  delete[] img_tmp;
399  return true;
400 }
401 
402 bool Openholo::getImgSize(int & w, int & h, int & bytesperpixel, const char * fname)
403 {
404  char szExtension[FILENAME_MAX] = { 0, };
405 
406  strcpy(szExtension, strrchr(fname, '.') + 1);
407 
408 #ifdef _MSC_VER
409  if (_stricmp(szExtension, "bmp")) { // not bmp
410 #elif __GNUC__
411  if (strcasecmp(szExtension, "bmp")) {
412 #endif
413  LOG("<FAILED> Not BMP file.\n");
414  return false;
415  }
416  // BMP
417  FILE *infile = fopen(fname, "rb");
418 
419  if (infile == nullptr) { LOG("<FAILED> Load image file.\n"); return false; }
420 
421  // BMP Header Information
424  size_t nRead = fread(&hf, sizeof(fileheader), 1, infile);
425  if (hf.signature[0] != 'B' || hf.signature[1] != 'M') return false;
426  nRead = fread(&hInfo, sizeof(bitmapinfoheader), 1, infile);
427  //if (hInfo.bitsperpixel != 8) { printf("Bad File Format!!"); return 0; }
428 
432  fclose(infile);
433 
434  return true;
435 }
436 
437 void Openholo::imgScaleBilinear(uchar* src, uchar* dst, int w, int h, int neww, int newh, int channels)
438 {
439  int channel = channels;
440  int nBytePerLine = ((w * channel) + 3) & ~3;
441  int nNewBytePerLine = ((neww * channel) + 3) & ~3;
442 #ifdef _OPENMP
443 #pragma omp parallel for firstprivate(nBytePerLine, nNewBytePerLine, w, h, neww, newh, channel)
444 #endif
445  for (int y = 0; y < newh; y++)
446  {
447  int nbppY = y * nNewBytePerLine;
448  for (int x = 0; x < neww; x++)
449  {
450  float gx = (x / (float)neww) * (w - 1);
451  float gy = (y / (float)newh) * (h - 1);
452 
453  int gxi = (int)gx;
454  int gyi = (int)gy;
455 
456  if (channel == 1) {
457  uint32_t a00, a01, a10, a11;
458 
459  a00 = src[gxi + 0 + gyi * nBytePerLine];
460  a01 = src[gxi + 1 + gyi * nBytePerLine];
461  a10 = src[gxi + 0 + (gyi + 1) * nBytePerLine];
462  a11 = src[gxi + 1 + (gyi + 1) * nBytePerLine];
463 
464  float dx = gx - gxi;
465  float dy = gy - gyi;
466 
467  float w1 = (1 - dx) * (1 - dy);
468  float w2 = dx * (1 - dy);
469  float w3 = (1 - dx) * dy;
470  float w4 = dx * dy;
471 
472  dst[x + y * neww] = int(a00 * w1 + a01 * w2 + a10 * w3 + a11 * w4);
473  }
474  else if (channel == 3) {
475  uint32_t b00[3], b01[3], b10[3], b11[3];
476  int srcX = gxi * channel;
477  int dstX = x * channel;
478 
479  b00[0] = src[srcX + 0 + gyi * nBytePerLine];
480  b00[1] = src[srcX + 1 + gyi * nBytePerLine];
481  b00[2] = src[srcX + 2 + gyi * nBytePerLine];
482 
483  b01[0] = src[srcX + 3 + gyi * nBytePerLine];
484  b01[1] = src[srcX + 4 + gyi * nBytePerLine];
485  b01[2] = src[srcX + 5 + gyi * nBytePerLine];
486 
487  b10[0] = src[srcX + 0 + (gyi + 1) * nBytePerLine];
488  b10[1] = src[srcX + 1 + (gyi + 1) * nBytePerLine];
489  b10[2] = src[srcX + 2 + (gyi + 1) * nBytePerLine];
490 
491  b11[0] = src[srcX + 3 + (gyi + 1) * nBytePerLine];
492  b11[1] = src[srcX + 4 + (gyi + 1) * nBytePerLine];
493  b11[2] = src[srcX + 5 + (gyi + 1) * nBytePerLine];
494 
495  float dx = gx - gxi;
496  float dy = gy - gyi;
497 
498  float w1 = (1 - dx) * (1 - dy);
499  float w2 = dx * (1 - dy);
500  float w3 = (1 - dx) * dy;
501  float w4 = dx * dy;
502 
503  dst[dstX + 0 + nbppY] = int(b00[0] * w1 + b01[0] * w2 + b10[0] * w3 + b11[0] * w4);
504  dst[dstX + 1 + nbppY] = int(b00[1] * w1 + b01[1] * w2 + b10[1] * w3 + b11[1] * w4);
505  dst[dstX + 2 + nbppY] = int(b00[2] * w1 + b01[2] * w2 + b10[2] * w3 + b11[2] * w4);
506  }
507  }
508  }
509 }
510 
511 void Openholo::convertToFormatGray8(unsigned char * src, unsigned char * dst, int w, int h, int bytesperpixel)
512 {
513  int idx = 0;
514  unsigned int r = 0, g = 0, b = 0;
515  int N = (((w * bytesperpixel) + 3) & ~3) * h;
516 
517  for (int i = 0; i < N; i++)
518  {
519  unsigned int blue = src[i + 0];
520  unsigned int green = src[i + 1];
521  unsigned int red = src[i + 2];
522  dst[idx++] = (blue + green + red) / 3;
523  i += bytesperpixel - 1;
524  }
525 }
526 
527 void Openholo::fft1(int n, Complex<Real>* in, int sign, uint flag)
528 {
529  pnx = n;
530  bool bIn = true;
531 
532  if (fft_in == nullptr)
533  fft_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * n);
534  if (fft_out == nullptr)
535  fft_out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * n);
536 
537  if (in == nullptr) {
538  in = new Complex<Real>[pnx];
539  fft_in = reinterpret_cast<fftw_complex*>(in);
540  bIn = false;
541  }
542 
543  fft_sign = sign;
544 
545  if (!bIn) delete[] in;
546 
547  if (sign == OPH_FORWARD)
548  plan_fwd = fftw_plan_dft_1d(n, fft_in, fft_out, sign, flag);
549  else if (sign == OPH_BACKWARD)
550  plan_bwd = fftw_plan_dft_1d(n, fft_in, fft_out, sign, flag);
551  else {
552  LOG("failed fftw : wrong sign");
553  fftFree();
554  return;
555  }
556 }
557 
558 
559 void Openholo::fft2(oph::ivec2 n, Complex<Real>* in, int sign, uint flag)
560 {
561  pnx = n[_X], pny = n[_Y];
562  int N = pnx * pny;
563 
564  if (fft_in == nullptr)
565  fft_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N);
566  if (fft_out == nullptr)
567  fft_out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N);
568 
569  if (in != nullptr)
570  {
571  fft_in = reinterpret_cast<fftw_complex*>(in);
572  }
573 
574  fft_sign = sign;
575 
576  if (sign == OPH_FORWARD)
577  plan_fwd = fftw_plan_dft_2d(pny, pnx, fft_in, fft_out, sign, flag);
578  else if (sign == OPH_BACKWARD)
579  plan_bwd = fftw_plan_dft_2d(pny, pnx, fft_in, fft_out, sign, flag);
580  else {
581  LOG("failed fftw : wrong sign");
582  fftFree();
583  return;
584  }
585 }
586 
587 void Openholo::fft3(oph::ivec3 n, Complex<Real>* in, int sign, uint flag)
588 {
589  pnx = n[_X], pny = n[_Y], pnz = n[_Z];
590  int size = pnx * pny * pnz;
591 
592  bool bIn = true;
593  if (fft_in == nullptr)
594  fft_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * size);
595  if (fft_out == nullptr)
596  fft_out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * size);
597 
598  if (!in) {
599  in = new Complex<Real>[size];
600  bIn = false;
601  }
602 
603  for (int i = 0; i < size; i++) {
604  fft_in[i][_RE] = in[i].real();
605  fft_in[i][_IM] = in[i].imag();
606  }
607 
608  fft_sign = sign;
609 
610  if (!bIn) delete[] in;
611 
612  if (sign == OPH_FORWARD)
613  plan_fwd = fftw_plan_dft_3d(pnz, pny, pnx, fft_in, fft_out, sign, flag);
614  else if (sign == OPH_BACKWARD)
615  plan_bwd = fftw_plan_dft_3d(pnz, pny, pnx, fft_in, fft_out, sign, flag);
616  else {
617  LOG("failed fftw : wrong sign");
618  fftFree();
619  return;
620  }
621 }
622 
623 void Openholo::fftExecute(Complex<Real>* out, bool bReverse)
624 {
625  if (fft_sign == OPH_FORWARD)
626  fftw_execute(plan_fwd);
627  else if (fft_sign == OPH_BACKWARD)
628  fftw_execute(plan_bwd);
629  else {
630  LOG("failed fftw : wrong sign");
631  out = nullptr;
632  fftFree();
633  return;
634  }
635 
636  int size = pnx * pny * pnz;
637 
638  if (!bReverse) {
639 #ifdef _OPENMP
640 #pragma omp parallel for
641 #endif
642  for (int i = 0; i < size; i++) {
643  out[i][_RE] = fft_out[i][_RE];
644  out[i][_IM] = fft_out[i][_IM];
645  }
646  }
647  else {
648 #ifdef _OPENMP
649 #pragma omp parallel for
650 #endif
651  for (int i = 0; i < size; i++) {
652  out[i][_RE] = fft_out[i][_RE] / size;
653  out[i][_IM] = fft_out[i][_IM] / size;
654  }
655  }
656 
657  fftFree();
658 }
659 
660 void Openholo::fftInit2D(ivec2 size, int sign, unsigned int flag)
661 {
662  int pnX = size[_X];
663  int pnY = size[_Y];
664  int N = pnX * pnY;
665 
666  if (fft_in == nullptr)
667  fft_in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N);
668  if (fft_out == nullptr)
669  fft_out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N);
670 
671  if (plan_fwd == nullptr)
672  plan_fwd = fftw_plan_dft_2d(pnY, pnX, fft_in, fft_out, sign, flag);
673  if (plan_bwd == nullptr)
674  plan_bwd = fftw_plan_dft_2d(pnY, pnX, fft_in, fft_out, sign, flag);
675 }
676 
677 void Openholo::fftFree(void)
678 {
679  if (plan_fwd) {
680  fftw_destroy_plan(plan_fwd);
681  plan_fwd = nullptr;
682  }
683  if (plan_bwd) {
684  fftw_destroy_plan(plan_bwd);
685  plan_bwd = nullptr;
686  }
687  fftw_free(fft_in);
688  fftw_free(fft_out);
689 
690  fft_in = nullptr;
691  fft_out = nullptr;
692 
693  pnx = 1;
694  pny = 1;
695  pnz = 1;
696 }
697 
698 void Openholo::fft2(Complex<Real>* src, Complex<Real>* dst, int nx, int ny, int type, bool bNormalized)
699 {
700  const int N = nx * ny;
701  fftw_complex *in, *out;
702  const bool bIn = fft_in == nullptr ? true : false;
703  const bool bOut = fft_out == nullptr ? true : false;
704 
705  if (bIn)
706  in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N);
707  else
708  in = fft_in;
709 
710  if (bOut)
711  out = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N);
712  else
713  out = fft_out;
714 
715  fftShift(nx, ny, src, reinterpret_cast<Complex<Real> *>(in));
716 
717  fftw_plan plan = nullptr;
718  if (!plan_fwd && !plan_bwd) {
719  plan = fftw_plan_dft_2d(ny, nx, in, out, type, OPH_ESTIMATE);
720  fftw_execute(plan);
721  }
722  else {
723  if (type == OPH_FORWARD)
724  fftw_execute_dft(plan_fwd, in, out);
725  else if (type == OPH_BACKWARD)
726  fftw_execute_dft(plan_bwd, in, out);
727  }
728 
729  if (bNormalized)
730  {
731 #pragma omp parallel for
732  for (int k = 0; k < N; k++) {
733  out[k][_RE] /= N;
734  out[k][_IM] /= N;
735  }
736  }
737  if (plan)
738  fftw_destroy_plan(plan);
739 
740  fftShift(nx, ny, reinterpret_cast<Complex<Real> *>(out), dst);
741 
742  if (bIn)
743  fftw_free(in);
744  if (bOut)
745  fftw_free(out);
746 }
747 
748 
749 void Openholo::fftShift(int nx, int ny, Complex<Real>* input, Complex<Real>* output)
750 {
751  int hnx = nx >> 1;
752  int hny = ny >> 1;
753 
754 #ifdef _OPENMP
755 #pragma omp parallel for firstprivate(hnx, hny)
756 #endif
757  for (int i = 0; i < nx; i++)
758  {
759  for (int j = 0; j < ny; j++)
760  {
761  int ti = i - hnx; if (ti < 0) ti += nx;
762  int tj = j - hny; if (tj < 0) tj += ny;
763 
764  output[ti + tj * nx] = input[i + j * nx];
765  }
766  }
767 
768 }
769 
770 void Openholo::setWaveNum(int nNum)
771 {
772  context_.waveNum = nNum;
773  if (context_.wave_length != nullptr) {
774  delete[] context_.wave_length;
775  context_.wave_length = nullptr;
776  }
777 
778  context_.wave_length = new Real[nNum];
779 }
780 
781 void Openholo::setMaxThreadNum(int num)
782 {
783 #ifdef _OPENMP
784  if (num > omp_get_max_threads())
785  omp_set_num_threads(omp_get_max_threads());
786  else
787  omp_set_num_threads(num);
788 #else
789  LOG("Not used openMP\n");
790 #endif
791 }
792 
794 {
795  int num_threads = 1;
796 #ifdef _OPENMP
797 #pragma omp parallel
798  {
799  num_threads = omp_get_num_threads();
800  }
801 #endif
802  return num_threads;
803 }
804 
805 void Openholo::ophFree(void)
806 {
807  ohcHeader header;
808  OHC_encoder->getOHCheader(header);
809  auto wavelength_num = header.fieldInfo.wavlenNum;
810  for (uint i = 0; i < wavelength_num; i++) {
811  if (complex_H[i]) {
812  delete[] complex_H[i];
813  complex_H[i] = nullptr;
814  }
815  }
816  if (complex_H) {
817  delete[] complex_H;
818  complex_H = nullptr;
819  }
820  if (context_.wave_length) {
821  delete[] context_.wave_length;
822  context_.wave_length = nullptr;
823  }
824  if (OHC_encoder) {
825  delete OHC_encoder;
826  OHC_encoder = nullptr;
827  }
828  if (OHC_decoder) {
829  delete OHC_decoder;
830  OHC_decoder = nullptr;
831  }
832 }
833 
uint32_t dibheadersize
Definition: struct.h:57
#define M_PI
Definition: define.h:52
#define OPH_FORWARD
Definition: define.h:66
virtual bool saveAsImg(const char *fname, uint8_t bitsperpixel, uchar *src, int width, int height)
Function for creating image files.
Definition: Openholo.cpp:135
size_t nRead
Definition: Openholo.cpp:424
Real k
Definition: Openholo.h:103
w
Definition: Openholo.cpp:429
Definition: Base.h:63
void fftFree(void)
Resource release method.
Definition: Openholo.cpp:677
bytesperpixel
Definition: Openholo.cpp:431
void setMaxThreadNum(int num)
Function for setting the max thread num.
Definition: Openholo.cpp:781
int getMaxThreadNum()
Function for getting the max thread num.
Definition: Openholo.cpp:793
unsigned char uchar
Definition: typedef.h:64
void fftShift(int nx, int ny, Complex< Real > *input, Complex< Real > *output)
Swap the top-left quadrant of data with the bottom-right , and the top-right quadrant with the bottom...
Definition: Openholo.cpp:749
bool Flip(FLIP mode, const uint8_t *src, uint8_t *dst, const uint32_t w, const uint32_t h, const uint8_t ch)
Flip the bitmap.
Definition: ImgControl.cpp:203
bool Rotate(const double rotate, const uint8_t *src, uint8_t *dst, const uint32_t w, const uint32_t h, const uint32_t neww, const uint32_t newh, const uint8_t ch)
Rotate the bitmap.
Definition: ImgControl.cpp:136
ohcFieldInfoHeader fieldInfo
void fft3(ivec3 n, Complex< Real > *in, int sign=OPH_FORWARD, uint flag=OPH_ESTIMATE)
Functions for performing fftw 3-dimension operations inside Openholo.
Definition: Openholo.cpp:587
vec2 ss
Definition: Openholo.h:104
FILE * infile
Definition: Openholo.cpp:417
return true
Definition: Openholo.cpp:434
float Real
Definition: typedef.h:55
bool checkExtension(const char *fname, const char *ext)
Functions for extension checking.
Definition: Openholo.cpp:86
structure for 2-dimensional integer vector and its arithmetic.
Definition: ivec.h:66
#define _IM
Definition: complex.h:58
def k(wvl)
Definition: Depthmap.py:16
h
Definition: Openholo.cpp:430
void setWaveNum(int num)
Function for setting the wave number.
Definition: Openholo.cpp:770
bool rotate
Definition: Openholo.h:124
fclose(infile)
ImageConfig imgCfg
Definition: Openholo.h:487
vec2 pixel_pitch
Definition: Openholo.h:101
uint32_t imagesize
Definition: struct.h:63
void getComplexFieldData(OphComplexField &cmplx_field, uint wavelen_idx)
Definition: ImgCodecOhc.h:74
#define _X
Definition: define.h:92
uint8_t signature[2]
Definition: struct.h:51
Definition: struct.h:69
Definition: struct.h:75
virtual void releaseFldData()
void addComplexFieldData(const OphComplexField &data)
bool separateColor(int idx, int width, int height, uchar *src, uchar *dst)
Function for generate each grayscale image from RGB image.
Definition: Openholo.cpp:119
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
bool getImgSize(int &w, int &h, int &bytesperpixel, const char *fname)
Function for getting the image size.
Definition: Openholo.cpp:402
uint16_t bitsperpixel
Definition: struct.h:61
#define OPH_PLANES
Definition: define.h:163
#define _RE
Definition: complex.h:55
void fftExecute(Complex< Real > *out, bool bReverse=false)
Execution functions to be called after fft1, fft2, and fft3.
Definition: Openholo.cpp:623
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
void convertToFormatGray8(uchar *src, uchar *dst, int w, int h, int bytesperpixel)
Function for convert image format to gray8.
Definition: Openholo.cpp:511
ImgDecoderOhc * OHC_decoder
Definition: Openholo.h:495
virtual ~Openholo(void)=0
Destructor.
Definition: Openholo.cpp:73
void fftInit2D(ivec2 size, int sign, unsigned int flag)
initialize method for 2D FFT
Definition: Openholo.cpp:660
uint waveNum
Definition: Openholo.h:105
uint32_t ypixelpermeter
Definition: struct.h:64
FLIP
Definition: ImgEncoder.h:6
uint32_t numcolorspallette
Definition: struct.h:66
bool setFileName(const std::string &_fname)
Definition: ImgCodecOhc.cpp:92
ivec2 pixel_number
Definition: Openholo.h:99
virtual bool loadAsOhc(const char *fname)
Function to read OHC file.
Definition: Openholo.cpp:280
#define _Y
Definition: define.h:96
uint32_t filesize
Definition: struct.h:52
Openholo(void)
Constructor.
Definition: Openholo.cpp:53
uint32_t fileoffset_to_pixelarray
Definition: struct.h:54
uint32_t width
Definition: struct.h:58
virtual uchar * loadAsImg(const char *fname)
Function for loading image files.
Definition: Openholo.cpp:321
#define OPH_COMPRESSION
Definition: define.h:164
bitmapinfoheader hInfo
Definition: Openholo.cpp:423
uint32_t height
Definition: struct.h:59
virtual bool saveAsOhc(const char *fname)
Function to write OHC file
Definition: Openholo.cpp:252
uint16_t planes
Definition: struct.h:60
structure for 3-dimensional integer vector and its arithmetic.
Definition: ivec.h:386
Complex< Real > ** complex_H
Definition: Openholo.h:489
#define OPH_ESTIMATE
Definition: define.h:76
bitmapinfoheader _bitmapinfoheader
Definition: struct.h:77
#define _Z
Definition: define.h:100
fileheader hf
Definition: Openholo.cpp:422
void getOHCheader(oph::ohcHeader &_Header)
#define ELAPSED_TIME(x, y)
Definition: function.h:59
ImgEncoderOhc * OHC_encoder
OHC file format Variables for read and write.
Definition: Openholo.h:494
OphConfig context_
Definition: Openholo.h:485
#define OPH_BACKWARD
Definition: define.h:67
fileheader _fileheader
Definition: struct.h:76
Real * wave_length
Definition: Openholo.h:106
void fft1(int n, Complex< Real > *in, int sign=OPH_FORWARD, uint flag=OPH_ESTIMATE)
Functions for performing fftw 1-dimension operations inside Openholo.
Definition: Openholo.cpp:527
bool loadAsImgUpSideDown(const char *fname, uchar *dst)
Function for loading image files | Output image data upside down.
Definition: Openholo.cpp:353
void getWavelength(std::vector< double_t > &wavlen_array)
uint32_t compression
Definition: struct.h:62
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
#define CUR_TIME
Definition: function.h:58
virtual void ophFree(void)
Pure virtual function for override in child classes.
Definition: Openholo.cpp:805
uint32_t xpixelpermeter
Definition: struct.h:65