1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22
23 #include "libgimpbase/gimpbase.h"
24 #include "libgimpcolor/gimpcolor.h"
25 #include "libgimpconfig/gimpconfig.h"
26 #include "libgimpmath/gimpmath.h"
27 #include "libgimpwidgets/gimpwidgets.h"
28
29 #include "display-types.h"
30
31 #include "config/gimpcoreconfig.h"
32
33 #include "gegl/gimp-babl.h"
34
35 #include "core/gimpimage.h"
36 #include "core/gimpprojectable.h"
37
38 #include "gimpdisplay.h"
39 #include "gimpdisplayshell.h"
40 #include "gimpdisplayshell-actions.h"
41 #include "gimpdisplayshell-filter.h"
42 #include "gimpdisplayshell-profile.h"
43 #include "gimpdisplayxfer.h"
44
45 #include "gimp-intl.h"
46
47
48 /* local function prototypes */
49
50 static void gimp_display_shell_profile_free (GimpDisplayShell *shell);
51
52 static void gimp_display_shell_color_config_notify (GimpColorConfig *config,
53 const GParamSpec *pspec,
54 GimpDisplayShell *shell);
55
56
57 /* public functions */
58
59 void
gimp_display_shell_profile_init(GimpDisplayShell * shell)60 gimp_display_shell_profile_init (GimpDisplayShell *shell)
61 {
62 GimpColorConfig *color_config;
63
64 color_config = GIMP_CORE_CONFIG (shell->display->config)->color_management;
65
66 shell->color_config = gimp_config_duplicate (GIMP_CONFIG (color_config));
67
68 /* use after so we are called after the profile cache is invalidated
69 * in gimp_widget_get_color_transform()
70 */
71 g_signal_connect_after (shell->color_config, "notify",
72 G_CALLBACK (gimp_display_shell_color_config_notify),
73 shell);
74 }
75
76 void
gimp_display_shell_profile_finalize(GimpDisplayShell * shell)77 gimp_display_shell_profile_finalize (GimpDisplayShell *shell)
78 {
79 g_clear_object (&shell->color_config);
80
81 gimp_display_shell_profile_free (shell);
82 }
83
84 void
gimp_display_shell_profile_update(GimpDisplayShell * shell)85 gimp_display_shell_profile_update (GimpDisplayShell *shell)
86 {
87 GimpImage *image;
88 GimpColorProfile *src_profile;
89 const Babl *src_format;
90 GimpColorProfile *filter_profile;
91 const Babl *filter_format;
92 const Babl *dest_format;
93
94 gimp_display_shell_profile_free (shell);
95
96 image = gimp_display_get_image (shell->display);
97
98 if (! image)
99 return;
100
101 src_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (shell));
102
103 if (! src_profile)
104 return;
105
106 src_format = gimp_projectable_get_format (GIMP_PROJECTABLE (image));
107
108 if (gimp_display_shell_has_filter (shell))
109 {
110 filter_format = shell->filter_format;
111 filter_profile = gimp_babl_format_get_color_profile (filter_format);
112 }
113 else
114 {
115 filter_format = src_format;
116 filter_profile = src_profile;
117 }
118
119 if (! gimp_display_shell_profile_can_convert_to_u8 (shell))
120 {
121 dest_format = shell->filter_format;
122 }
123 else
124 {
125 dest_format = babl_format ("R'G'B'A u8");
126 }
127
128 #if 0
129 g_printerr ("src_profile: %s\n"
130 "src_format: %s\n"
131 "filter_profile: %s\n"
132 "filter_format: %s\n"
133 "dest_format: %s\n",
134 gimp_color_profile_get_label (src_profile),
135 babl_get_name (src_format),
136 gimp_color_profile_get_label (filter_profile),
137 babl_get_name (filter_format),
138 babl_get_name (dest_format));
139 #endif
140
141 if (! gimp_color_transform_can_gegl_copy (src_profile, filter_profile))
142 {
143 shell->filter_transform =
144 gimp_color_transform_new (src_profile,
145 src_format,
146 filter_profile,
147 filter_format,
148 GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
149 GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION |
150 GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE);
151 }
152
153 shell->profile_transform =
154 gimp_widget_get_color_transform (gtk_widget_get_toplevel (GTK_WIDGET (shell)),
155 gimp_display_shell_get_color_config (shell),
156 filter_profile,
157 filter_format,
158 dest_format);
159
160 if (shell->filter_transform || shell->profile_transform)
161 {
162 gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH;
163 gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT;
164
165 shell->profile_data =
166 gegl_malloc (w * h * babl_format_get_bytes_per_pixel (src_format));
167
168 shell->profile_stride =
169 w * babl_format_get_bytes_per_pixel (src_format);
170
171 shell->profile_buffer =
172 gegl_buffer_linear_new_from_data (shell->profile_data,
173 src_format,
174 GEGL_RECTANGLE (0, 0, w, h),
175 GEGL_AUTO_ROWSTRIDE,
176 (GDestroyNotify) gegl_free,
177 shell->profile_data);
178 }
179 }
180
181 gboolean
gimp_display_shell_profile_can_convert_to_u8(GimpDisplayShell * shell)182 gimp_display_shell_profile_can_convert_to_u8 (GimpDisplayShell *shell)
183 {
184 GimpImage *image = gimp_display_get_image (shell->display);
185
186 if (image)
187 {
188 GimpComponentType component_type;
189
190 if (! gimp_display_shell_has_filter (shell))
191 component_type = gimp_image_get_component_type (image);
192 else
193 component_type = gimp_babl_format_get_component_type (shell->filter_format);
194
195 switch (component_type)
196 {
197 case GIMP_COMPONENT_TYPE_U8:
198 #if 0
199 /* would like to convert directly for these too, but it
200 * produces inferior results, see bug 750874
201 */
202 case GIMP_COMPONENT_TYPE_U16:
203 case GIMP_COMPONENT_TYPE_U32:
204 #endif
205 return TRUE;
206
207 default:
208 break;
209 }
210 }
211
212 return FALSE;
213 }
214
215
216 /* private functions */
217
218 static void
gimp_display_shell_profile_free(GimpDisplayShell * shell)219 gimp_display_shell_profile_free (GimpDisplayShell *shell)
220 {
221 g_clear_object (&shell->profile_transform);
222 g_clear_object (&shell->filter_transform);
223 g_clear_object (&shell->profile_buffer);
224 shell->profile_data = NULL;
225 shell->profile_stride = 0;
226 }
227
228 static void
gimp_display_shell_color_config_notify(GimpColorConfig * config,const GParamSpec * pspec,GimpDisplayShell * shell)229 gimp_display_shell_color_config_notify (GimpColorConfig *config,
230 const GParamSpec *pspec,
231 GimpDisplayShell *shell)
232 {
233 if (! strcmp (pspec->name, "mode") ||
234 ! strcmp (pspec->name, "display-rendering-intent") ||
235 ! strcmp (pspec->name, "display-use-black-point-compensation") ||
236 ! strcmp (pspec->name, "simulation-rendering-intent") ||
237 ! strcmp (pspec->name, "simulation-use-black-point-compensation") ||
238 ! strcmp (pspec->name, "simulation-gamut-check"))
239 {
240 gboolean managed = FALSE;
241 gboolean softproof = FALSE;
242 const gchar *action = NULL;
243
244 #define SET_SENSITIVE(action, sensitive) \
245 gimp_display_shell_set_action_sensitive (shell, action, sensitive);
246
247 #define SET_ACTIVE(action, active) \
248 gimp_display_shell_set_action_active (shell, action, active);
249
250 switch (gimp_color_config_get_mode (config))
251 {
252 case GIMP_COLOR_MANAGEMENT_OFF:
253 break;
254
255 case GIMP_COLOR_MANAGEMENT_DISPLAY:
256 managed = TRUE;
257 break;
258
259 case GIMP_COLOR_MANAGEMENT_SOFTPROOF:
260 managed = TRUE;
261 softproof = TRUE;
262 break;
263 }
264
265 SET_ACTIVE ("view-color-management-enable", managed);
266 SET_ACTIVE ("view-color-management-softproof", softproof);
267
268 switch (gimp_color_config_get_display_intent (config))
269 {
270 case GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL:
271 action = "view-display-intent-perceptual";
272 break;
273
274 case GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC:
275 action = "view-display-intent-relative-colorimetric";
276 break;
277
278 case GIMP_COLOR_RENDERING_INTENT_SATURATION:
279 action = "view-display-intent-saturation";
280 break;
281
282 case GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC:
283 action = "view-display-intent-absolute-colorimetric";
284 break;
285 }
286
287 SET_SENSITIVE ("view-display-intent-perceptual", managed);
288 SET_SENSITIVE ("view-display-intent-relative-colorimetric", managed);
289 SET_SENSITIVE ("view-display-intent-saturation", managed);
290 SET_SENSITIVE ("view-display-intent-absolute-colorimetric", managed);
291
292 SET_ACTIVE (action, TRUE);
293
294 SET_SENSITIVE ("view-display-black-point-compensation", managed);
295 SET_ACTIVE ("view-display-black-point-compensation",
296 gimp_color_config_get_display_bpc (config));
297
298 SET_SENSITIVE ("view-softproof-profile", softproof);
299
300 switch (gimp_color_config_get_simulation_intent (config))
301 {
302 case GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL:
303 action = "view-softproof-intent-perceptual";
304 break;
305
306 case GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC:
307 action = "view-softproof-intent-relative-colorimetric";
308 break;
309
310 case GIMP_COLOR_RENDERING_INTENT_SATURATION:
311 action = "view-softproof-intent-saturation";
312 break;
313
314 case GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC:
315 action = "view-softproof-intent-absolute-colorimetric";
316 break;
317 }
318
319 SET_SENSITIVE ("view-softproof-intent-perceptual", softproof);
320 SET_SENSITIVE ("view-softproof-intent-relative-colorimetric", softproof);
321 SET_SENSITIVE ("view-softproof-intent-saturation", softproof);
322 SET_SENSITIVE ("view-softproof-intent-absolute-colorimetric", softproof);
323
324 SET_ACTIVE (action, TRUE);
325
326 SET_SENSITIVE ("view-softproof-black-point-compensation", softproof);
327 SET_ACTIVE ("view-softproof-black-point-compensation",
328 gimp_color_config_get_simulation_bpc (config));
329
330 SET_SENSITIVE ("view-softproof-gamut-check", softproof);
331 SET_ACTIVE ("view-softproof-gamut-check",
332 gimp_color_config_get_simulation_gamut_check (config));
333 }
334
335 gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (shell));
336 }
337