• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (c) 2011-2013, Richard Hughes
3 Copyright (c) 2014, Joseph Simon
4 
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
12 
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 
24 MIT Open Source License  -  http://www.opensource.org/
25 
26 */
27 
28 
29 #include "colormanager.h"
30 #include <cupsfilters/colord.h>
31 //#include <cupsfilters/kmdevices.h>
32 
33 
34 #define CM_MAX_FILE_LENGTH 1024
35 
36 
37 /* Private function prototypes */
38 static int      _get_colord_printer_cm_status   (const char *printer_name);
39 static char    *_get_colord_printer_id          (const char *printer_name);
40 static int      _get_colord_profile             (const char *printer_name,
41                                                  char **profile,
42                                                  ppd_file_t *ppd);
43 static char    *_get_ppd_icc_fallback           (ppd_file_t *ppd,
44                                                  char **qualifier);
45 
46 
47 
48 /* Commonly-used calibration numbers */
49 
50 double           adobergb_wp[3] = {0.95045471, 1.0, 1.08905029};
51 double              sgray_wp[3] = {0.9505, 1, 1.0890};
52 double        adobergb_gamma[3] = {2.2, 2.2, 2.2};
53 double           sgray_gamma[1] = {2.2};
54 double       adobergb_matrix[9] = {0.60974121, 0.20527649, 0.14918518,
55                                    0.31111145, 0.62567139, 0.06321716,
56                                    0.01947021, 0.06086731, 0.74456787};
57 double    blackpoint_default[3] = {0.0, 0.0, 0.0};
58 
59 
60 
61 
62 /*
63  * Public functions
64  */
65 
66 
67 /* Get printer color management status from the system's color manager */
68 int
cmIsPrinterCmDisabled(const char * printer_name)69 cmIsPrinterCmDisabled(const char *printer_name)    /* dest name */
70 {
71 
72     int is_cm_off = 0;          /* color management status flag */
73 
74 
75     /* Request color management status from colord */
76     is_cm_off = _get_colord_printer_cm_status(printer_name);
77 
78     if (is_cm_off)
79       fprintf(stderr,"DEBUG: Color Manager: Color management disabled by OS.\n");
80 
81     return is_cm_off;
82 
83 }
84 
85 
86 /* Get printer ICC profile from the system's color manager */
87 int
cmGetPrinterIccProfile(const char * printer_name,char ** icc_profile,ppd_file_t * ppd)88 cmGetPrinterIccProfile(const char *printer_name,  /* Printer name (usually "dest" name) */
89                        char **icc_profile,        /* ICC Profile Path */
90                        ppd_file_t *ppd)           /* Optional PPD file for fallback profile */
91 {
92 
93     int profile_set = 0;        /* 'is profile found' flag */
94 
95 
96     /* Request a profile from colord */
97     profile_set = _get_colord_profile(printer_name, icc_profile, ppd);
98 
99     fprintf(stderr, "DEBUG: Color Manager: ICC Profile: %s\n", *icc_profile ?
100         *icc_profile : "None");
101 
102     return profile_set;
103 
104 }
105 
106 
107 /* Find the "cm-calibration" CUPS option */
108 cm_calibration_t
cmGetCupsColorCalibrateMode(cups_option_t * options,int num_options)109 cmGetCupsColorCalibrateMode(cups_option_t *options,    /* Options from CUPS */
110                             int num_options)           /* Options from CUPS */
111 {
112 
113     cm_calibration_t status;     /* color management status */
114 
115 
116     /* Find the string in CUPS options and */
117     if (cupsGetOption(CM_CALIBRATION_STRING, num_options, options) != NULL)
118       status = CM_CALIBRATION_ENABLED;
119     else
120       status = CM_CALIBRATION_DISABLED;
121 
122     fprintf(stderr, "DEBUG: Color Manager: %s\n", status ?
123            "Calibration Mode/Enabled" : "Calibration Mode/Off");
124 
125     return status;
126 
127 }
128 
129 
130 /* Functions to return specific calibration data */
131 
132 
133 /* Gamma values */
134 
cmGammaAdobeRgb(void)135 double *cmGammaAdobeRgb(void)
136 {
137     return adobergb_gamma;
138 }
cmGammaSGray(void)139 double *cmGammaSGray(void)
140 {
141     return sgray_gamma;
142 }
143 
144 
145 /* Whitepoint values */
146 
cmWhitePointAdobeRgb(void)147 double *cmWhitePointAdobeRgb(void)
148 {
149     return adobergb_wp;
150 }
cmWhitePointSGray(void)151 double *cmWhitePointSGray(void)
152 {
153     return sgray_wp;
154 }
155 
156 
157 /* Adapted primaries matrix */
158 
cmMatrixAdobeRgb(void)159 double *cmMatrixAdobeRgb(void)
160 {
161     return adobergb_matrix;
162 }
163 
164 
165 /* Blackpoint value */
166 
cmBlackPointDefault(void)167 double *cmBlackPointDefault(void)
168 {
169     return blackpoint_default;
170 }
171 
172 
173 
174 
175 /*
176  * Private functions
177  */
178 
179 
180 char *
_get_colord_printer_id(const char * printer_name)181 _get_colord_printer_id(const char *printer_name)         /* Dest name */
182 {
183 
184     if (printer_name == NULL) {
185       fprintf(stderr, "DEBUG: Color Manager: Invalid printer name.\n");
186       return 0;
187     }
188 
189     /* Create printer id string for colord */
190     char* printer_id = (char*)malloc(CM_MAX_FILE_LENGTH);
191     snprintf (printer_id, CM_MAX_FILE_LENGTH, "cups-%s", printer_name);
192 
193     return printer_id;
194 
195 }
196 
197 
198 int
_get_colord_printer_cm_status(const char * printer_name)199 _get_colord_printer_cm_status(const char *printer_name)  /* Dest name */
200 {
201 
202     /* If invalid input, we leave color management alone */
203     if (printer_name == NULL) {
204       fprintf(stderr, "DEBUG: Color Manager: Invalid printer name.\n");
205       return 0;
206     } else if (!strcmp(printer_name, "(null)"))
207       return 0;
208 
209     int is_printer_cm_disabled = 0;   /* color management status flag */
210     char *printer_id = 0;             /* colord printer id string */
211 
212 
213     /* Check if device is inhibited/disabled in colord  */
214     printer_id = _get_colord_printer_id(printer_name);
215     is_printer_cm_disabled = colord_get_inhibit_for_device_id (printer_id);
216 
217     if (printer_id != NULL)
218       free(printer_id);
219 
220     return is_printer_cm_disabled;
221 
222 }
223 
224 int
_get_colord_profile(const char * printer_name,char ** profile,ppd_file_t * ppd)225 _get_colord_profile(const char   *printer_name,     /* Dest name */
226                     char         **profile,         /* Requested icc profile path */
227                     ppd_file_t   *ppd)              /* PPD file */
228 {
229 
230     if (printer_name == NULL || profile == 0) {
231       fprintf(stderr, "DEBUG: Color Manager: Invalid input - Unable to find profile.\n");
232       return -1;
233     }
234 
235     int   is_profile_set = 0;        /* profile-is-found flag */
236     char  **qualifier = NULL;        /* color qualifier strings */
237     char  *icc_profile = NULL;       /* icc profile path */
238     char  *printer_id = NULL;        /* colord printer id */
239 
240 
241     /* Get color qualifier triple */
242     qualifier = colord_get_qualifier_for_ppd(ppd);
243 
244     if (qualifier != NULL) {
245       printer_id = _get_colord_printer_id(printer_name);
246       /* Get profile from colord using qualifiers */
247       icc_profile = colord_get_profile_for_device_id ((const char *)printer_id,
248 						      (const char **)qualifier);
249     }
250 
251     if (icc_profile)
252       is_profile_set = 1;
253     else if (ppd) {
254     /* Get optional fallback PPD profile */
255       icc_profile = _get_ppd_icc_fallback(ppd, qualifier);
256       if (icc_profile)
257         is_profile_set = 1;
258     }
259 
260     /* If a profile is found, we give it to the caller */
261     if (is_profile_set)
262       *profile = strdup(icc_profile);
263     else
264       *profile = 0;
265 
266     if (printer_id != NULL)
267       free(printer_id);
268 
269     if (qualifier != NULL) {
270       for (int i=0; qualifier[i] != NULL; i++)
271         free(qualifier[i]);
272       free(qualifier);
273     }
274 
275     if (icc_profile != NULL)
276       free(icc_profile);
277 
278     return is_profile_set;
279 
280 }
281 
282 
283 #ifndef CUPSDATA
284 #define CUPSDATA "/usr/share/cups"
285 #endif
286 
287 /* From gstoraster */
288 char *
_get_ppd_icc_fallback(ppd_file_t * ppd,char ** qualifier)289 _get_ppd_icc_fallback (ppd_file_t *ppd, char **qualifier)
290 {
291   char full_path[1024];
292   char *icc_profile = NULL;
293   char qualifer_tmp[1024];
294   const char *profile_key;
295   ppd_attr_t *attr;
296 
297   /* get profile attr, falling back to CUPS */
298   profile_key = "APTiogaProfile";
299   attr = ppdFindAttr(ppd, profile_key, NULL);
300   if (attr == NULL) {
301     profile_key = "cupsICCProfile";
302     attr = ppdFindAttr(ppd, profile_key, NULL);
303   }
304 
305   /* create a string for a quick comparion */
306   snprintf(qualifer_tmp, sizeof(qualifer_tmp),
307            "%s.%s.%s",
308            qualifier[0],
309            qualifier[1],
310            qualifier[2]);
311 
312   /* neither */
313   if (attr == NULL) {
314     fprintf(stderr, "INFO: Color Manager: no profiles specified in PPD\n");
315     goto out;
316   }
317 
318   /* try to find a profile that matches the qualifier exactly */
319   for (;attr != NULL; attr = ppdFindNextAttr(ppd, profile_key, NULL)) {
320     fprintf(stderr, "INFO: Color Manager: found profile %s in PPD with qualifier '%s'\n",
321             attr->value, attr->spec);
322 
323     /* invalid entry */
324     if (attr->spec == NULL || attr->value == NULL)
325       continue;
326 
327     /* expand to a full path if not already specified */
328     if (attr->value[0] != '/')
329       snprintf(full_path, sizeof(full_path),
330                "%s/profiles/%s", CUPSDATA, attr->value);
331     else {
332       strncpy(full_path, attr->value, sizeof(full_path) - 1);
333       if (strlen(attr->value) > 1023)
334         full_path[1023] = '\0';
335     }
336 
337     /* check the file exists */
338     if (access(full_path, 0)) {
339       fprintf(stderr, "INFO: Color Manager: found profile %s in PPD that does not exist\n",
340               full_path);
341       continue;
342     }
343 
344     /* matches the qualifier */
345     if (strcmp(qualifer_tmp, attr->spec) == 0) {
346       icc_profile = strdup(full_path);
347       goto out;
348     }
349   }
350 
351   /* no match */
352   if (attr == NULL) {
353     fprintf(stderr, "INFO: Color Manager: no profiles in PPD for qualifier '%s'\n",
354             qualifer_tmp);
355     goto out;
356   }
357 
358 out:
359   return icc_profile;
360 }
361 
362