Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
wxcms.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
10 /* This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This software is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public
21  * License along with this software. If not, see
22  * <http://www.gnu.org/licenses/>.
23  *
24  */
25 
26 #include "wxcms.h"
27 #include "hugin_utils/utils.h"
28 #ifdef __WXGTK__
29 #include <X11/Xlib.h>
30 #endif
31 #ifdef __WXMAC__
32 #include <ApplicationServices/ApplicationServices.h>
33 #include <CoreFoundation/CoreFoundation.h>
34 #include "wx/osx/core/cfstring.h"
35 #include <wx/osx/private.h>
36 #endif
37 
38 namespace HuginBase
39 {
40  namespace Color
41  {
42  namespace detail
43  {
44 #ifdef __WXMSW__
45  // retrieve monitor profile from Windows
46  // TODO: support for multi-monitor setups
47  void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
48  {
49  // look up monitor profile in system
50  HDC hdc = GetDC(NULL);
51  if (hdc)
52  {
53  wxChar filename[MAX_PATH];
54  DWORD len = MAX_PATH - 1;
55  if (GetICMProfile(hdc, &len, filename))
56  {
57  profileName = filename;
58  profile = cmsOpenProfileFromFile(profileName.c_str(), "r");
59  };
60  ReleaseDC(NULL, hdc);
61  };
62  };
63 #elif defined __WXGTK__
64  cmsHPROFILE GetProfileFromAtom(Display* disp, const char* prop_name)
65  {
66  Atom atom = XInternAtom(disp, prop_name, True);
67  if (atom)
68  {
69  int actual_format_return;
70  unsigned long nitems_return = 0;
71  unsigned long bytes_after_return = 0;
72  unsigned char* prop_return = 0;
73  Atom a;
74  Window w = XDefaultRootWindow(disp);
75  if (w)
76  {
77  XGetWindowProperty(disp, w, atom, 0, INT_MAX, False,
78  AnyPropertyType,
79  &a, &actual_format_return, &nitems_return,
80  &bytes_after_return, &prop_return);
81  if (nitems_return && prop_return)
82  {
83  cmsHPROFILE profile = cmsOpenProfileFromMem(prop_return, nitems_return);
84  XFree(prop_return);
85  if (profile != NULL)
86  {
87  return profile;
88  };
89  };
90  };
91  };
92  return NULL;
93  }
94 
95  // retrieve monitor profile from X system
96  // TODO: support for multi-monitor setups
97  void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
98  {
99  Display *disp = XOpenDisplay(0);
100  if (disp)
101  {
102  // when using libXcm we should also use
103  // profile = GetProfileFromAtom(disp, "_ICC_DEVICE_PROFILE");
104  // profile = GetProfileFromAtom(disp, XCM_ICC_COLOUR_SERVER_TARGET_PROFILE_IN_X_BASE)
105  // but in this case we need to update the code to take X11/Xcm/Xcm.h XcolorRegion
106  // into account
107  profile = GetProfileFromAtom(disp, "_ICC_PROFILE");
108  if (profile != NULL)
109  {
110  profileName = wxString(hugin_utils::GetICCDesc(profile).c_str(), wxConvLocal);
111  }
112  XSync(disp, False);
113  XCloseDisplay(disp);
114  };
115  };
116 #elif defined __WXMAC__
117  // retrieve monitor profile for Mac
118  typedef struct {
119  CFUUIDRef dispuuid;
120  CFURLRef url;
121  } ColorsyncIteratorData;
122 
123  static bool ColorSyncIterateCallback(CFDictionaryRef dict, void *data)
124  {
125  ColorsyncIteratorData *iterData = (ColorsyncIteratorData *)data;
126  CFStringRef str;
127  CFUUIDRef uuid;
128  CFBooleanRef iscur;
129 
130  if (!CFDictionaryGetValueIfPresent(dict, kColorSyncDeviceClass, (const void**)&str))
131  {
132  DEBUG_INFO("kColorSyncDeviceClass failed");
133  return true;
134  }
135  if (!CFEqual(str, kColorSyncDisplayDeviceClass))
136  {
137  return true;
138  }
139  if (!CFDictionaryGetValueIfPresent(dict, kColorSyncDeviceID, (const void**)&uuid))
140  {
141  DEBUG_INFO("kColorSyncDeviceID failed");
142  return true;
143  }
144  if (!CFEqual(uuid, iterData->dispuuid))
145  {
146  return true;
147  }
148  if (!CFDictionaryGetValueIfPresent(dict, kColorSyncDeviceProfileIsCurrent, (const void**)&iscur))
149  {
150  DEBUG_INFO("kColorSyncDeviceProfileIsCurrent failed");
151  return true;
152  }
153  if (!CFBooleanGetValue(iscur))
154  {
155  return true;
156  }
157  if (!CFDictionaryGetValueIfPresent(dict, kColorSyncDeviceProfileURL, (const void**)&(iterData->url)))
158  {
159  DEBUG_INFO("Could not get current profile URL");
160  return true;
161  }
162  CFRetain(iterData->url);
163  return false;
164  }
165 
166  void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
167  {
168  ColorsyncIteratorData data;
169  data.dispuuid = CGDisplayCreateUUIDFromDisplayID(CGMainDisplayID());
170  if (data.dispuuid == NULL)
171  {
172  DEBUG_INFO("CGDisplayCreateUUIDFromDisplayID() failed.");
173  return;
174  }
175  data.url = NULL;
176  ColorSyncIterateDeviceProfiles(ColorSyncIterateCallback, (void *)&data);
177  CFRelease(data.dispuuid);
178 
179  CFStringRef urlstr = CFURLCopyFileSystemPath(data.url, kCFURLPOSIXPathStyle);
180  CFRelease(data.url);
181  if (urlstr == NULL)
182  {
183  DEBUG_INFO("Failed to get URL in CFString");
184  }
185  else
186  {
187  CFRetain(urlstr);
188  profileName = wxCFStringRef(urlstr).AsString(wxLocale::GetSystemEncoding());
189  profile = cmsOpenProfileFromFile(profileName.c_str(), "r");
190  DEBUG_INFO("Found profile: " << profileName.c_str());
191  };
192  };
193 #else
194  // general case, does nothing
195  void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
196  {
197  };
198 #endif
199  }
200 
201  void GetMonitorProfile(wxString& profileName, cmsHPROFILE& profile)
202  {
203  if (profile != NULL)
204  {
205  cmsCloseProfile(profile);
206  }
207  profileName.Clear();
208  profile = NULL;
209  detail::GetMonitorProfile(profileName, profile);
210  // check if monitor profile could be successful loaded, if not switch back to default sRGB profile
211  if (profile == NULL)
212  {
213  profile = cmsCreate_sRGBProfile();
214  profileName.Clear();
215  };
216  };
217 
218  void CorrectImage(wxImage& image, const vigra::ImageImportInfo::ICCProfile& iccProfile, const cmsHPROFILE& monitorProfile)
219  {
220  cmsHPROFILE inputICC = NULL;
221  if (!iccProfile.empty())
222  {
223  inputICC = cmsOpenProfileFromMem(iccProfile.data(), iccProfile.size());
224  };
225  // check type of input profile
226  if (inputICC != NULL)
227  {
228  if (cmsGetColorSpace(inputICC) != cmsSigRgbData)
229  {
230  cmsCloseProfile(inputICC);
231  inputICC = NULL;
232  };
233  };
234  // if there is no icc profile in file fall back to sRGB
235  if (inputICC == NULL)
236  {
237  inputICC = cmsCreate_sRGBProfile();
238  };
239  // now build transform
240  cmsHTRANSFORM transform = cmsCreateTransform(inputICC, TYPE_RGB_8,
241  monitorProfile, TYPE_RGB_8,
242  INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_BLACKPOINTCOMPENSATION);
243  // check that we could get a valid transform
244  if (transform != NULL)
245  {
246  unsigned char* imgData = image.GetData();
247  const int imgWidth = image.GetWidth();
248  const int imgHeight = image.GetHeight();
249 #pragma omp parallel for
250  for (int y = 0; y < imgHeight; ++y)
251  {
252  cmsDoTransform(transform, imgData + 3 * y * imgWidth, imgData + 3 * y * imgWidth, imgWidth);
253  };
254  cmsDeleteTransform(transform);
255  };
256  cmsCloseProfile(inputICC);
257  };
258 
259  }; // namespace Color
260 }; // namespace HuginBase
#define DEBUG_INFO(msg)
Definition: utils.h:69
std::string GetICCDesc(const vigra::ImageImportInfo::ICCProfile &iccProfile)
returns description of given icc profile
Definition: utils.cpp:925
void GetMonitorProfile(wxString &profileName, cmsHPROFILE &profile)
Definition: wxcms.cpp:195
void CorrectImage(wxImage &image, const vigra::ImageImportInfo::ICCProfile &iccProfile, const cmsHPROFILE &monitorProfile)
apply color correction to given image using input iccProfile and monitor profile
Definition: wxcms.cpp:218
options wxIntPtr wxIntPtr sortData std::vector< PanoInfo > * data
void GetMonitorProfile(wxString &profileName, cmsHPROFILE &profile)
retrieve monitor profile from system
Definition: wxcms.cpp:201