27 #include "hugin_version.h"
28 #include "hugin_config.h"
32 #include <sys/utime.h>
38 #include <sys/types.h>
49 #include <hugin_config.h>
56 #include <mach-o/dyld.h>
61 #if defined HAVE_EPOXY && HAVE_EPOXY
64 #include <epoxy/wgl.h>
73 #include <GLUT/glut.h>
76 namespace hugin_utils {
84 gettimeofday(&tv,NULL);
85 localtime_r((time_t*)&tv.tv_sec, &t);
86 strftime(tmp,99,
"%H:%M:%S",&t);
87 sprintf(tmp+8,
".%06ld", (
long)tv.tv_usec);
101 std::string::size_type idx = basename2.rfind(
'.');
104 if (idx == std::string::npos) {
106 return std::string(
"");
110 std::string::size_type slashidx = basename2.find(
'/', idx);
111 if ( slashidx == std::string::npos)
113 return basename2.substr(idx+1);
115 return std::string(
"");
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)
123 return basename2.substr(idx+1);
125 return std::string(
"");
132 std::string::size_type idx = basename2.rfind(
'.');
135 if (idx == std::string::npos) {
140 std::string::size_type slashidx = basename2.find(
'/', idx);
141 if ( slashidx == std::string::npos)
143 return basename2.substr(0, idx);
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)
153 return basename2.substr(0, idx);
163 std::string::size_type idx = filename.rfind(
'/');
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) {
170 }
else if (idx2 == std::string::npos) {
176 if (idx != std::string::npos) {
178 return filename.substr(idx + 1);
187 std::string::size_type idx = filename.rfind(
'/');
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) {
194 }
else if (idx2 == std::string::npos) {
200 if (idx != std::string::npos) {
202 return filename.substr(0, idx+1);
211 std::string::size_type pos = s.find_last_not_of(
" \t");
212 if (pos != std::string::npos)
215 pos = s.find_first_not_of(
" \t");
216 if (pos != std::string::npos)
223 s.erase(s.begin(), s.end());
235 std::sprintf(fmt,
"%%.%df",
std::min(digits, 16));
240 _snprintf (c, 1023, fmt, d);
242 snprintf (c, 1023, fmt, d);
245 std::string number (c);
247 int l = (int)number.length()-1;
249 while ( l != 0 && number[l] ==
'0' ) {
253 if ( number[l] ==
',' ) {
257 if ( number[l] ==
'.' ) {
271 int x = atoi(s.c_str());
287 val =
static_cast<unsigned int>(x);
294 std::vector<std::string>
SplitString(
const std::string& s,
const std::string& sep)
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)
303 std::string t(s.substr(pos2, pos - pos2));
311 pos = s.find_first_of(sep, pos2);
313 if (pos2 < s.length())
315 std::string t(s.substr(pos2));
325 void ReplaceAll(std::string& s,
const std::string& oldChar,
char newChar)
327 std::size_t found = s.find_first_of(oldChar);
328 while (found != std::string::npos)
331 found = s.find_first_of(oldChar, found + 1);
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();
342 double &r,
double &g,
double &b)
357 g = 0.75 * ((1.0 - std::min<double>(cperr -
XP1,
XP2 -
XP1) / (
XP2 - XP1)));
364 std::ifstream ifile(filename.c_str());
365 return !ifile.fail();
371 char fullpath[_MAX_PATH];
372 _fullpath(fullpath,filename.c_str(),_MAX_PATH);
373 return std::string(fullpath);
379 bool tempFileCreated=
false;
382 tempFileCreated=
true;
383 std::ofstream os(filename.c_str());
386 char *real_path = realpath(filename.c_str(), NULL);
390 absPath=std::string(real_path);
399 remove(filename.c_str());
408 return (vigra::impexListExtensions().find(extension) != std::string::npos);
414 if (extension.empty())
420 std::string
GetOutputFilename(
const std::string& out,
const std::string& in,
const std::string& suffix)
425 if (extension.empty())
427 return in +
"_" + suffix;
431 return in.substr(0, in.length() - extension.length() - 1).append(
"_" + suffix +
"." + extension);
444 char buffer[MAX_PATH];
445 GetModuleFileName(NULL,buffer,
sizeof(buffer));
446 fs::path data_path(buffer);
447 data_path.remove_filename();
448 if (data_path.has_parent_path())
450 return (data_path.parent_path() /
"share/hugin/data").
string() +
"\\";
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)
459 data_path=dirname(path);
460 data_path.append(
"/../Resources/xrc/");
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())
468 return (data_path.parent_path() /
"share/hugin/data").
string() +
"/";
470 return std::string();
472 return std::string(INSTALL_DATA_DIR);
479 char *homedir = getenv(
"HOME");
483 pw = getpwuid(getuid());
486 homedir = pw->pw_dir;
491 return std::string();
493 return std::string(homedir);
501 char fullpath[_MAX_PATH];
502 if(SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, fullpath)!=S_OK)
504 return std::string();
506 path = fs::path(fullpath);
510 char *xdgDataDir = getenv(
"XDG_DATA_HOME");
511 if (xdgDataDir == NULL || strlen(xdgDataDir) == 0)
518 return std::string();
520 path = fs::path(homeDir);
521 path /=
".local/share/hugin";
526 path = fs::path(xdgDataDir);
534 return std::string();
536 path = fs::path(homeDir);
539 path /=
".hugindata";
542 if (!fs::exists(path))
544 if (!fs::create_directories(path))
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();
551 return path.string();
556 struct ContextSettings
560 HGLRC renderingContext;
566 renderingContext = NULL;
569 static ContextSettings
context;
574 WNDCLASS windowClass;
576 ZeroMemory(&windowClass,
sizeof(WNDCLASS));
577 windowClass.hInstance = GetModuleHandle(NULL);
578 windowClass.lpfnWndProc = DefWindowProc;
579 windowClass.lpszClassName =
"Hugin";
580 if (RegisterClass(&windowClass) == 0)
585 context.
window = CreateWindow(
"Hugin",
"Hugin", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
586 CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL);
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)
609 if (SetPixelFormat(
context.dc, pixelFormat, &pixelFormatDesc) == FALSE)
615 if (
context.renderingContext == NULL)
619 if (wglMakeCurrent(
context.dc,
context.renderingContext) == FALSE)
623 #if defined HAVE_EPOXY && HAVE_EPOXY
624 epoxy_handle_external_wglMakeCurrent();
631 if (
context.renderingContext != NULL)
633 wglMakeCurrent(NULL, NULL);
634 #if defined HAVE_EPOXY && HAVE_EPOXY
635 epoxy_handle_external_wglMakeCurrent();
637 wglDeleteContext(
context.renderingContext);
647 UnregisterClass(
"Hugin", GetModuleHandle(NULL));
650 #elif defined __APPLE__
651 static GLuint GlutWindowHandle;
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");
668 glutDestroyWindow(GlutWindowHandle);
672 #if defined HAVE_EGL && HAVE_EGL
673 #if defined HAVE_EPOXY && HAVE_EPOXY
674 #include <epoxy/egl.h>
679 struct ContextSettings
681 EGLDisplay m_display;
682 EGLContext m_context;
685 static ContextSettings
context;
687 static const EGLint configAttribs[] = {
692 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
693 EGL_CONFORMANT, EGL_OPENGL_BIT,
694 EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
701 context.m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
702 if (
context.m_display == EGL_NO_DISPLAY)
704 std::cerr <<
"Could not connect to EGL_DEFAULT_DISPLAY" << std::endl;
709 if (eglInitialize(
context.m_display, &major, &minor) != EGL_TRUE)
711 std::cerr <<
"Could not initialize EGL" << std::endl
712 <<
"Error: 0x" << std::hex << eglGetError() << std::endl;
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;
721 if (!eglBindAPI(EGL_OPENGL_API))
723 std::cerr <<
"Could not bind OpenGL API" << std::endl
724 <<
"Error: 0x" << std::hex << eglGetError() << std::endl;
729 EGLConfig egl_config;
730 if (eglChooseConfig(
context.m_display, configAttribs, &egl_config, 1, &numConfigs) != EGL_TRUE)
732 std::cerr <<
"Cound not set egl config" << std::endl
733 <<
"Error: 0x" << std::hex << eglGetError() << std::endl;
738 context.m_context = eglCreateContext(
context.m_display, egl_config, EGL_NO_CONTEXT, NULL);
739 if (
context.m_context == EGL_NO_CONTEXT)
741 std::cerr <<
"Cound not create context" << std::endl
742 <<
"Error: 0x" << std::hex << eglGetError() << std::endl;
745 if (eglMakeCurrent(
context.m_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
context.m_context) != EGL_TRUE)
747 std::cerr <<
"Could not make current context" << std::endl
748 <<
"Error: 0x" << std::hex << eglGetError() << std::endl;
757 eglTerminate(
context.m_display);
761 #include <X11/Xlib.h>
762 #include <X11/Xutil.h>
763 #if defined HAVE_EPOXY && HAVE_EPOXY
764 #include <epoxy/glx.h>
804 int attrib[] = { GLX_RGBA, None };
818 XSetWindowAttributes swa;
819 swa.border_pixel = 0;
823 CWBorderPixel | CWColormap, &swa);
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");
875 int err = glewInit();
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;
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");
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;
922 return std::string(DISPLAY_VERSION);
925 std::string
GetICCDesc(
const vigra::ImageImportInfo::ICCProfile& iccProfile)
927 if (iccProfile.empty())
930 return std::string();
932 cmsHPROFILE profile = cmsOpenProfileFromMem(iccProfile.data(), iccProfile.size());
936 return std::string();
939 cmsCloseProfile(profile);
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);
955 std::vector<std::string> rawExt{
"dng",
"crw",
"cr2",
"cr3",
"raw",
"erf",
"raf",
"mrw",
"nef",
"orf",
"rw2",
"pef",
"srw",
"arw" };
961 const std::string testExtLower =
tolower(testExt);
963 for (
const auto& ext : rawExts)
965 if (testExtLower.compare(ext) == 0)
static ContextSettings context
std::string GetICCDesc(const vigra::ImageImportInfo::ICCProfile &iccProfile)
returns description of given icc profile
bool wrapupGPU()
cleanup GPU settings
bool FileExists(const std::string &filename)
checks if file exists
std::string StrTrim(const std::string &str)
remove trailing and leading white spaces and tabs
std::string GetCurrentTimeString()
current time as a string
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...
void EnforceExtension(std::string &filename, const std::string &defaultExtension)
check if filename contains extension, if not add default extension
std::string doubleToString(double d, int digits)
convert a double to a string, suitable for display within a GUI.
bool stringToUInt(const std::string &s, unsigned int &val)
convert string to unsigned integer value, returns true, if sucessful
std::string GetDataDir()
returns the full path to the data directory
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
std::string GetAbsoluteFilename(const std::string &filename)
returns the full absolute filename
bool IsFileTypeSupported(const std::string &filename)
return true, if file type by extension is supported by vigra
std::string getExtension(const std::string &basename2)
Get extension of a filename.
std::string stripExtension(const std::string &basename2)
remove extension of a filename
bool stringToInt(const std::string &s, int &val)
convert string to integer value, returns true, if sucessful
bool initGPU(int *argcp, char **argv)
Try to initalise GLUT and GLEW, and create an OpenGL context for GPU stitching.
bool StringContainsCaseInsensitive(const std::string &s1, const std::string &s2)
check if s1 contains s2 using case insensitive comparison
void ReplaceAll(std::string &s, const std::string &oldChar, char newChar)
replace all characters oldChar in s with newChar
bool CreateContext(int *argcp, char **argv)
std::vector< std::string > GetRawExtensions()
return vector of known extensions of raw files, all lower case
std::string GetUserAppDataDir()
returns the directory for user specific Hugin settings, e.g.
void ControlPointErrorColour(const double cperr, double &r, double &g, double &b)
std::string GetHuginVersion()
return a string with version numbers
bool IsRawExtension(const std::string testExt)
return true if extension belongs to a raw file
std::vector< std::string > SplitString(const std::string &s, const std::string &sep)
split string s at given sep, returns vector of strings
std::string tolower(const std::string &s)
convert a string to lowercase
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)