1 /* separate+ 0.5 - image processing plug-in for the Gimp
2 *
3 * Copyright (C) 2002-2004 Alastair Robinson (blackfive@fakenhamweb.co.uk),
4 * Based on code by Andrew Kieschnick and Peter Kirchgessner
5 * 2007-2010 Modified by Yoshinori Yamakawa (yamma-ma@users.sourceforge.jp)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28
29 #include <libgimp/gimp.h>
30
31 #include "platform.h"
32
33 #include "separate.h"
34 #include "util.h"
35
36 static char *separate_channelnames[] = {"C", "M", "Y", "K"};
37
38 static gboolean
check_layer_name(char * layer_name,gint * mask)39 check_layer_name (char *layer_name,
40 gint *mask)
41 {
42 if ((((*mask) & 16) == 0) && (strcmp (layer_name, _("Background")) == 0))
43 {
44 *mask |= 16;
45 return TRUE;
46 }
47 if ((((*mask) & 1) == 0) && (strcmp (layer_name, "C") == 0))
48 {
49 *mask |= 1;
50 return TRUE;
51 }
52 if ((((*mask) & 2) == 0) && (strcmp (layer_name, "M") == 0))
53 {
54 *mask |= 2;
55 return TRUE;
56 }
57 if ((((*mask) & 4) == 0) && (strcmp (layer_name, "Y") == 0))
58 {
59 *mask |= 4;
60 return TRUE;
61 }
62 if ((((*mask) & 8) == 0) && (strcmp (layer_name, "K") == 0))
63 {
64 *mask |= 8;
65 return TRUE;
66 }
67 return FALSE;
68 }
69
70
71 GimpDrawable *
separate_find_channel(gint32 image_id,enum separate_channel channel)72 separate_find_channel (gint32 image_id,
73 enum separate_channel channel)
74 {
75 GimpDrawable *result=NULL;
76 gint *layers, layercount;
77 gint i;
78
79 if ((channel < 0) || (channel > 3))
80 return NULL;
81
82 layers = gimp_image_get_layers (image_id, &layercount);
83 for (i = 0; i < layercount; ++i)
84 {
85 char *layer_name = gimp_drawable_get_name (layers[i]);
86
87 if (strcmp (layer_name, separate_channelnames[channel]) == 0)
88 {
89 result = gimp_drawable_get (layers[i]);
90 if (gimp_drawable_is_rgb (result->drawable_id))
91 result = gimp_drawable_get (gimp_layer_get_mask (layers[i]));
92
93 return result;
94 }
95 }
96
97 return result;
98 }
99
100 GimpDrawable *
separate_find_alpha(gint32 image_id)101 separate_find_alpha (gint32 image_id)
102 {
103 gint *channels, n_channels;
104 gint i;
105
106 channels = gimp_image_get_channels (image_id, &n_channels);
107
108 if (n_channels && gimp_drawable_get_visible (channels[0]))
109 return gimp_drawable_get (channels[0]);
110 else
111 return NULL;
112 }
113
114
115 gboolean
separate_is_CMYK(gint32 image_id)116 separate_is_CMYK (gint32 image_id)
117 {
118 gint *layers, layercount;
119 gint i;
120 gint mask = 0;
121
122 layers = gimp_image_get_layers (image_id, &layercount);
123
124 if (layercount > 5)
125 return FALSE;
126
127 for (i = 0; i < layercount; ++i)
128 {
129 char *layer_name = gimp_drawable_get_name (layers[i]);
130
131 if (check_layer_name (layer_name, &mask) == FALSE)
132 return FALSE;
133 }
134
135 if (mask == 0 || mask == 16)
136 return FALSE;
137
138 return TRUE;
139 }
140
141
142 void
separate_init_settings(SeparateContext * sc,enum separate_function func,gboolean get_last_values)143 separate_init_settings (SeparateContext *sc,
144 enum separate_function func,
145 gboolean get_last_values)
146 {
147 #ifdef ENABLE_COLOR_MANAGEMENT
148 GimpColorConfig *config;
149 #endif
150
151 memset (sc, '\0', sizeof (SeparateContext));
152
153 /* set default values */
154 switch (func)
155 {
156 case SEP_LIGHT:
157 case SEP_FULL:
158 case SEP_SEPARATE:
159 case SEP_PROOF:
160 #ifdef ENABLE_COLOR_MANAGEMENT
161 if ((config = gimp_get_color_configuration()))
162 {
163 g_object_get (config,
164 "display-profile", &(sc->alt_displayfilename),
165 "rgb-profile", &(sc->alt_rgbfilename),
166 "cmyk-profile", &(sc->alt_cmykfilename),
167 "printer-profile", &(sc->alt_prooffilename),
168 "display-rendering-intent", &(sc->ps.mode),
169 "simulation-rendering-intent", &(sc->ss.intent),
170 NULL);
171 if (sc->ps.mode >= 2)
172 sc->ps.mode--;
173 }
174 g_object_unref (G_OBJECT (config));
175 #endif
176
177 if (!(sc->alt_displayfilename))
178 sc->alt_displayfilename = DEFAULT_RGB_PROFILE;
179 if (!(sc->alt_rgbfilename))
180 sc->alt_rgbfilename = DEFAULT_RGB_PROFILE;
181 if (!(sc->alt_cmykfilename))
182 sc->alt_cmykfilename = DEFAULT_CMYK_PROFILE;
183 if (!(sc->alt_prooffilename))
184 sc->alt_prooffilename = DEFAULT_CMYK_PROFILE;
185
186 sc->ss.profile = TRUE;
187 sc->ps.profile = TRUE;
188
189 break;
190 case SEP_SAVE:
191 case SEP_EXPORT:
192 #ifdef ENABLE_COLOR_MANAGEMENT
193 if ((config = gimp_get_color_configuration()))
194 {
195 g_object_get (config,
196 "cmyk-profile", &(sc->cmykfilename),
197 "printer-profile", &(sc->prooffilename),
198 NULL);
199 }
200 g_object_unref (G_OBJECT (config));
201 #endif
202 break;
203 case SEP_DUOTONE:
204 default:
205 break;
206 }
207
208 /* get last values */
209 if (get_last_values)
210 {
211 gint size;
212
213 switch (func)
214 {
215 /* TODO : g_free ()やNULL値の設定が必要でないことの検証 */
216 case SEP_LIGHT:
217 case SEP_FULL:
218 case SEP_SEPARATE:
219 if ((size = gimp_get_data_size ("separate_rgbprofile")))
220 {
221 g_free (sc->rgbfilename);
222 sc->rgbfilename = g_new (gchar, size);
223 gimp_get_data ("separate_rgbprofile", sc->rgbfilename);
224 }
225 g_free (sc->cmykfilename);
226 if ((size = gimp_get_data_size ("separate_cmykprofile")) > 1)
227 {
228 sc->cmykfilename = g_new (gchar, size);
229 gimp_get_data ("separate_cmykprofile", sc->cmykfilename);
230 }
231 else
232 sc->cmykfilename = NULL;
233 gimp_get_data ("separate_settings", &(sc->ss));
234 break;
235 case SEP_PROOF:
236 if ((size = gimp_get_data_size ("separate_displayprofile")))
237 {
238 g_free (sc->displayfilename );
239 sc->displayfilename = g_new (gchar, size);
240 gimp_get_data ("separate_displayprofile", sc->displayfilename);
241 }
242 if ((size = gimp_get_data_size ("separate_proofprofile")))
243 {
244 g_free (sc->prooffilename);
245 sc->prooffilename = g_new (gchar, size);
246 gimp_get_data ("separate_proofprofile", sc->prooffilename);
247 }
248 gimp_get_data( "separate_proofsettings", &( sc->ps ) );
249 break;
250 case SEP_EXPORT:
251 gimp_get_data ("separate_exportsettings", &(sc->sas));
252 break;
253 default:
254 break;
255 }
256 }
257 }
258
259 void
separate_store_settings(SeparateContext * sc,enum separate_function func)260 separate_store_settings (SeparateContext *sc,
261 enum separate_function func)
262 {
263 switch( func ) {
264 case SEP_SEPARATE:
265 case SEP_FULL:
266 case SEP_LIGHT:
267 if( sc->rgbfilename )
268 gimp_set_data( "separate_rgbprofile", sc->rgbfilename, strlen( sc->rgbfilename ) + 1 );
269 if( sc->cmykfilename )
270 gimp_set_data( "separate_cmykprofile", sc->cmykfilename, strlen( sc->cmykfilename ) + 1 );
271 else
272 gimp_set_data( "separate_cmykprofile", "", 1);
273 gimp_set_data( "separate_settings", &( sc->ss ), sizeof( SeparateSettings ) );
274 break;
275 case SEP_PROOF:
276 if( sc->displayfilename )
277 gimp_set_data( "separate_displayprofile", sc->displayfilename, strlen( sc->displayfilename ) + 1 );
278 if( sc->prooffilename )
279 gimp_set_data( "separate_proofprofile", sc->prooffilename, strlen( sc->prooffilename ) + 1 );
280 gimp_set_data( "separate_proofsettings", &( sc->ps ), sizeof( ProofSettings ) );
281 break;
282 case SEP_EXPORT:
283 gimp_set_data ("separate_exportsettings", &(sc->sas), sizeof (SaveSettings));
284 break;
285 default:
286 break;
287 }
288 }
289
290 /* Create a normal RGB image for proof...*/
291 gint32
separate_create_RGB(gchar * filename,guint width,guint height,gboolean has_alpha,gint32 * layers)292 separate_create_RGB (gchar *filename,
293 guint width,
294 guint height,
295 gboolean has_alpha,
296 gint32 *layers)
297 {
298 gint32 image_id;
299
300 image_id = gimp_image_new (width, height, GIMP_RGB);
301 gimp_image_undo_disable (image_id);
302 gimp_image_set_filename (image_id, filename);
303
304 if (has_alpha)
305 layers[0] = gimp_layer_new (image_id, _("Layer 1"), width, height,
306 GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
307 else
308 layers[0] = gimp_layer_new (image_id, _("Background"), width, height,
309 GIMP_RGB_IMAGE, 100, GIMP_NORMAL_MODE);
310
311 gimp_image_add_layer (image_id, layers[0], -1);
312
313 return image_id;
314 }
315
316
317 /* Create an image with four greyscale layers, to be used as CMYK channels...*/
318 gint32
separate_create_planes_grey(gchar * filename,guint width,guint height,gint32 * layers)319 separate_create_planes_grey (gchar *filename,
320 guint width,
321 guint height,
322 gint32 *layers)
323 {
324 gint32 image_id;
325
326 image_id = gimp_image_new (width, height, GIMP_GRAY);
327 gimp_image_undo_disable (image_id);
328 gimp_image_set_filename (image_id, filename);
329
330 layers[0] = gimp_layer_new (image_id, "K", width, height,
331 GIMP_GRAY_IMAGE, 100, GIMP_NORMAL_MODE);
332 gimp_image_add_layer (image_id, layers[0], -1);
333 layers[1] = gimp_layer_new (image_id, "Y", width, height,
334 GIMP_GRAY_IMAGE, 100, GIMP_NORMAL_MODE);
335 gimp_image_add_layer (image_id, layers[1], -1);
336 layers[2] = gimp_layer_new (image_id, "M", width, height,
337 GIMP_GRAY_IMAGE, 100, GIMP_NORMAL_MODE);
338 gimp_image_add_layer (image_id, layers[2], -1);
339 layers[3] = gimp_layer_new (image_id, "C", width, height,
340 GIMP_GRAY_IMAGE, 100, GIMP_NORMAL_MODE);
341 gimp_image_add_layer (image_id, layers[3], -1);
342
343 return image_id;
344 }
345
346
347 /* Create an image with four colour layers with masks, to be used as CMYK channels...*/
348 gint32
separate_create_planes_CMYK(gchar * filename,guint width,guint height,gint32 * layers,guchar * primaries)349 separate_create_planes_CMYK (gchar *filename,
350 guint width,
351 guint height,
352 gint32 *layers,
353 guchar *primaries)
354 {
355 gint32 image_id;
356 gint32 background_id;
357 gint counter;
358 GimpRGB rgb;
359
360 image_id = gimp_image_new (width, height, GIMP_RGB);
361 gimp_image_undo_disable (image_id);
362 gimp_image_set_filename (image_id, filename);
363
364 background_id = gimp_layer_new (image_id, _("Background"), width, height,
365 GIMP_RGB_IMAGE, 100, GIMP_NORMAL_MODE);
366 gimp_image_add_layer (image_id, background_id, -1);
367 layers[0] = gimp_layer_new (image_id, "K", width, height,
368 GIMP_RGBA_IMAGE, 100, GIMP_DARKEN_ONLY_MODE);
369 gimp_image_add_layer (image_id, layers[0], -1);
370 layers[1] = gimp_layer_new (image_id, "Y", width, height,
371 GIMP_RGBA_IMAGE, 100, GIMP_DARKEN_ONLY_MODE);
372 gimp_image_add_layer (image_id, layers[1], -1);
373 layers[2] = gimp_layer_new (image_id, "M", width, height,
374 GIMP_RGBA_IMAGE, 100, GIMP_DARKEN_ONLY_MODE);
375 gimp_image_add_layer (image_id, layers[2], -1);
376 layers[3] = gimp_layer_new (image_id, "C", width, height,
377 GIMP_RGBA_IMAGE, 100, GIMP_DARKEN_ONLY_MODE);
378 gimp_image_add_layer (image_id, layers[3], -1);
379
380 gimp_context_push ();
381
382 for (counter = 0; counter < 4; counter++)
383 {
384 gimp_rgb_set_uchar (&rgb, primaries[0], primaries[1], primaries[2]);
385 gimp_context_set_foreground (&rgb);
386 primaries += 3;
387
388 gimp_drawable_fill (layers[counter], GIMP_FOREGROUND_FILL);
389 }
390
391 rgb.r = rgb.g = rgb.b = 1.0;
392 gimp_context_set_foreground (&rgb);
393 gimp_drawable_fill (background_id, GIMP_FOREGROUND_FILL);
394
395 gimp_context_pop ();
396
397 return image_id;
398 }
399
400
401 /* Create an image with two colour layers with masks, to be used as MK duotone channels...*/
402 gint32
separate_create_planes_Duotone(gchar * filename,guint width,guint height,gint32 * layers)403 separate_create_planes_Duotone (gchar *filename,
404 guint width,
405 guint height,
406 gint32 *layers)
407 {
408 gint32 image_id;
409 gint32 background_id;
410 GimpRGB rgb = {0};
411
412 image_id = gimp_image_new (width, height, GIMP_RGB);
413 gimp_image_undo_disable (image_id);
414 gimp_image_set_filename (image_id, filename);
415
416 background_id = gimp_layer_new (image_id, _("Background"), width, height,
417 GIMP_RGB_IMAGE, 100, GIMP_NORMAL_MODE);
418 gimp_image_add_layer (image_id, background_id, -1);
419
420 layers[0] = gimp_layer_new (image_id, "K", width, height,
421 GIMP_RGBA_IMAGE, 100, GIMP_DARKEN_ONLY_MODE);
422 gimp_image_add_layer (image_id, layers[0], -1);
423
424 layers[1] = gimp_layer_new (image_id, "M", width, height,
425 GIMP_RGBA_IMAGE, 100, GIMP_DARKEN_ONLY_MODE);
426 gimp_image_add_layer (image_id, layers[1], -1);
427
428 gimp_context_push ();
429
430 gimp_context_set_foreground (&rgb);
431 gimp_drawable_fill (layers[0], GIMP_FOREGROUND_FILL);
432
433 rgb.r = 1.0;
434 gimp_context_set_foreground (&rgb);
435 gimp_drawable_fill (layers[1], GIMP_FOREGROUND_FILL);
436
437 rgb.r = rgb.g = rgb.b = 1.0;
438 gimp_context_set_foreground (&rgb);
439 gimp_drawable_fill (background_id, GIMP_FOREGROUND_FILL);
440
441 gimp_context_pop ();
442
443 return image_id;
444 }
445
446
447 char *
separate_build_filename(char * root,char * suffix)448 separate_build_filename (char *root,
449 char *suffix)
450 {
451 /* Build a filename like <imagename>-<channel>.<extension> */
452 char *filename;
453 char *extension;
454 root = g_strdup (root);
455 extension = root + strlen (root) - 1;
456
457 while (extension >= root)
458 {
459 if (*extension == '.')
460 break;
461
462 extension--;
463 }
464
465 if (extension >= root)
466 {
467 *(extension++) = '\0';
468 filename = g_strdup_printf ("%s-%s.%s", root, suffix, extension);
469 }
470 else
471 filename = g_strdup_printf ("%s-%s", root, suffix);
472
473 g_free (root);
474
475 return filename;
476 }
477
478
479 char *
separate_filename_add_suffix(char * root,char * suffix)480 separate_filename_add_suffix (char *root,
481 char *suffix)
482 {
483 /* Build a filename like <imagename>-<channel>.<extension> */
484 char *filename;
485 char *extension;
486
487 if (root == NULL)
488 return g_strdup_printf (_("Untitled-%s.tif"), suffix);
489
490 root = g_strdup (root);
491 extension = root + strlen (root) - 1;
492
493 while (extension >= root)
494 {
495 if (*extension == '.') break;
496 extension--;
497 }
498 if (extension >= root)
499 {
500 *(extension++) = '\0';
501 }
502
503 filename = g_strdup_printf ("%s-%s.tif", root, suffix);
504 g_free (root);
505
506 return filename;
507 }
508
509
510 char *
separate_filename_change_extension(char * root,char * newext)511 separate_filename_change_extension (char *root,
512 char *newext)
513 {
514 /* Change <imagename>.<extension> to <imagename>.<tif> */
515 char *filename;
516 char *extension;
517
518 root =g_strdup (root);
519 extension = root + strlen (root) - 1;
520
521 while (extension >= root)
522 {
523 if (*extension == '.')
524 break;
525
526 extension--;
527 }
528
529 if (extension >= root)
530 {
531 *extension++ = 0;
532 filename = g_strdup_printf ("%s.%s", root, newext);
533 }
534 else
535 filename = g_strdup (root);
536
537 g_free (root);
538
539 return filename;
540 }
541
542
543 gint
separate_path_get_extention_offset(gchar * filename)544 separate_path_get_extention_offset (gchar *filename)
545 {
546 gint length;
547 gint offset;
548
549 g_return_val_if_fail (filename != NULL, 0);
550
551 length = strlen (filename);
552 offset = length;
553
554 while (offset > 0)
555 {
556 if (filename[offset] == '.')
557 {
558 if (!(offset == length - 1) && !G_IS_DIR_SEPARATOR (filename[offset - 1]))
559 return offset;
560 else
561 return 0;
562 }
563
564 offset--;
565 }
566
567 return 0;
568 }
569