utils.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00025 #include "utils.h"
00026 #include "hugin_version.h"
00027 #include "hugin_config.h"
00028 
00029 #ifdef _WIN32
00030     #define NOMINMAX
00031     #include <sys/utime.h>
00032     #include <ShlObj.h>
00033 #else
00034     #include <sys/time.h>
00035     #include <cstdlib>
00036     #include <unistd.h>
00037     #include <sys/types.h>
00038     #include <pwd.h>
00039 #endif
00040 #include <time.h>
00041 #include <fstream>
00042 #include <stdio.h>
00043 #include <cstdio>
00044 #ifdef _WIN32
00045 #define NOMINMAX
00046 #include <windows.h>
00047 #else
00048 #include <hugin_config.h>
00049 #endif
00050 #include <algorithm>
00051 #ifdef HAVE_STD_FILESYSTEM
00052 #include <filesystem>
00053 namespace fs = std::tr2::sys;
00054 #else
00055 #define BOOST_FILESYSTEM_VERSION 3
00056 #include <boost/filesystem.hpp>
00057 namespace fs = boost::filesystem;
00058 #endif
00059 #include <lcms2.h>
00060 
00061 #ifdef __APPLE__
00062 #include <mach-o/dyld.h>  /* _NSGetExecutablePath */
00063 #include <limits.h>       /* PATH_MAX */
00064 #include <libgen.h>       /* dirname */
00065 #endif
00066 
00067 #include <GL/glew.h>
00068 #ifdef _WIN32
00069 #include <GL/wglew.h>
00070 #elif defined __APPLE__
00071   #include <GLUT/glut.h>
00072 #endif
00073 
00074 namespace hugin_utils {
00075     
00076 #ifdef UNIX_LIKE
00077 std::string GetCurrentTimeString()
00078 {
00079   char tmp[100];
00080   struct tm t;
00081   struct timeval tv;
00082   gettimeofday(&tv,NULL);
00083   localtime_r((time_t*)&tv.tv_sec, &t); // is the casting safe?
00084   strftime(tmp,99,"%H:%M:%S",&t);
00085   sprintf(tmp+8,".%06ld", (long)tv.tv_usec);
00086   return tmp;
00087 }
00088 #else
00089 std::string GetCurrentTimeString()
00090 {
00091     // FIXME implement for Win
00092     return "";
00093 }
00094 #endif
00095 
00096 
00097 std::string getExtension(const std::string & basename2)
00098 {
00099         std::string::size_type idx = basename2.rfind('.');
00100     // check if the dot is not followed by a \ or a /
00101     // to avoid cutting pathes.
00102     if (idx == std::string::npos) {
00103         // no dot found
00104                 return std::string("");
00105     }
00106 #ifdef UNIX_LIKE
00107     // check for slashes after dot
00108     std::string::size_type slashidx = basename2.find('/', idx);
00109     if ( slashidx == std::string::npos)
00110     {
00111         return basename2.substr(idx+1);
00112     } else {
00113         return std::string("");
00114     }
00115 #else
00116     // check for slashes after dot
00117     std::string::size_type slashidx = basename2.find('/', idx);
00118     std::string::size_type backslashidx = basename2.find('\\', idx);
00119     if ( slashidx == std::string::npos &&  backslashidx == std::string::npos)
00120     {
00121         return basename2.substr(idx+1);
00122     } else {
00123                 return std::string("");
00124     }
00125 #endif
00126 }
00127 
00128 std::string stripExtension(const std::string & basename2)
00129 {
00130     std::string::size_type idx = basename2.rfind('.');
00131     // check if the dot is not followed by a \ or a /
00132     // to avoid cutting pathes.
00133     if (idx == std::string::npos) {
00134         // no dot found
00135         return basename2;
00136     }
00137 #ifdef UNIX_LIKE
00138     std::string::size_type slashidx = basename2.find('/', idx);
00139     if ( slashidx == std::string::npos)
00140     {
00141         return basename2.substr(0, idx);
00142     } else {
00143         return basename2;
00144     }
00145 #else
00146     // check for slashes after dot
00147     std::string::size_type slashidx = basename2.find('/', idx);
00148     std::string::size_type backslashidx = basename2.find('\\', idx);
00149     if ( slashidx == std::string::npos &&  backslashidx == std::string::npos)
00150     {
00151         return basename2.substr(0, idx);
00152     } else {
00153         return basename2;
00154     }
00155 #endif
00156 }
00157 
00158 std::string stripPath(const std::string & filename)
00159 {
00160 #ifdef UNIX_LIKE
00161     std::string::size_type idx = filename.rfind('/');
00162 #else
00163     std::string::size_type idx1 = filename.rfind('\\');
00164     std::string::size_type idx2 = filename.rfind('/');
00165     std::string::size_type idx;
00166     if (idx1 == std::string::npos) {
00167         idx = idx2;
00168     } else if (idx2 == std::string::npos) {
00169         idx = idx1;
00170     } else {
00171         idx = std::max(idx1, idx2);
00172     }
00173 #endif
00174     if (idx != std::string::npos) {
00175 //        DEBUG_DEBUG("returning substring: " << filename.substr(idx + 1));
00176         return filename.substr(idx + 1);
00177     } else {
00178         return filename;
00179     }
00180 }
00181 
00182 std::string getPathPrefix(const std::string & filename)
00183 {
00184 #ifdef UNIX_LIKE
00185     std::string::size_type idx = filename.rfind('/');
00186 #else
00187     std::string::size_type idx1 = filename.rfind('\\');
00188     std::string::size_type idx2 = filename.rfind('/');
00189     std::string::size_type idx;
00190     if (idx1 == std::string::npos) {
00191         idx = idx2;
00192     } else if (idx2 == std::string::npos) {
00193         idx = idx1;
00194     } else {
00195         idx = std::max(idx1, idx2);
00196     }
00197 #endif
00198     if (idx != std::string::npos) {
00199 //        DEBUG_DEBUG("returning substring: " << filename.substr(idx + 1));
00200         return filename.substr(0, idx+1);
00201     } else {
00202         return "";
00203     }
00204 }
00205 
00206 std::string StrTrim(const std::string& str)
00207 {
00208     std::string s(str);
00209     std::string::size_type pos = s.find_last_not_of(" \t");
00210     if (pos != std::string::npos)
00211     {
00212         s.erase(pos + 1);
00213         pos = s.find_first_not_of(" \t");
00214         if (pos != std::string::npos)
00215         {
00216             s.erase(0, pos);
00217         };
00218     }
00219     else
00220     {
00221         s.erase(s.begin(), s.end());
00222     };
00223     return s;
00224 }
00225 
00226 std::string doubleToString(double d, int digits)
00227 {
00228     char fmt[10];
00229     if (digits < 0) {
00230         strcpy(fmt,"%f");
00231     } else {
00232         std::sprintf(fmt,"%%.%df",digits);
00233     }
00234     char c[1024];
00235     c[1023] = 0;
00236 #ifdef _MSC_VER
00237     _snprintf (c, 1023, fmt, d);
00238 #else
00239     snprintf (c, 1023, fmt, d);
00240 #endif
00241 
00242     std::string number (c);
00243 
00244     int l = (int)number.length()-1;
00245 
00246     while ( l != 0 && number[l] == '0' ) {
00247       number.erase (l);
00248       l--;
00249     }
00250     if ( number[l] == ',' ) {
00251       number.erase (l);
00252       l--;
00253     }
00254     if ( number[l] == '.' ) {
00255       number.erase (l);
00256       l--;
00257     }
00258     return number;
00259 }
00260 
00261 bool stringToInt(const std::string& s, int& val)
00262 {
00263     if (StrTrim(s) == "0")
00264     {
00265         val = 0;
00266         return true;
00267     };
00268     int x = atoi(s.c_str());
00269     if (x != 0)
00270     {
00271         val = x;
00272         return true;
00273     };
00274     return false;
00275 };
00276 
00277 bool stringToUInt(const std::string&s, unsigned int& val)
00278 {
00279     int x;
00280     if (stringToInt(s, x))
00281     {
00282         if (x >= 0)
00283         {
00284             val = static_cast<unsigned int>(x);
00285             return true;
00286         };
00287     };
00288     return false;
00289 };
00290 
00291 std::vector<std::string> SplitString(const std::string& s, const std::string& sep)
00292 {
00293     std::vector<std::string> result;
00294     std::size_t pos = s.find_first_of(sep, 0);
00295     std::size_t pos2 = 0;
00296     while (pos != std::string::npos)
00297     {
00298         if (pos - pos2 > 0)
00299         {
00300             std::string t(s.substr(pos2, pos - pos2));
00301             t=StrTrim(t);
00302             if (!t.empty())
00303             {
00304                 result.push_back(t);
00305             };
00306         };
00307         pos2 = pos + 1;
00308         pos = s.find_first_of(sep, pos2);
00309     }
00310     if (pos2 < s.length())
00311     {
00312         std::string t(s.substr(pos2));
00313         t = StrTrim(t);
00314         if (!t.empty())
00315         {
00316             result.push_back(t);
00317         };
00318     };
00319     return result;
00320 };
00321 
00322 void ReplaceAll(std::string& s, const std::string& oldChar, char newChar)
00323 {
00324     std::size_t found = s.find_first_of(oldChar);
00325     while (found != std::string::npos)
00326     {
00327         s[found] = newChar;
00328         found = s.find_first_of(oldChar, found + 1);
00329     };
00330 };
00331 
00332     void ControlPointErrorColour(const double cperr, 
00333         double &r,double &g, double &b)
00334     {
00335         //Colour change points
00336 #define XP1 5.0f
00337 #define XP2 10.0f
00338 
00339         if ( cperr<= XP1) 
00340         {
00341             //low error
00342             r = cperr / XP1;
00343             g = 0.75;
00344         }
00345         else
00346         {
00347             r = 1.0;
00348             g = 0.75 * ((1.0 - std::min<double>(cperr - XP1, XP2 - XP1) / (XP2 - XP1)));
00349         } 
00350         b = 0.0;
00351     }
00352 
00353 bool FileExists(const std::string& filename)
00354 {
00355     std::ifstream ifile(filename.c_str());
00356     return !ifile.fail();
00357 }
00358 
00359 std::string GetAbsoluteFilename(const std::string& filename)
00360 {
00361 #ifdef _WIN32
00362     char fullpath[_MAX_PATH];
00363     _fullpath(fullpath,filename.c_str(),_MAX_PATH);
00364     return std::string(fullpath);
00365 #else
00366     //realpath works only with existing files
00367     //so as work around we create the file first, call then realpath 
00368     //and delete the temp file
00370     bool tempFileCreated=false;
00371     if(!FileExists(filename))
00372     {
00373         tempFileCreated=true;
00374         std::ofstream os(filename.c_str());
00375         os.close();
00376     };
00377     char *real_path = realpath(filename.c_str(), NULL);
00378     std::string absPath;
00379     if(real_path!=NULL)
00380     {
00381         absPath=std::string(real_path);
00382         free(real_path);
00383     }
00384     else
00385     {
00386         absPath=filename;
00387     };
00388     if(tempFileCreated)
00389     {
00390         remove(filename.c_str());
00391     };
00392     return absPath;
00393 #endif
00394 };
00395 
00396 bool IsFileTypeSupported(const std::string& filename)
00397 {
00398     const std::string extension = getExtension(filename);
00399     return (vigra::impexListExtensions().find(extension) != std::string::npos);
00400 };
00401 
00402 void EnforceExtension(std::string& filename, const std::string& defaultExtension)
00403 {
00404     const std::string extension = getExtension(filename);
00405     if (extension.empty())
00406     {
00407         filename = stripExtension(filename) + "." + defaultExtension;
00408     };
00409 };
00410 
00411 std::string GetDataDir()
00412 {
00413 #ifdef _WIN32
00414     char buffer[MAX_PATH];//always use MAX_PATH for filepaths
00415     GetModuleFileName(NULL,buffer,sizeof(buffer));
00416     std::string working_path(buffer);
00417     std::string data_path("");
00418     //remove filename
00419     std::string::size_type pos=working_path.rfind("\\");
00420     if(pos!=std::string::npos)
00421     {
00422         working_path.erase(pos);
00423         //remove last dir: should be bin
00424         pos=working_path.rfind("\\");
00425         if(pos!=std::string::npos)
00426         {
00427             working_path.erase(pos);
00428             //append path delimiter and path
00429             working_path.append("\\share\\hugin\\data\\");
00430             data_path=working_path;
00431         }
00432     }
00433 #elif defined MAC_SELF_CONTAINED_BUNDLE
00434     char path[PATH_MAX + 1];
00435     uint32_t size = sizeof(path);
00436     std::string data_path("");
00437     if (_NSGetExecutablePath(path, &size) == 0)
00438     {
00439         data_path=dirname(path);
00440         data_path.append("/../Resources/xrc/");
00441     }
00442 #else
00443     std::string data_path = (INSTALL_DATA_DIR);
00444 #endif
00445     return data_path;
00446 };
00447 
00448 std::string GetUserAppDataDir()
00449 {
00450     fs::path path;
00451 #ifdef _WIN32
00452     char fullpath[_MAX_PATH];
00453     if(SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, fullpath)!=S_OK)
00454     {
00455         return std::string();
00456     };
00457     path = fs::path(fullpath);
00458     path /= "hugin";
00459 #else
00460     char *homedir = getenv("HOME");
00461     struct passwd *pw;
00462     if (homedir == NULL)
00463     {
00464         pw = getpwuid(getuid());
00465         if(pw != NULL)
00466         {
00467             homedir = pw->pw_dir;
00468         };
00469     };
00470     if(homedir == NULL)
00471     {
00472         return std::string();
00473     };
00474     path = fs::path(homedir);
00475     // we have already a file with name ".hugin" for our wxWidgets settings
00476     // therefore we use directory ".hugindata" in homedir
00477     path /= ".hugindata";
00478 #endif
00479     if (!fs::exists(path))
00480     {
00481         if (!fs::create_directories(path))
00482         {
00483             std::cerr << "ERROR: Could not create destination directory: " << path.string() << std::endl
00484                 << "Maybe you have not sufficient rights to create this directory." << std::endl;
00485             return std::string();
00486         };
00487     };
00488     return path.string();
00489 };
00490 
00491 // initialization and wrapup of GPU for GPU remapping
00492 #ifdef _WIN32
00493 struct ContextSettings
00494 {
00495     HWND window;
00496     HDC dc;
00497     HGLRC renderingContext;
00498     
00499     ContextSettings()
00500     {
00501         window = NULL;
00502         dc = NULL;
00503         renderingContext = NULL;
00504     }
00505 };
00506 static ContextSettings context;
00507 
00508 // create context, return false if failed
00509 bool CreateContext(int *argcp, char **argv)
00510 {
00511     WNDCLASS windowClass;
00512     /* register window class */
00513     ZeroMemory(&windowClass, sizeof(WNDCLASS));
00514     windowClass.hInstance = GetModuleHandle(NULL);
00515     windowClass.lpfnWndProc = DefWindowProc;
00516     windowClass.lpszClassName = "Hugin";
00517     if (RegisterClass(&windowClass) == 0)
00518     {
00519         return false;
00520     };
00521     /* create window */
00522     context.window = CreateWindow("Hugin", "Hugin", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
00523         CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL);
00524     if (context.window == NULL)
00525     {
00526         return false;
00527     };
00528     /* get the device context */
00529     context.dc = GetDC(context.window);
00530     if (context.dc == NULL)
00531     {
00532         return false;
00533     };
00534     /* find pixel format */
00535     PIXELFORMATDESCRIPTOR pixelFormatDesc;
00536     ZeroMemory(&pixelFormatDesc, sizeof(PIXELFORMATDESCRIPTOR));
00537     pixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
00538     pixelFormatDesc.nVersion = 1;
00539     pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
00540     int pixelFormat = ChoosePixelFormat(context.dc, &pixelFormatDesc);
00541     if (pixelFormat == 0)
00542     {
00543         return false;
00544     }
00545     /* set the pixel format for the dc */
00546     if (SetPixelFormat(context.dc, pixelFormat, &pixelFormatDesc) == FALSE)
00547     {
00548         return false;
00549     };
00550     /* create rendering context */
00551     context.renderingContext = wglCreateContext(context.dc);
00552     if (context.renderingContext == NULL)
00553     {
00554         return false;
00555     };
00556     if (wglMakeCurrent(context.dc, context.renderingContext) == FALSE)
00557     {
00558         return false;
00559     };
00560     return true;
00561 }
00562 
00563 void DestroyContext()
00564 {
00565     if (context.renderingContext != NULL)
00566     {
00567         wglMakeCurrent(NULL, NULL);
00568         wglDeleteContext(context.renderingContext);
00569     }
00570     if (context.window != NULL && context.dc != NULL)
00571     {
00572         ReleaseDC(context.window, context.dc);
00573     };
00574     if (context.window != NULL)
00575     {
00576         DestroyWindow(context.window);
00577     };
00578     UnregisterClass("Hugin", GetModuleHandle(NULL));
00579 }
00580 
00581 #elif defined __APPLE__
00582 static GLuint GlutWindowHandle;
00583 bool CreateContext(int *argcp, char **argv)
00584 {
00585     glutInit(argcp, argv);
00586     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_ALPHA);
00587     GlutWindowHandle = glutCreateWindow("Hugin");
00588     return true;
00589 }
00590 
00591 void DestroyContext()
00592 {
00593     glutDestroyWindow(GlutWindowHandle);
00594 }
00595 
00596 #else
00597 #include <X11/Xlib.h>
00598 #include <X11/Xutil.h>
00599 #include <GL/glx.h>
00600 
00601 struct ContextSettings
00602 {
00603     Display* display;
00604     XVisualInfo* visualInfo;
00605     GLXContext context;
00606     Window window;
00607     Colormap colormap;
00608     
00609     ContextSettings()
00610     {
00611         display=NULL;
00612         visualInfo=NULL;
00613         context=NULL;
00614         window=0;
00615         colormap=0;
00616     };
00617 };
00618 
00619 static ContextSettings context;
00620 
00621 bool CreateContext(int *argcp, char **argv)
00622 {
00623     /* open display */
00624     context.display = XOpenDisplay(NULL);
00625     if (context.display == NULL)
00626     {
00627         return false;
00628     };
00629     /* query for glx */
00630     int erb, evb;
00631     if (!glXQueryExtension(context.display, &erb, &evb))
00632     {
00633         return false;
00634     };
00635     /* choose visual */
00636     int attrib[] = { GLX_RGBA, None };
00637     context.visualInfo = glXChooseVisual(context.display, DefaultScreen(context.display), attrib);
00638     if (context.visualInfo == NULL)
00639     {
00640         return false;
00641     };
00642     /* create context */
00643     context.context = glXCreateContext(context.display, context.visualInfo, None, True);
00644     if (context.context == NULL)
00645     {
00646         return false;
00647     };
00648     /* create window */
00649     context.colormap = XCreateColormap(context.display, RootWindow(context.display, context.visualInfo->screen), context.visualInfo->visual, AllocNone);
00650     XSetWindowAttributes swa;
00651     swa.border_pixel = 0;
00652     swa.colormap = context.colormap;
00653     context.window = XCreateWindow(context.display, RootWindow(context.display, context.visualInfo->screen),
00654         0, 0, 1, 1, 0, context.visualInfo->depth, InputOutput, context.visualInfo->visual,
00655         CWBorderPixel | CWColormap, &swa);
00656     /* make context current */
00657     if (!glXMakeCurrent(context.display, context.window, context.context))
00658     {
00659         return false;
00660     };
00661     return true;
00662 };
00663 
00664 void DestroyContext()
00665 {
00666     if (context.display != NULL && context.context != NULL)
00667     {
00668         glXDestroyContext(context.display, context.context);
00669     }
00670     if (context.display != NULL && context.window != 0)
00671     {
00672         XDestroyWindow(context.display, context.window);
00673     };
00674     if (context.display != NULL && context.colormap != 0)
00675     {
00676         XFreeColormap(context.display, context.colormap);
00677     };
00678     if (context.visualInfo != NULL)
00679     {
00680         XFree(context.visualInfo);
00681     };
00682     if (context.display != NULL)
00683     {
00684         XCloseDisplay(context.display);
00685     };
00686 };
00687 #endif
00688 
00689 bool initGPU(int *argcp, char **argv)
00690 {
00691     if (!CreateContext(argcp, argv))
00692     {
00693         return false;
00694     };
00695     int err = glewInit();
00696     if (err != GLEW_OK)
00697     {
00698         std::cerr << argv[0] << ": an error occurred while setting up the GPU:" << std::endl;
00699         std::cerr << glewGetErrorString(err) << std::endl;
00700         std::cerr << argv[0] << ": Switching to CPU calculation." << std::endl;
00701         DestroyContext();
00702         return false;
00703     }
00704 
00705     std::cout << hugin_utils::stripPath(argv[0]) << ": using graphics card: " << glGetString(GL_VENDOR) << " " << glGetString(GL_RENDERER) << std::endl;
00706 
00707     const GLboolean has_arb_fragment_shader = glewGetExtension("GL_ARB_fragment_shader");
00708     const GLboolean has_arb_vertex_shader = glewGetExtension("GL_ARB_vertex_shader");
00709     const GLboolean has_arb_shader_objects = glewGetExtension("GL_ARB_shader_objects");
00710     const GLboolean has_arb_shading_language = glewGetExtension("GL_ARB_shading_language_100");
00711     const GLboolean has_ext_framebuffer = glewGetExtension("GL_EXT_framebuffer_object");
00712     const GLboolean has_arb_texture_rectangle = glewGetExtension("GL_ARB_texture_rectangle");
00713     const GLboolean has_arb_texture_border_clamp = glewGetExtension("GL_ARB_texture_border_clamp");
00714     const GLboolean has_arb_texture_float = glewGetExtension("GL_ARB_texture_float");
00715 
00716     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)) {
00717         const char * msg[] = {"false", "true"};
00718         std::cerr << argv[0] << ": extension GL_ARB_fragment_shader = " << msg[has_arb_fragment_shader] << std::endl;
00719         std::cerr << argv[0] << ": extension GL_ARB_vertex_shader = " << msg[has_arb_vertex_shader] << std::endl;
00720         std::cerr << argv[0] << ": extension GL_ARB_shader_objects = " << msg[has_arb_shader_objects] << std::endl;
00721         std::cerr << argv[0] << ": extension GL_ARB_shading_language_100 = " << msg[has_arb_shading_language] << std::endl;
00722         std::cerr << argv[0] << ": extension GL_EXT_framebuffer_object = " << msg[has_ext_framebuffer] << std::endl;
00723         std::cerr << argv[0] << ": extension GL_ARB_texture_rectangle = " << msg[has_arb_texture_rectangle] << std::endl;
00724         std::cerr << argv[0] << ": extension GL_ARB_texture_border_clamp = " << msg[has_arb_texture_border_clamp] << std::endl;
00725         std::cerr << argv[0] << ": extension GL_ARB_texture_float = " << msg[has_arb_texture_float] << std::endl;
00726         std::cerr << argv[0] << ": This graphics system lacks the necessary extensions for -g." << std::endl;
00727         std::cerr << argv[0] << ": Switching to CPU calculation." << std::endl;
00728         DestroyContext();
00729         return false;
00730     }
00731 
00732     return true;
00733 }
00734 
00735 bool wrapupGPU()
00736 {
00737     DestroyContext();
00738     return true;
00739 }
00740 
00741 std::string GetHuginVersion()
00742 {
00743     return std::string(DISPLAY_VERSION);
00744 };
00745 
00746 std::string GetICCDesc(const vigra::ImageImportInfo::ICCProfile& iccProfile)
00747 {
00748     if (iccProfile.empty())
00749     {
00750         // no profile
00751         return std::string();
00752     };
00753     cmsHPROFILE profile = cmsOpenProfileFromMem(iccProfile.data(), iccProfile.size());
00754     if (profile == NULL)
00755     {
00756         // invalid profile
00757         return std::string();
00758     };
00759     const std::string name=GetICCDesc(profile);
00760     cmsCloseProfile(profile);
00761     return name;
00762 };
00763 
00764 std::string GetICCDesc(const cmsHPROFILE& profile)
00765 {
00766     const size_t size = cmsGetProfileInfoASCII(profile, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, nullptr, 0);
00767     std::string information(size, '\000');
00768     cmsGetProfileInfoASCII(profile, cmsInfoDescription, cmsNoLanguage, cmsNoCountry, &information[0], size);
00769     StrTrim(information);
00770     return information;
00771 }
00772 } //namespace

Generated on 21 Sep 2017 for Hugintrunk by  doxygen 1.4.7