Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
utils.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
25 #include "utils.h"
26 #include "stl_utils.h"
27 #include "hugin_version.h"
28 #include "hugin_config.h"
29 
30 #ifdef _WIN32
31  #define NOMINMAX
32  #include <sys/utime.h>
33  #include <shlobj.h>
34 #else
35  #include <sys/time.h>
36  #include <cstdlib>
37  #include <unistd.h>
38  #include <sys/types.h>
39  #include <pwd.h>
40 #endif
41 #include <time.h>
42 #include <fstream>
43 #include <stdio.h>
44 #include <cstdio>
45 #ifdef _WIN32
46 #define NOMINMAX
47 #include <windows.h>
48 #else
49 #include <hugin_config.h>
50 #endif
51 #include <algorithm>
52 #include <filesystem>
53 #include <lcms2.h>
54 
55 #ifdef __APPLE__
56 #include <mach-o/dyld.h> /* _NSGetExecutablePath */
57 #include <limits.h> /* PATH_MAX */
58 #include <libgen.h> /* dirname */
59 #endif
60 
61 #if defined HAVE_EPOXY && HAVE_EPOXY
62 #include <epoxy/gl.h>
63 #ifdef _WIN32
64 #include <epoxy/wgl.h>
65 #endif
66 #else
67 #include <GL/glew.h>
68 #ifdef _WIN32
69 #include <GL/wglew.h>
70 #endif
71 #endif
72 #if defined __APPLE__
73  #include <GLUT/glut.h>
74 #endif
75 
76 namespace hugin_utils {
77 
78 #ifdef UNIX_LIKE
79 std::string GetCurrentTimeString()
80 {
81  char tmp[100];
82  struct tm t;
83  struct timeval tv;
84  gettimeofday(&tv,NULL);
85  localtime_r((time_t*)&tv.tv_sec, &t); // is the casting safe?
86  strftime(tmp,99,"%H:%M:%S",&t);
87  sprintf(tmp+8,".%06ld", (long)tv.tv_usec);
88  return tmp;
89 }
90 #else
91 std::string GetCurrentTimeString()
92 {
93  // FIXME implement for Win
94  return "";
95 }
96 #endif
97 
98 
99 std::string getExtension(const std::string & basename2)
100 {
101  std::string::size_type idx = basename2.rfind('.');
102  // check if the dot is not followed by a \ or a /
103  // to avoid cutting pathes.
104  if (idx == std::string::npos) {
105  // no dot found
106  return std::string("");
107  }
108 #ifdef UNIX_LIKE
109  // check for slashes after dot
110  std::string::size_type slashidx = basename2.find('/', idx);
111  if ( slashidx == std::string::npos)
112  {
113  return basename2.substr(idx+1);
114  } else {
115  return std::string("");
116  }
117 #else
118  // check for slashes after dot
119  std::string::size_type slashidx = basename2.find('/', idx);
120  std::string::size_type backslashidx = basename2.find('\\', idx);
121  if ( slashidx == std::string::npos && backslashidx == std::string::npos)
122  {
123  return basename2.substr(idx+1);
124  } else {
125  return std::string("");
126  }
127 #endif
128 }
129 
130 std::string stripExtension(const std::string & basename2)
131 {
132  std::string::size_type idx = basename2.rfind('.');
133  // check if the dot is not followed by a \ or a /
134  // to avoid cutting pathes.
135  if (idx == std::string::npos) {
136  // no dot found
137  return basename2;
138  }
139 #ifdef UNIX_LIKE
140  std::string::size_type slashidx = basename2.find('/', idx);
141  if ( slashidx == std::string::npos)
142  {
143  return basename2.substr(0, idx);
144  } else {
145  return basename2;
146  }
147 #else
148  // check for slashes after dot
149  std::string::size_type slashidx = basename2.find('/', idx);
150  std::string::size_type backslashidx = basename2.find('\\', idx);
151  if ( slashidx == std::string::npos && backslashidx == std::string::npos)
152  {
153  return basename2.substr(0, idx);
154  } else {
155  return basename2;
156  }
157 #endif
158 }
159 
160 std::string stripPath(const std::string & filename)
161 {
162 #ifdef UNIX_LIKE
163  std::string::size_type idx = filename.rfind('/');
164 #else
165  std::string::size_type idx1 = filename.rfind('\\');
166  std::string::size_type idx2 = filename.rfind('/');
167  std::string::size_type idx;
168  if (idx1 == std::string::npos) {
169  idx = idx2;
170  } else if (idx2 == std::string::npos) {
171  idx = idx1;
172  } else {
173  idx = std::max(idx1, idx2);
174  }
175 #endif
176  if (idx != std::string::npos) {
177 // DEBUG_DEBUG("returning substring: " << filename.substr(idx + 1));
178  return filename.substr(idx + 1);
179  } else {
180  return filename;
181  }
182 }
183 
184 std::string getPathPrefix(const std::string & filename)
185 {
186 #ifdef UNIX_LIKE
187  std::string::size_type idx = filename.rfind('/');
188 #else
189  std::string::size_type idx1 = filename.rfind('\\');
190  std::string::size_type idx2 = filename.rfind('/');
191  std::string::size_type idx;
192  if (idx1 == std::string::npos) {
193  idx = idx2;
194  } else if (idx2 == std::string::npos) {
195  idx = idx1;
196  } else {
197  idx = std::max(idx1, idx2);
198  }
199 #endif
200  if (idx != std::string::npos) {
201 // DEBUG_DEBUG("returning substring: " << filename.substr(idx + 1));
202  return filename.substr(0, idx+1);
203  } else {
204  return "";
205  }
206 }
207 
208 std::string StrTrim(const std::string& str)
209 {
210  std::string s(str);
211  std::string::size_type pos = s.find_last_not_of(" \t");
212  if (pos != std::string::npos)
213  {
214  s.erase(pos + 1);
215  pos = s.find_first_not_of(" \t");
216  if (pos != std::string::npos)
217  {
218  s.erase(0, pos);
219  };
220  }
221  else
222  {
223  s.erase(s.begin(), s.end());
224  };
225  return s;
226 }
227 
228 std::string doubleToString(double d, int digits)
229 {
230  char fmt[10];
231  if (digits < 0) {
232  strcpy(fmt,"%f");
233  } else {
234  // max. 16 digits to prevent overflow
235  std::sprintf(fmt, "%%.%df", std::min(digits, 16));
236  }
237  char c[1024];
238  c[1023] = 0;
239 #ifdef _MSC_VER
240  _snprintf (c, 1023, fmt, d);
241 #else
242  snprintf (c, 1023, fmt, d);
243 #endif
244 
245  std::string number (c);
246 
247  int l = (int)number.length()-1;
248 
249  while ( l != 0 && number[l] == '0' ) {
250  number.erase (l);
251  l--;
252  }
253  if ( number[l] == ',' ) {
254  number.erase (l);
255  l--;
256  }
257  if ( number[l] == '.' ) {
258  number.erase (l);
259  l--;
260  }
261  return number;
262 }
263 
264 bool stringToInt(const std::string& s, int& val)
265 {
266  if (StrTrim(s) == "0")
267  {
268  val = 0;
269  return true;
270  };
271  int x = atoi(s.c_str());
272  if (x != 0)
273  {
274  val = x;
275  return true;
276  };
277  return false;
278 };
279 
280 bool stringToUInt(const std::string&s, unsigned int& val)
281 {
282  int x;
283  if (stringToInt(s, x))
284  {
285  if (x >= 0)
286  {
287  val = static_cast<unsigned int>(x);
288  return true;
289  };
290  };
291  return false;
292 };
293 
294 std::vector<std::string> SplitString(const std::string& s, const std::string& sep)
295 {
296  std::vector<std::string> result;
297  std::size_t pos = s.find_first_of(sep, 0);
298  std::size_t pos2 = 0;
299  while (pos != std::string::npos)
300  {
301  if (pos - pos2 > 0)
302  {
303  std::string t(s.substr(pos2, pos - pos2));
304  t=StrTrim(t);
305  if (!t.empty())
306  {
307  result.push_back(t);
308  };
309  };
310  pos2 = pos + 1;
311  pos = s.find_first_of(sep, pos2);
312  }
313  if (pos2 < s.length())
314  {
315  std::string t(s.substr(pos2));
316  t = StrTrim(t);
317  if (!t.empty())
318  {
319  result.push_back(t);
320  };
321  };
322  return result;
323 };
324 
325 void ReplaceAll(std::string& s, const std::string& oldChar, char newChar)
326 {
327  std::size_t found = s.find_first_of(oldChar);
328  while (found != std::string::npos)
329  {
330  s[found] = newChar;
331  found = s.find_first_of(oldChar, found + 1);
332  };
333 };
334 
335 bool StringContainsCaseInsensitive(const std::string& s1, const std::string& s2)
336 {
337  const auto it = std::search(s1.begin(), s1.end(), s2.begin(), s2.end(), [](const char a, const char b)->bool { return std::tolower(a) == std::tolower(b); });
338  return it != s1.end();
339 }
340 
341  void ControlPointErrorColour(const double cperr,
342  double &r,double &g, double &b)
343  {
344  //Colour change points
345 #define XP1 5.0f
346 #define XP2 10.0f
347 
348  if ( cperr<= XP1)
349  {
350  //low error
351  r = cperr / XP1;
352  g = 0.75;
353  }
354  else
355  {
356  r = 1.0;
357  g = 0.75 * ((1.0 - std::min<double>(cperr - XP1, XP2 - XP1) / (XP2 - XP1)));
358  }
359  b = 0.0;
360  }
361 
362 bool FileExists(const std::string& filename)
363 {
364  std::ifstream ifile(filename.c_str());
365  return !ifile.fail();
366 }
367 
368 std::string GetAbsoluteFilename(const std::string& filename)
369 {
370 #ifdef _WIN32
371  char fullpath[_MAX_PATH];
372  _fullpath(fullpath,filename.c_str(),_MAX_PATH);
373  return std::string(fullpath);
374 #else
375  //realpath works only with existing files
376  //so as work around we create the file first, call then realpath
377  //and delete the temp file
379  bool tempFileCreated=false;
380  if(!FileExists(filename))
381  {
382  tempFileCreated=true;
383  std::ofstream os(filename.c_str());
384  os.close();
385  };
386  char *real_path = realpath(filename.c_str(), NULL);
387  std::string absPath;
388  if(real_path!=NULL)
389  {
390  absPath=std::string(real_path);
391  free(real_path);
392  }
393  else
394  {
395  absPath=filename;
396  };
397  if(tempFileCreated)
398  {
399  remove(filename.c_str());
400  };
401  return absPath;
402 #endif
403 };
404 
405 bool IsFileTypeSupported(const std::string& filename)
406 {
407  const std::string extension = getExtension(filename);
408  return (vigra::impexListExtensions().find(extension) != std::string::npos);
409 };
410 
411 void EnforceExtension(std::string& filename, const std::string& defaultExtension)
412 {
413  const std::string extension = getExtension(filename);
414  if (extension.empty())
415  {
416  filename = stripExtension(filename) + "." + defaultExtension;
417  };
418 }
419 
420 std::string GetOutputFilename(const std::string& out, const std::string& in, const std::string& suffix)
421 {
422  if (out.empty())
423  {
424  const std::string extension = getExtension(in);
425  if (extension.empty())
426  {
427  return in + "_" + suffix;
428  }
429  else
430  {
431  return in.substr(0, in.length() - extension.length() - 1).append("_" + suffix + "." + extension);
432  };
433  }
434  else
435  {
436  return out;
437  };
438 }
439 
440 
441 std::string GetDataDir()
442 {
443 #ifdef _WIN32
444  char buffer[MAX_PATH];//always use MAX_PATH for filepaths
445  GetModuleFileName(NULL,buffer,sizeof(buffer));
446  std::filesystem::path data_path(buffer);
447  data_path.remove_filename();
448  if (data_path.has_parent_path())
449  {
450  return std::filesystem::absolute(data_path.parent_path() / ".." / "share" / "hugin" / "data").string() + "\\";
451  };
452  return std::string();
453 #elif defined MAC_SELF_CONTAINED_BUNDLE
454  char path[PATH_MAX + 1];
455  uint32_t size = sizeof(path);
456  std::string data_path("");
457  if (_NSGetExecutablePath(path, &size) == 0)
458  {
459  data_path=dirname(path);
460  data_path.append("/../Resources/xrc/");
461  }
462  return data_path;
463 #elif defined UNIX_SELF_CONTAINED_BUNDLE
464  std::filesystem::path data_path = std::filesystem::read_symlink("/proc/self/exe");
465  data_path.remove_filename();
466  if (data_path.has_parent_path())
467  {
468  return (data_path.parent_path() / "share/hugin/data").string() + "/";
469  };
470  return std::string();
471 #else
472  return std::string(INSTALL_DATA_DIR);
473 #endif
474 };
475 
476 #ifndef _WIN32
477 std::string GetHomeDir()
478 {
479  char *homedir = getenv("HOME");
480  struct passwd *pw;
481  if (homedir == NULL)
482  {
483  pw = getpwuid(getuid());
484  if (pw != NULL)
485  {
486  homedir = pw->pw_dir;
487  };
488  };
489  if (homedir == NULL)
490  {
491  return std::string();
492  };
493  return std::string(homedir);
494 }
495 #endif
496 
497 std::string GetUserAppDataDir()
498 {
499  std::filesystem::path path;
500 #ifdef _WIN32
501  char fullpath[_MAX_PATH];
502  if(SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, fullpath)!=S_OK)
503  {
504  return std::string();
505  };
506  path = std::filesystem::path(fullpath);
507  path /= "hugin";
508 #else
509  char *xdgDataDir = getenv("XDG_DATA_HOME");
510  if (xdgDataDir == NULL || strlen(xdgDataDir) == 0)
511  {
512  // no XDG_DATA_HOME enviroment variable set or empty variable
513  // use $HOME/.local/share instead
514  const std::string homeDir = GetHomeDir();
515  if (homeDir.empty())
516  {
517  return std::string();
518  };
519  path = std::filesystem::path(homeDir);
520  path /= ".local/share/hugin";
521  }
522  else
523  {
524  // XDG_DATA_HOME set, use hugindata sub directory
525  path = std::filesystem::path(xdgDataDir);
526  path /= "hugin";
527  };
528 #endif
529  if (!std::filesystem::exists(path))
530  {
531  if (!std::filesystem::create_directories(path))
532  {
533  std::cerr << "ERROR: Could not create destination directory: " << path.string() << std::endl
534  << "Maybe you have not sufficient rights to create this directory." << std::endl;
535  return std::string();
536  };
537  };
538  return path.string();
539 };
540 
541 // initialization and wrapup of GPU for GPU remapping
542 #ifdef _WIN32
543 struct ContextSettings
544 {
545  HWND window;
546  HDC dc;
547  HGLRC renderingContext;
548 
550  {
551  window = NULL;
552  dc = NULL;
553  renderingContext = NULL;
554  }
555 };
556 static ContextSettings context;
557 
558 // create context, return false if failed
559 bool CreateContext(int *argcp, char **argv)
560 {
561  WNDCLASS windowClass;
562  /* register window class */
563  ZeroMemory(&windowClass, sizeof(WNDCLASS));
564  windowClass.hInstance = GetModuleHandle(NULL);
565  windowClass.lpfnWndProc = DefWindowProc;
566  windowClass.lpszClassName = "Hugin";
567  if (RegisterClass(&windowClass) == 0)
568  {
569  return false;
570  };
571  /* create window */
572  context.window = CreateWindow("Hugin", "Hugin", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
573  CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL);
574  if (context.window == NULL)
575  {
576  return false;
577  };
578  /* get the device context */
579  context.dc = GetDC(context.window);
580  if (context.dc == NULL)
581  {
582  return false;
583  };
584  /* find pixel format */
585  PIXELFORMATDESCRIPTOR pixelFormatDesc;
586  ZeroMemory(&pixelFormatDesc, sizeof(PIXELFORMATDESCRIPTOR));
587  pixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
588  pixelFormatDesc.nVersion = 1;
589  pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
590  int pixelFormat = ChoosePixelFormat(context.dc, &pixelFormatDesc);
591  if (pixelFormat == 0)
592  {
593  return false;
594  }
595  /* set the pixel format for the dc */
596  if (SetPixelFormat(context.dc, pixelFormat, &pixelFormatDesc) == FALSE)
597  {
598  return false;
599  };
600  /* create rendering context */
601  context.renderingContext = wglCreateContext(context.dc);
602  if (context.renderingContext == NULL)
603  {
604  return false;
605  };
606  if (wglMakeCurrent(context.dc, context.renderingContext) == FALSE)
607  {
608  return false;
609  };
610 #if defined HAVE_EPOXY && HAVE_EPOXY
611  epoxy_handle_external_wglMakeCurrent();
612 #endif
613  return true;
614 }
615 
616 void DestroyContext()
617 {
618  if (context.renderingContext != NULL)
619  {
620  wglMakeCurrent(NULL, NULL);
621 #if defined HAVE_EPOXY && HAVE_EPOXY
622  epoxy_handle_external_wglMakeCurrent();
623 #endif
624  wglDeleteContext(context.renderingContext);
625  }
626  if (context.window != NULL && context.dc != NULL)
627  {
628  ReleaseDC(context.window, context.dc);
629  };
630  if (context.window != NULL)
631  {
632  DestroyWindow(context.window);
633  };
634  UnregisterClass("Hugin", GetModuleHandle(NULL));
635 }
636 
637 #elif defined __APPLE__
638 static GLuint GlutWindowHandle;
639 bool CreateContext(int *argcp, char **argv)
640 {
641  // GLUT changes the working directory to the ressource path of the bundle
642  // so we store the old working directory and restore it at the end
643  char workingDir[FILENAME_MAX];
644  getcwd(workingDir, FILENAME_MAX);
645  glutInit(argcp, argv);
646  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_ALPHA);
647  GlutWindowHandle = glutCreateWindow("Hugin");
648  // restore working dir, as GLUT changes it the ressource path
649  chdir(workingDir);
650  return true;
651 }
652 
653 void DestroyContext()
654 {
655  glutDestroyWindow(GlutWindowHandle);
656 }
657 
658 #else
659 #if defined HAVE_EGL && HAVE_EGL
660 #if defined HAVE_EPOXY && HAVE_EPOXY
661 #include <epoxy/egl.h>
662 #else
663 #include <EGL/egl.h>
664 #endif
665 
666 struct ContextSettings
667 {
668  EGLDisplay m_display;
669  EGLContext m_context;
670 };
671 
672 static ContextSettings context;
673 
674 static const EGLint configAttribs[] = {
675  EGL_BLUE_SIZE, 8,
676  EGL_GREEN_SIZE, 8,
677  EGL_RED_SIZE, 8,
678  EGL_ALPHA_SIZE, 8,
679  EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
680  EGL_CONFORMANT, EGL_OPENGL_BIT,
681  EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
682  EGL_NONE
683 };
684 
685 bool CreateContext(int *argcp, char **argv)
686 {
687  // get display connection
688  context.m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
689  if (context.m_display == EGL_NO_DISPLAY)
690  {
691  std::cerr << "Could not connect to EGL_DEFAULT_DISPLAY" << std::endl;
692  return false;
693  };
694  // initialize egl
695  EGLint major, minor;
696  if (eglInitialize(context.m_display, &major, &minor) != EGL_TRUE)
697  {
698  std::cerr << "Could not initialize EGL" << std::endl
699  << "Error: 0x" << std::hex << eglGetError() << std::endl;
700  return false;
701  };
702  std::cout << "Init OpenGL ES " << major << "." << minor << std::endl;
703  std::cout << "Client API: " << eglQueryString(context.m_display, EGL_CLIENT_APIS) << std::endl
704  << "Vendor: " << eglQueryString(context.m_display, EGL_VENDOR) << std::endl
705  << "Version: " << eglQueryString(context.m_display, EGL_VERSION) << std::endl
706  << "EGL Extensions: " << eglQueryString(context.m_display, EGL_EXTENSIONS) << std::endl;
707  // bind OpenGL API (not OpenGL ES)
708  if (!eglBindAPI(EGL_OPENGL_API))
709  {
710  std::cerr << "Could not bind OpenGL API" << std::endl
711  << "Error: 0x" << std::hex << eglGetError() << std::endl;
712  return false;
713  };
714  // choose config
715  EGLint numConfigs;
716  EGLConfig egl_config;
717  if (eglChooseConfig(context.m_display, configAttribs, &egl_config, 1, &numConfigs) != EGL_TRUE)
718  {
719  std::cerr << "Cound not set egl config" << std::endl
720  << "Error: 0x" << std::hex << eglGetError() << std::endl;
721  return false;
722  };
723  // create surface
724  // create context and make it current
725  context.m_context = eglCreateContext(context.m_display, egl_config, EGL_NO_CONTEXT, NULL);
726  if (context.m_context == EGL_NO_CONTEXT)
727  {
728  std::cerr << "Cound not create context" << std::endl
729  << "Error: 0x" << std::hex << eglGetError() << std::endl;
730  return false;
731  };
732  if (eglMakeCurrent(context.m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, context.m_context) != EGL_TRUE)
733  {
734  std::cerr << "Could not make current context" << std::endl
735  << "Error: 0x" << std::hex << eglGetError() << std::endl;
736  return false;
737  };
738  return true;
739 }
740 
741 void DestroyContext()
742 {
743  // terminate egl at end
744  eglTerminate(context.m_display);
745 };
746 
747 #else
748 #include <X11/Xlib.h>
749 #include <X11/Xutil.h>
750 #if defined HAVE_EPOXY && HAVE_EPOXY
751 #include <epoxy/glx.h>
752 #else
753 #include <GL/glx.h>
754 #endif
755 
757 {
758  Display* display;
759  XVisualInfo* visualInfo;
760  GLXContext context;
761  Window window;
762  Colormap colormap;
763 
765  {
766  display=NULL;
767  visualInfo=NULL;
768  context=NULL;
769  window=0;
770  colormap=0;
771  };
772 };
773 
775 
776 bool CreateContext(int *argcp, char **argv)
777 {
778  /* open display */
779  context.display = XOpenDisplay(NULL);
780  if (context.display == NULL)
781  {
782  return false;
783  };
784  /* query for glx */
785  int erb, evb;
786  if (!glXQueryExtension(context.display, &erb, &evb))
787  {
788  return false;
789  };
790  /* choose visual */
791  int attrib[] = { GLX_RGBA, None };
792  context.visualInfo = glXChooseVisual(context.display, DefaultScreen(context.display), attrib);
793  if (context.visualInfo == NULL)
794  {
795  return false;
796  };
797  /* create context */
798  context.context = glXCreateContext(context.display, context.visualInfo, None, True);
799  if (context.context == NULL)
800  {
801  return false;
802  };
803  /* create window */
804  context.colormap = XCreateColormap(context.display, RootWindow(context.display, context.visualInfo->screen), context.visualInfo->visual, AllocNone);
805  XSetWindowAttributes swa;
806  swa.border_pixel = 0;
807  swa.colormap = context.colormap;
808  context.window = XCreateWindow(context.display, RootWindow(context.display, context.visualInfo->screen),
809  0, 0, 1, 1, 0, context.visualInfo->depth, InputOutput, context.visualInfo->visual,
810  CWBorderPixel | CWColormap, &swa);
811  /* make context current */
812  if (!glXMakeCurrent(context.display, context.window, context.context))
813  {
814  return false;
815  };
816  return true;
817 };
818 
820 {
821  if (context.display != NULL && context.context != NULL)
822  {
823  glXDestroyContext(context.display, context.context);
824  }
825  if (context.display != NULL && context.window != 0)
826  {
827  XDestroyWindow(context.display, context.window);
828  };
829  if (context.display != NULL && context.colormap != 0)
830  {
831  XFreeColormap(context.display, context.colormap);
832  };
833  if (context.visualInfo != NULL)
834  {
835  XFree(context.visualInfo);
836  };
837  if (context.display != NULL)
838  {
839  XCloseDisplay(context.display);
840  };
841 };
842 #endif
843 #endif
844 
845 bool initGPU(int *argcp, char **argv)
846 {
847  if (!CreateContext(argcp, argv))
848  {
849  return false;
850  };
851  std::cout << hugin_utils::stripPath(argv[0]) << ": using graphics card: " << glGetString(GL_VENDOR) << " " << glGetString(GL_RENDERER) << std::endl;
852 #if defined HAVE_EPOXY && HAVE_EPOXY
853  const GLboolean has_arb_fragment_shader = epoxy_has_gl_extension("GL_ARB_fragment_shader");
854  const GLboolean has_arb_vertex_shader = epoxy_has_gl_extension("GL_ARB_vertex_shader");
855  const GLboolean has_arb_shader_objects = epoxy_has_gl_extension("GL_ARB_shader_objects");
856  const GLboolean has_arb_shading_language = epoxy_has_gl_extension("GL_ARB_shading_language_100");
857  const GLboolean has_ext_framebuffer = epoxy_has_gl_extension("GL_EXT_framebuffer_object");
858  const GLboolean has_arb_texture_rectangle = epoxy_has_gl_extension("GL_ARB_texture_rectangle");
859  const GLboolean has_arb_texture_border_clamp = epoxy_has_gl_extension("GL_ARB_texture_border_clamp");
860  const GLboolean has_arb_texture_float = epoxy_has_gl_extension("GL_ARB_texture_float");
861 #else
862  int err = glewInit();
863  if (err != GLEW_OK)
864  {
865  std::cerr << argv[0] << ": an error occurred while setting up the GPU:" << std::endl;
866  std::cerr << glewGetErrorString(err) << std::endl;
867  std::cerr << argv[0] << ": Switching to CPU calculation." << std::endl;
868  DestroyContext();
869  return false;
870  }
871 
872  const GLboolean has_arb_fragment_shader = glewGetExtension("GL_ARB_fragment_shader");
873  const GLboolean has_arb_vertex_shader = glewGetExtension("GL_ARB_vertex_shader");
874  const GLboolean has_arb_shader_objects = glewGetExtension("GL_ARB_shader_objects");
875  const GLboolean has_arb_shading_language = glewGetExtension("GL_ARB_shading_language_100");
876  const GLboolean has_ext_framebuffer = glewGetExtension("GL_EXT_framebuffer_object");
877  const GLboolean has_arb_texture_rectangle = glewGetExtension("GL_ARB_texture_rectangle");
878  const GLboolean has_arb_texture_border_clamp = glewGetExtension("GL_ARB_texture_border_clamp");
879  const GLboolean has_arb_texture_float = glewGetExtension("GL_ARB_texture_float");
880 #endif
881 
882  if (!(has_arb_fragment_shader && has_arb_vertex_shader && has_arb_shader_objects && has_arb_shading_language && has_ext_framebuffer && has_arb_texture_rectangle && has_arb_texture_border_clamp && has_arb_texture_float)) {
883  const char * msg[] = {"false", "true"};
884  std::cerr << argv[0] << ": extension GL_ARB_fragment_shader = " << msg[has_arb_fragment_shader] << std::endl;
885  std::cerr << argv[0] << ": extension GL_ARB_vertex_shader = " << msg[has_arb_vertex_shader] << std::endl;
886  std::cerr << argv[0] << ": extension GL_ARB_shader_objects = " << msg[has_arb_shader_objects] << std::endl;
887  std::cerr << argv[0] << ": extension GL_ARB_shading_language_100 = " << msg[has_arb_shading_language] << std::endl;
888  std::cerr << argv[0] << ": extension GL_EXT_framebuffer_object = " << msg[has_ext_framebuffer] << std::endl;
889  std::cerr << argv[0] << ": extension GL_ARB_texture_rectangle = " << msg[has_arb_texture_rectangle] << std::endl;
890  std::cerr << argv[0] << ": extension GL_ARB_texture_border_clamp = " << msg[has_arb_texture_border_clamp] << std::endl;
891  std::cerr << argv[0] << ": extension GL_ARB_texture_float = " << msg[has_arb_texture_float] << std::endl;
892  std::cerr << argv[0] << ": This graphics system lacks the necessary extensions for -g." << std::endl;
893  std::cerr << argv[0] << ": Switching to CPU calculation." << std::endl;
894  DestroyContext();
895  return false;
896  }
897 
898  return true;
899 }
900 
901 bool wrapupGPU()
902 {
903  DestroyContext();
904  return true;
905 }
906 
907 std::string GetHuginVersion()
908 {
909  return std::string(DISPLAY_VERSION);
910 };
911 
912 std::string GetICCDesc(const vigra::ImageImportInfo::ICCProfile& iccProfile)
913 {
914  if (iccProfile.empty())
915  {
916  // no profile
917  return std::string();
918  };
919  cmsHPROFILE profile = cmsOpenProfileFromMem(iccProfile.data(), iccProfile.size());
920  if (profile == NULL)
921  {
922  // invalid profile
923  return std::string();
924  };
925  const std::string name=GetICCDesc(profile);
926  cmsCloseProfile(profile);
927  return name;
928 };
929 
930 std::string GetICCDesc(const cmsHPROFILE& profile)
931 {
932  const size_t size = cmsGetProfileInfoASCII(profile, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, nullptr, 0);
933  std::string information(size, '\000');
934  cmsGetProfileInfoASCII(profile, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, &information[0], size);
935  StrTrim(information);
936  return information;
937 }
938 
940 std::vector<std::string> GetRawExtensions()
941 {
942  std::vector<std::string> rawExt{ "dng", "crw", "cr2","cr3","raw","erf","raf","mrw","nef","orf","rw2","pef","srw","arw" };
943  return rawExt;
944 };
945 
946 bool IsRawExtension(const std::string testExt)
947 {
948  const std::string testExtLower = tolower(testExt);
949  const auto rawExts = GetRawExtensions();
950  for (const auto& ext : rawExts)
951  {
952  if (testExtLower.compare(ext) == 0)
953  {
954  return true;
955  };
956  };
957  return false;
958 };
959 
960 } //namespace
static ContextSettings context
Definition: utils.cpp:774
std::string GetICCDesc(const vigra::ImageImportInfo::ICCProfile &iccProfile)
returns description of given icc profile
Definition: utils.cpp:912
bool wrapupGPU()
cleanup GPU settings
Definition: utils.cpp:901
bool FileExists(const std::string &filename)
checks if file exists
Definition: utils.cpp:362
std::string StrTrim(const std::string &str)
remove trailing and leading white spaces and tabs
Definition: utils.cpp:208
std::string GetCurrentTimeString()
current time as a string
Definition: utils.cpp:91
std::string GetOutputFilename(const std::string &out, const std::string &in, const std::string &suffix)
construct output filename, if ouput is known return this value otherwise use the input filename and a...
Definition: utils.cpp:420
std::string GetHomeDir()
Definition: utils.cpp:477
void EnforceExtension(std::string &filename, const std::string &defaultExtension)
check if filename contains extension, if not add default extension
Definition: utils.cpp:411
std::string doubleToString(double d, int digits)
convert a double to a string, suitable for display within a GUI.
Definition: utils.cpp:228
bool stringToUInt(const std::string &s, unsigned int &val)
convert string to unsigned integer value, returns true, if sucessful
Definition: utils.cpp:280
#define XP1
std::string GetDataDir()
returns the full path to the data directory
Definition: utils.cpp:441
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition: utils.cpp:184
std::string GetAbsoluteFilename(const std::string &filename)
returns the full absolute filename
Definition: utils.cpp:368
bool IsFileTypeSupported(const std::string &filename)
return true, if file type by extension is supported by vigra
Definition: utils.cpp:405
std::string getExtension(const std::string &basename2)
Get extension of a filename.
Definition: utils.cpp:99
std::string stripExtension(const std::string &basename2)
remove extension of a filename
Definition: utils.cpp:130
bool stringToInt(const std::string &s, int &val)
convert string to integer value, returns true, if sucessful
Definition: utils.cpp:264
#define XP2
bool initGPU(int *argcp, char **argv)
Try to initalise GLUT and GLEW, and create an OpenGL context for GPU stitching.
Definition: utils.cpp:845
void DestroyContext()
Definition: utils.cpp:819
bool StringContainsCaseInsensitive(const std::string &s1, const std::string &s2)
check if s1 contains s2 using case insensitive comparison
Definition: utils.cpp:335
void ReplaceAll(std::string &s, const std::string &oldChar, char newChar)
replace all characters oldChar in s with newChar
Definition: utils.cpp:325
bool CreateContext(int *argcp, char **argv)
Definition: utils.cpp:776
std::vector< std::string > GetRawExtensions()
return vector of known extensions of raw files, all lower case
Definition: utils.cpp:940
static T max(T x, T y)
Definition: svm.cpp:65
std::string GetUserAppDataDir()
returns the directory for user specific Hugin settings, e.g.
Definition: utils.cpp:497
void ControlPointErrorColour(const double cperr, double &r, double &g, double &b)
Definition: utils.cpp:341
std::string GetHuginVersion()
return a string with version numbers
Definition: utils.cpp:907
XVisualInfo * visualInfo
Definition: utils.cpp:759
bool IsRawExtension(const std::string testExt)
return true if extension belongs to a raw file
Definition: utils.cpp:946
std::vector< std::string > SplitString(const std::string &s, const std::string &sep)
split string s at given sep, returns vector of strings
Definition: utils.cpp:294
static T min(T x, T y)
Definition: svm.cpp:62
std::string tolower(const std::string &s)
convert a string to lowercase
Definition: stl_utils.h:49
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
Definition: utils.cpp:160