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 <hugin_utils/filesystem.h>
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  fs::path data_path(buffer);
447  data_path.remove_filename();
448  if (data_path.has_parent_path())
449  {
450  return (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  fs::path data_path = fs::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  fs::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 = fs::path(fullpath);
507  path /= "hugin";
508 #else
509 #ifdef USE_XDG_DIRS
510  char *xdgDataDir = getenv("XDG_DATA_HOME");
511  if (xdgDataDir == NULL || strlen(xdgDataDir) == 0)
512  {
513  // no XDG_DATA_HOME enviroment variable set or empty variable
514  // use $HOME/.local/share instead
515  const std::string homeDir = GetHomeDir();
516  if (homeDir.empty())
517  {
518  return std::string();
519  };
520  path = fs::path(homeDir);
521  path /= ".local/share/hugin";
522  }
523  else
524  {
525  // XDG_DATA_HOME set, use hugindata sub directory
526  path = fs::path(xdgDataDir);
527  path /= "hugin";
528  };
529 #else
530  // old behaviour, save in users home directory, sub-directory .hugindata
531  const std::string homeDir = GetHomeDir();
532  if (homeDir.empty())
533  {
534  return std::string();
535  };
536  path = fs::path(homeDir);
537  // we have already a file with name ".hugin" for our wxWidgets settings
538  // therefore we use directory ".hugindata" in homedir
539  path /= ".hugindata";
540 #endif
541 #endif
542  if (!fs::exists(path))
543  {
544  if (!fs::create_directories(path))
545  {
546  std::cerr << "ERROR: Could not create destination directory: " << path.string() << std::endl
547  << "Maybe you have not sufficient rights to create this directory." << std::endl;
548  return std::string();
549  };
550  };
551  return path.string();
552 };
553 
554 // initialization and wrapup of GPU for GPU remapping
555 #ifdef _WIN32
556 struct ContextSettings
557 {
558  HWND window;
559  HDC dc;
560  HGLRC renderingContext;
561 
563  {
564  window = NULL;
565  dc = NULL;
566  renderingContext = NULL;
567  }
568 };
569 static ContextSettings context;
570 
571 // create context, return false if failed
572 bool CreateContext(int *argcp, char **argv)
573 {
574  WNDCLASS windowClass;
575  /* register window class */
576  ZeroMemory(&windowClass, sizeof(WNDCLASS));
577  windowClass.hInstance = GetModuleHandle(NULL);
578  windowClass.lpfnWndProc = DefWindowProc;
579  windowClass.lpszClassName = "Hugin";
580  if (RegisterClass(&windowClass) == 0)
581  {
582  return false;
583  };
584  /* create window */
585  context.window = CreateWindow("Hugin", "Hugin", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
586  CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL);
587  if (context.window == NULL)
588  {
589  return false;
590  };
591  /* get the device context */
592  context.dc = GetDC(context.window);
593  if (context.dc == NULL)
594  {
595  return false;
596  };
597  /* find pixel format */
598  PIXELFORMATDESCRIPTOR pixelFormatDesc;
599  ZeroMemory(&pixelFormatDesc, sizeof(PIXELFORMATDESCRIPTOR));
600  pixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
601  pixelFormatDesc.nVersion = 1;
602  pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
603  int pixelFormat = ChoosePixelFormat(context.dc, &pixelFormatDesc);
604  if (pixelFormat == 0)
605  {
606  return false;
607  }
608  /* set the pixel format for the dc */
609  if (SetPixelFormat(context.dc, pixelFormat, &pixelFormatDesc) == FALSE)
610  {
611  return false;
612  };
613  /* create rendering context */
614  context.renderingContext = wglCreateContext(context.dc);
615  if (context.renderingContext == NULL)
616  {
617  return false;
618  };
619  if (wglMakeCurrent(context.dc, context.renderingContext) == FALSE)
620  {
621  return false;
622  };
623 #if defined HAVE_EPOXY && HAVE_EPOXY
624  epoxy_handle_external_wglMakeCurrent();
625 #endif
626  return true;
627 }
628 
629 void DestroyContext()
630 {
631  if (context.renderingContext != NULL)
632  {
633  wglMakeCurrent(NULL, NULL);
634 #if defined HAVE_EPOXY && HAVE_EPOXY
635  epoxy_handle_external_wglMakeCurrent();
636 #endif
637  wglDeleteContext(context.renderingContext);
638  }
639  if (context.window != NULL && context.dc != NULL)
640  {
641  ReleaseDC(context.window, context.dc);
642  };
643  if (context.window != NULL)
644  {
645  DestroyWindow(context.window);
646  };
647  UnregisterClass("Hugin", GetModuleHandle(NULL));
648 }
649 
650 #elif defined __APPLE__
651 static GLuint GlutWindowHandle;
652 bool CreateContext(int *argcp, char **argv)
653 {
654  // GLUT changes the working directory to the ressource path of the bundle
655  // so we store the old working directory and restore it at the end
656  char workingDir[FILENAME_MAX];
657  getcwd(workingDir, FILENAME_MAX);
658  glutInit(argcp, argv);
659  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_ALPHA);
660  GlutWindowHandle = glutCreateWindow("Hugin");
661  // restore working dir, as GLUT changes it the ressource path
662  chdir(workingDir);
663  return true;
664 }
665 
666 void DestroyContext()
667 {
668  glutDestroyWindow(GlutWindowHandle);
669 }
670 
671 #else
672 #if defined HAVE_EGL && HAVE_EGL
673 #if defined HAVE_EPOXY && HAVE_EPOXY
674 #include <epoxy/egl.h>
675 #else
676 #include <EGL/egl.h>
677 #endif
678 
679 struct ContextSettings
680 {
681  EGLDisplay m_display;
682  EGLContext m_context;
683 };
684 
685 static ContextSettings context;
686 
687 static const EGLint configAttribs[] = {
688  EGL_BLUE_SIZE, 8,
689  EGL_GREEN_SIZE, 8,
690  EGL_RED_SIZE, 8,
691  EGL_ALPHA_SIZE, 8,
692  EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
693  EGL_CONFORMANT, EGL_OPENGL_BIT,
694  EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
695  EGL_NONE
696 };
697 
698 bool CreateContext(int *argcp, char **argv)
699 {
700  // get display connection
701  context.m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
702  if (context.m_display == EGL_NO_DISPLAY)
703  {
704  std::cerr << "Could not connect to EGL_DEFAULT_DISPLAY" << std::endl;
705  return false;
706  };
707  // initialize egl
708  EGLint major, minor;
709  if (eglInitialize(context.m_display, &major, &minor) != EGL_TRUE)
710  {
711  std::cerr << "Could not initialize EGL" << std::endl
712  << "Error: 0x" << std::hex << eglGetError() << std::endl;
713  return false;
714  };
715  std::cout << "Init OpenGL ES " << major << "." << minor << std::endl;
716  std::cout << "Client API: " << eglQueryString(context.m_display, EGL_CLIENT_APIS) << std::endl
717  << "Vendor: " << eglQueryString(context.m_display, EGL_VENDOR) << std::endl
718  << "Version: " << eglQueryString(context.m_display, EGL_VERSION) << std::endl
719  << "EGL Extensions: " << eglQueryString(context.m_display, EGL_EXTENSIONS) << std::endl;
720  // bind OpenGL API (not OpenGL ES)
721  if (!eglBindAPI(EGL_OPENGL_API))
722  {
723  std::cerr << "Could not bind OpenGL API" << std::endl
724  << "Error: 0x" << std::hex << eglGetError() << std::endl;
725  return false;
726  };
727  // choose config
728  EGLint numConfigs;
729  EGLConfig egl_config;
730  if (eglChooseConfig(context.m_display, configAttribs, &egl_config, 1, &numConfigs) != EGL_TRUE)
731  {
732  std::cerr << "Cound not set egl config" << std::endl
733  << "Error: 0x" << std::hex << eglGetError() << std::endl;
734  return false;
735  };
736  // create surface
737  // create context and make it current
738  context.m_context = eglCreateContext(context.m_display, egl_config, EGL_NO_CONTEXT, NULL);
739  if (context.m_context == EGL_NO_CONTEXT)
740  {
741  std::cerr << "Cound not create context" << std::endl
742  << "Error: 0x" << std::hex << eglGetError() << std::endl;
743  return false;
744  };
745  if (eglMakeCurrent(context.m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, context.m_context) != EGL_TRUE)
746  {
747  std::cerr << "Could not make current context" << std::endl
748  << "Error: 0x" << std::hex << eglGetError() << std::endl;
749  return false;
750  };
751  return true;
752 }
753 
754 void DestroyContext()
755 {
756  // terminate egl at end
757  eglTerminate(context.m_display);
758 };
759 
760 #else
761 #include <X11/Xlib.h>
762 #include <X11/Xutil.h>
763 #if defined HAVE_EPOXY && HAVE_EPOXY
764 #include <epoxy/glx.h>
765 #else
766 #include <GL/glx.h>
767 #endif
768 
770 {
771  Display* display;
772  XVisualInfo* visualInfo;
773  GLXContext context;
774  Window window;
775  Colormap colormap;
776 
778  {
779  display=NULL;
780  visualInfo=NULL;
781  context=NULL;
782  window=0;
783  colormap=0;
784  };
785 };
786 
788 
789 bool CreateContext(int *argcp, char **argv)
790 {
791  /* open display */
792  context.display = XOpenDisplay(NULL);
793  if (context.display == NULL)
794  {
795  return false;
796  };
797  /* query for glx */
798  int erb, evb;
799  if (!glXQueryExtension(context.display, &erb, &evb))
800  {
801  return false;
802  };
803  /* choose visual */
804  int attrib[] = { GLX_RGBA, None };
805  context.visualInfo = glXChooseVisual(context.display, DefaultScreen(context.display), attrib);
806  if (context.visualInfo == NULL)
807  {
808  return false;
809  };
810  /* create context */
811  context.context = glXCreateContext(context.display, context.visualInfo, None, True);
812  if (context.context == NULL)
813  {
814  return false;
815  };
816  /* create window */
817  context.colormap = XCreateColormap(context.display, RootWindow(context.display, context.visualInfo->screen), context.visualInfo->visual, AllocNone);
818  XSetWindowAttributes swa;
819  swa.border_pixel = 0;
820  swa.colormap = context.colormap;
821  context.window = XCreateWindow(context.display, RootWindow(context.display, context.visualInfo->screen),
822  0, 0, 1, 1, 0, context.visualInfo->depth, InputOutput, context.visualInfo->visual,
823  CWBorderPixel | CWColormap, &swa);
824  /* make context current */
825  if (!glXMakeCurrent(context.display, context.window, context.context))
826  {
827  return false;
828  };
829  return true;
830 };
831 
833 {
834  if (context.display != NULL && context.context != NULL)
835  {
836  glXDestroyContext(context.display, context.context);
837  }
838  if (context.display != NULL && context.window != 0)
839  {
840  XDestroyWindow(context.display, context.window);
841  };
842  if (context.display != NULL && context.colormap != 0)
843  {
844  XFreeColormap(context.display, context.colormap);
845  };
846  if (context.visualInfo != NULL)
847  {
848  XFree(context.visualInfo);
849  };
850  if (context.display != NULL)
851  {
852  XCloseDisplay(context.display);
853  };
854 };
855 #endif
856 #endif
857 
858 bool initGPU(int *argcp, char **argv)
859 {
860  if (!CreateContext(argcp, argv))
861  {
862  return false;
863  };
864  std::cout << hugin_utils::stripPath(argv[0]) << ": using graphics card: " << glGetString(GL_VENDOR) << " " << glGetString(GL_RENDERER) << std::endl;
865 #if defined HAVE_EPOXY && HAVE_EPOXY
866  const GLboolean has_arb_fragment_shader = epoxy_has_gl_extension("GL_ARB_fragment_shader");
867  const GLboolean has_arb_vertex_shader = epoxy_has_gl_extension("GL_ARB_vertex_shader");
868  const GLboolean has_arb_shader_objects = epoxy_has_gl_extension("GL_ARB_shader_objects");
869  const GLboolean has_arb_shading_language = epoxy_has_gl_extension("GL_ARB_shading_language_100");
870  const GLboolean has_ext_framebuffer = epoxy_has_gl_extension("GL_EXT_framebuffer_object");
871  const GLboolean has_arb_texture_rectangle = epoxy_has_gl_extension("GL_ARB_texture_rectangle");
872  const GLboolean has_arb_texture_border_clamp = epoxy_has_gl_extension("GL_ARB_texture_border_clamp");
873  const GLboolean has_arb_texture_float = epoxy_has_gl_extension("GL_ARB_texture_float");
874 #else
875  int err = glewInit();
876  if (err != GLEW_OK)
877  {
878  std::cerr << argv[0] << ": an error occurred while setting up the GPU:" << std::endl;
879  std::cerr << glewGetErrorString(err) << std::endl;
880  std::cerr << argv[0] << ": Switching to CPU calculation." << std::endl;
881  DestroyContext();
882  return false;
883  }
884 
885  const GLboolean has_arb_fragment_shader = glewGetExtension("GL_ARB_fragment_shader");
886  const GLboolean has_arb_vertex_shader = glewGetExtension("GL_ARB_vertex_shader");
887  const GLboolean has_arb_shader_objects = glewGetExtension("GL_ARB_shader_objects");
888  const GLboolean has_arb_shading_language = glewGetExtension("GL_ARB_shading_language_100");
889  const GLboolean has_ext_framebuffer = glewGetExtension("GL_EXT_framebuffer_object");
890  const GLboolean has_arb_texture_rectangle = glewGetExtension("GL_ARB_texture_rectangle");
891  const GLboolean has_arb_texture_border_clamp = glewGetExtension("GL_ARB_texture_border_clamp");
892  const GLboolean has_arb_texture_float = glewGetExtension("GL_ARB_texture_float");
893 #endif
894 
895  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)) {
896  const char * msg[] = {"false", "true"};
897  std::cerr << argv[0] << ": extension GL_ARB_fragment_shader = " << msg[has_arb_fragment_shader] << std::endl;
898  std::cerr << argv[0] << ": extension GL_ARB_vertex_shader = " << msg[has_arb_vertex_shader] << std::endl;
899  std::cerr << argv[0] << ": extension GL_ARB_shader_objects = " << msg[has_arb_shader_objects] << std::endl;
900  std::cerr << argv[0] << ": extension GL_ARB_shading_language_100 = " << msg[has_arb_shading_language] << std::endl;
901  std::cerr << argv[0] << ": extension GL_EXT_framebuffer_object = " << msg[has_ext_framebuffer] << std::endl;
902  std::cerr << argv[0] << ": extension GL_ARB_texture_rectangle = " << msg[has_arb_texture_rectangle] << std::endl;
903  std::cerr << argv[0] << ": extension GL_ARB_texture_border_clamp = " << msg[has_arb_texture_border_clamp] << std::endl;
904  std::cerr << argv[0] << ": extension GL_ARB_texture_float = " << msg[has_arb_texture_float] << std::endl;
905  std::cerr << argv[0] << ": This graphics system lacks the necessary extensions for -g." << std::endl;
906  std::cerr << argv[0] << ": Switching to CPU calculation." << std::endl;
907  DestroyContext();
908  return false;
909  }
910 
911  return true;
912 }
913 
914 bool wrapupGPU()
915 {
916  DestroyContext();
917  return true;
918 }
919 
920 std::string GetHuginVersion()
921 {
922  return std::string(DISPLAY_VERSION);
923 };
924 
925 std::string GetICCDesc(const vigra::ImageImportInfo::ICCProfile& iccProfile)
926 {
927  if (iccProfile.empty())
928  {
929  // no profile
930  return std::string();
931  };
932  cmsHPROFILE profile = cmsOpenProfileFromMem(iccProfile.data(), iccProfile.size());
933  if (profile == NULL)
934  {
935  // invalid profile
936  return std::string();
937  };
938  const std::string name=GetICCDesc(profile);
939  cmsCloseProfile(profile);
940  return name;
941 };
942 
943 std::string GetICCDesc(const cmsHPROFILE& profile)
944 {
945  const size_t size = cmsGetProfileInfoASCII(profile, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, nullptr, 0);
946  std::string information(size, '\000');
947  cmsGetProfileInfoASCII(profile, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, &information[0], size);
948  StrTrim(information);
949  return information;
950 }
951 
953 std::vector<std::string> GetRawExtensions()
954 {
955  std::vector<std::string> rawExt{ "dng", "crw", "cr2","cr3","raw","erf","raf","mrw","nef","orf","rw2","pef","srw","arw" };
956  return rawExt;
957 };
958 
959 bool IsRawExtension(const std::string testExt)
960 {
961  const std::string testExtLower = tolower(testExt);
962  const auto rawExts = GetRawExtensions();
963  for (const auto& ext : rawExts)
964  {
965  if (testExtLower.compare(ext) == 0)
966  {
967  return true;
968  };
969  };
970  return false;
971 };
972 
973 } //namespace
static ContextSettings context
Definition: utils.cpp:787
std::string GetICCDesc(const vigra::ImageImportInfo::ICCProfile &iccProfile)
returns description of given icc profile
Definition: utils.cpp:925
bool wrapupGPU()
cleanup GPU settings
Definition: utils.cpp:914
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:858
void DestroyContext()
Definition: utils.cpp:832
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:789
std::vector< std::string > GetRawExtensions()
return vector of known extensions of raw files, all lower case
Definition: utils.cpp:953
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:920
XVisualInfo * visualInfo
Definition: utils.cpp:772
bool IsRawExtension(const std::string testExt)
return true if extension belongs to a raw file
Definition: utils.cpp:959
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