wxcms.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00010 /*  This program is free software; you can redistribute it and/or
00011  *  modify it under the terms of the GNU General Public
00012  *  License as published by the Free Software Foundation; either
00013  *  version 2 of the License, or (at your option) any later version.
00014  *
00015  *  This software is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  *  General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public
00021  *  License along with this software. If not, see
00022  *  <http://www.gnu.org/licenses/>.
00023  *
00024  */
00025 
00026 #include "wxcms.h"
00027 #include "hugin_utils/utils.h"
00028 #ifdef __WXGTK__
00029 #include <X11/Xlib.h>
00030 #endif
00031 #ifdef __WXMAC__
00032 #include <ApplicationServices/ApplicationServices.h>
00033 #include <CoreFoundation/CoreFoundation.h>
00034 #include "wx/osx/core/cfstring.h"
00035 #include <wx/osx/private.h>
00036 #endif
00037 
00038 namespace HuginBase
00039 {
00040     namespace Color
00041     {
00042         namespace detail
00043         {
00044 #ifdef __WXMSW__
00045             // retrieve monitor profile from Windows
00046             // TODO: support for multi-monitor setups
00047             void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
00048             {
00049                 // look up monitor profile in system
00050                 HDC hdc = GetDC(NULL);
00051                 if (hdc)
00052                 {
00053                     wxChar filename[MAX_PATH];
00054                     DWORD len;
00055                     if (GetICMProfile(hdc, &len, filename))
00056                     {
00057                         profileName = filename;
00058                         profile = cmsOpenProfileFromFile(profileName.c_str(), "r");
00059                     };
00060                     ReleaseDC(NULL, hdc);
00061                 };
00062             };
00063 #elif defined __WXGTK__
00064             cmsHPROFILE GetProfileFromAtom(Display* disp, const char* prop_name)
00065             {
00066                 Atom atom = XInternAtom(disp, prop_name, True);
00067                 if (atom)
00068                 {
00069                     int actual_format_return;
00070                     unsigned long nitems_return = 0;
00071                     unsigned long bytes_after_return = 0;
00072                     unsigned char* prop_return = 0;
00073                     Atom a;
00074                     Window w = XDefaultRootWindow(disp);
00075                     if (w)
00076                     {
00077                         XGetWindowProperty(disp, w, atom, 0, INT_MAX, False,
00078                             AnyPropertyType,
00079                             &a, &actual_format_return, &nitems_return,
00080                             &bytes_after_return, &prop_return);
00081                         if (nitems_return && prop_return)
00082                         {
00083                             cmsHPROFILE profile = cmsOpenProfileFromMem(prop_return, nitems_return);
00084                             XFree(prop_return);
00085                             if (profile != NULL)
00086                             {
00087                                 return profile;
00088                             };
00089                         };
00090                     };
00091                 };
00092                 return NULL;
00093             }
00094 
00095             // retrieve monitor profile from X system
00096             // TODO: support for multi-monitor setups
00097             void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
00098             {
00099                 Display *disp = XOpenDisplay(0);
00100                 if (disp)
00101                 {
00102                     // when using libXcm we should also use
00103                     // profile = GetProfileFromAtom(disp, "_ICC_DEVICE_PROFILE");
00104                     // profile = GetProfileFromAtom(disp, XCM_ICC_COLOUR_SERVER_TARGET_PROFILE_IN_X_BASE)
00105                     // but in this case we need to update the code to take X11/Xcm/Xcm.h XcolorRegion
00106                     // into account
00107                     profile = GetProfileFromAtom(disp, "_ICC_PROFILE");
00108                     if (profile != NULL)
00109                     {
00110                         profileName = wxString(hugin_utils::GetICCDesc(profile).c_str(), wxConvLocal);
00111                     }
00112                     XSync(disp, False);
00113                     XCloseDisplay(disp);
00114                 };
00115             };
00116 #elif defined __WXMAC__
00117             // retrieve monitor profile for Mac
00118             typedef struct {
00119                 CFUUIDRef dispuuid;
00120                 CFURLRef url;
00121             } ColorsyncIteratorData;
00122 
00123             static bool ColorSyncIterateCallback(CFDictionaryRef dict, void *data)
00124             {
00125                 ColorsyncIteratorData *iterData = (ColorsyncIteratorData *)data;
00126                 CFStringRef str;
00127                 CFUUIDRef uuid;
00128                 CFBooleanRef iscur;
00129 
00130                 if (!CFDictionaryGetValueIfPresent(dict, kColorSyncDeviceClass, (const void**)&str))
00131                 {
00132                     DEBUG_INFO("kColorSyncDeviceClass failed");
00133                     return true;
00134                 }
00135                 if (!CFEqual(str, kColorSyncDisplayDeviceClass))
00136                 {
00137                     return true;
00138                 }
00139                 if (!CFDictionaryGetValueIfPresent(dict, kColorSyncDeviceID, (const void**)&uuid))
00140                 {
00141                     DEBUG_INFO("kColorSyncDeviceID failed");
00142                     return true;
00143                 }
00144                 if (!CFEqual(uuid, iterData->dispuuid))
00145                 {
00146                     return true;
00147                 }
00148                 if (!CFDictionaryGetValueIfPresent(dict, kColorSyncDeviceProfileIsCurrent, (const void**)&iscur))
00149                 {
00150                     DEBUG_INFO("kColorSyncDeviceProfileIsCurrent failed");
00151                     return true;
00152                 }
00153                 if (!CFBooleanGetValue(iscur))
00154                 {
00155                     return true;
00156                 }
00157                 if (!CFDictionaryGetValueIfPresent(dict, kColorSyncDeviceProfileURL, (const void**)&(iterData->url)))
00158                 {
00159                     DEBUG_INFO("Could not get current profile URL");
00160                     return true;
00161                 }
00162                 CFRetain(iterData->url);
00163                 return false;
00164             }
00165 
00166             void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
00167             {
00168                 ColorsyncIteratorData data;
00169                 data.dispuuid = CGDisplayCreateUUIDFromDisplayID(CGMainDisplayID());
00170                 if (data.dispuuid == NULL)
00171                 {
00172                     DEBUG_INFO("CGDisplayCreateUUIDFromDisplayID() failed.");
00173                     return;
00174                 }
00175                 data.url = NULL;
00176                 ColorSyncIterateDeviceProfiles(ColorSyncIterateCallback, (void *)&data);
00177                 CFRelease(data.dispuuid);
00178 
00179                 CFStringRef urlstr = CFURLCopyFileSystemPath(data.url, kCFURLPOSIXPathStyle);
00180                 CFRelease(data.url);
00181                 if (urlstr == NULL)
00182                 {
00183                     DEBUG_INFO("Failed to get URL in CFString");
00184                 }
00185                 else
00186                 {
00187                     CFRetain(urlstr);
00188                     profileName = wxCFStringRef(urlstr).AsString(wxLocale::GetSystemEncoding());
00189                     profile = cmsOpenProfileFromFile(profileName.c_str(), "r");
00190                     DEBUG_INFO("Found profile: " << profileName.c_str());
00191                 };
00192             };
00193 #else
00194             // general case, does nothing
00195             void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
00196             {
00197             };
00198 #endif
00199         }
00200 
00201         void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
00202         {
00203             if (profile != NULL)
00204             {
00205                 cmsCloseProfile(profile);
00206             }
00207             profileName.Clear();
00208             profile = NULL;
00209             detail::GetMonitorProfile(profileName, profile);
00210             // check if monitor profile could be successful loaded, if not switch back to default sRGB profile
00211             if (profile == NULL)
00212             {
00213                 profile = cmsCreate_sRGBProfile();
00214                 profileName.Clear();
00215             };
00216         };
00217 
00218         void CorrectImage(wxImage& image, const vigra::ImageImportInfo::ICCProfile& iccProfile, const cmsHPROFILE& monitorProfile)
00219         {
00220             cmsHPROFILE inputICC = NULL;
00221             if (!iccProfile.empty())
00222             {
00223                 inputICC = cmsOpenProfileFromMem(iccProfile.data(), iccProfile.size());
00224             };
00225             // check type of input profile
00226             if (inputICC != NULL)
00227             {
00228                 if (cmsGetColorSpace(inputICC) != cmsSigRgbData)
00229                 {
00230                     cmsCloseProfile(inputICC);
00231                     inputICC = NULL;
00232                 };
00233             };
00234             // if there is no icc profile in file fall back to sRGB
00235             if (inputICC == NULL)
00236             {
00237                 inputICC = cmsCreate_sRGBProfile();
00238             };
00239             // now build transform
00240             cmsHTRANSFORM transform = cmsCreateTransform(inputICC, TYPE_RGB_8,
00241                 monitorProfile, TYPE_RGB_8,
00242                 INTENT_PERCEPTUAL, cmsFLAGS_BLACKPOINTCOMPENSATION);
00243             // check that we could get a valid transform
00244             if (transform != NULL)
00245             {
00246                 unsigned char* imgData = image.GetData();
00247                 const int imgWidth = image.GetWidth();
00248                 const int imgHeight = image.GetHeight();
00249 #pragma omp parallel for
00250                 for (int y = 0; y < imgHeight; ++y)
00251                 {
00252                     cmsDoTransform(transform, imgData + 3 * y * imgWidth, imgData + 3 * y * imgWidth, imgWidth);
00253                 };
00254                 cmsDeleteTransform(transform);
00255             };
00256             cmsCloseProfile(inputICC);
00257         };
00258 
00259     }; // namespace Color
00260 }; // namespace HuginBase

Generated on 23 Jan 2018 for Hugintrunk by  doxygen 1.4.7