color-selector-cmyk.c 12.4 KB
Newer Older
1 2
/* GIMP CMYK ColorSelector using littleCMS
 * Copyright (C) 2006  Sven Neumann <sven@gimp.org>
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 8 9 10 11 12 13 14
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * 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 19
 */

#include "config.h"

20
#include <gegl.h>
21 22 23
#include <gtk/gtk.h>

#include "libgimpcolor/gimpcolor.h"
24
#include "libgimpconfig/gimpconfig.h"
25 26 27 28 29 30 31 32
#include "libgimpmodule/gimpmodule.h"
#include "libgimpwidgets/gimpwidgets.h"

#include "libgimp/libgimp-intl.h"


/* definitions and variables */

33
#define COLORSEL_TYPE_CMYK            (colorsel_cmyk_get_type ())
34 35 36 37 38 39 40 41 42 43 44
#define COLORSEL_CMYK(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), COLORSEL_TYPE_CMYK, ColorselCmyk))
#define COLORSEL_CMYK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), COLORSEL_TYPE_CMYK, ColorselCmykClass))
#define COLORSEL_IS_CMYK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), COLORSEL_TYPE_CMYK))
#define COLORSEL_IS_CMYK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), COLORSEL_TYPE_CMYK))


typedef struct _ColorselCmyk      ColorselCmyk;
typedef struct _ColorselCmykClass ColorselCmykClass;

struct _ColorselCmyk
{
45
  GimpColorSelector   parent_instance;
46

47 48 49
  GimpColorConfig    *config;
  GimpColorTransform *rgb2cmyk;
  GimpColorTransform *cmyk2rgb;
50

51 52 53
  GimpCMYK            cmyk;
  GtkAdjustment      *adj[4];
  GtkWidget          *name_label;
54

55
  gboolean            in_destruction;
56 57 58 59 60 61 62 63
};

struct _ColorselCmykClass
{
  GimpColorSelectorClass  parent_class;
};


64 65 66
static GType  colorsel_cmyk_get_type       (void);

static void   colorsel_cmyk_dispose        (GObject           *object);
67

68 69 70
static void   colorsel_cmyk_set_color      (GimpColorSelector *selector,
                                            const GimpRGB     *rgb,
                                            const GimpHSV     *hsv);
71 72 73
static void   colorsel_cmyk_set_config     (GimpColorSelector *selector,
                                            GimpColorConfig   *config);

74 75
static void   colorsel_cmyk_adj_update     (GtkAdjustment     *adj,
                                            ColorselCmyk      *module);
76
static void   colorsel_cmyk_config_changed (ColorselCmyk      *module);
77 78 79 80 81


static const GimpModuleInfo colorsel_cmyk_info =
{
  GIMP_MODULE_ABI_VERSION,
82
  N_("CMYK color selector (using color profile)"),
83
  "Sven Neumann <sven@gimp.org>",
84 85 86
  "v0.1",
  "(c) 2006, released under the GPL",
  "September 2006"
87 88
};

89 90 91

G_DEFINE_DYNAMIC_TYPE (ColorselCmyk, colorsel_cmyk,
                       GIMP_TYPE_COLOR_SELECTOR)
92 93 94 95 96 97 98 99 100 101 102


G_MODULE_EXPORT const GimpModuleInfo *
gimp_module_query (GTypeModule *module)
{
  return &colorsel_cmyk_info;
}

G_MODULE_EXPORT gboolean
gimp_module_register (GTypeModule *module)
{
103
  colorsel_cmyk_register_type (module);
104 105 106 107 108 109 110

  return TRUE;
}

static void
colorsel_cmyk_class_init (ColorselCmykClass *klass)
{
111
  GObjectClass           *object_class   = G_OBJECT_CLASS (klass);
Sven Neumann's avatar
Sven Neumann committed
112
  GimpColorSelectorClass *selector_class = GIMP_COLOR_SELECTOR_CLASS (klass);
113

114 115 116 117
  object_class->dispose      = colorsel_cmyk_dispose;

  selector_class->name       = _("CMYK");
  selector_class->help_id    = "gimp-colorselector-cmyk";
118
  selector_class->icon_name  = GIMP_ICON_COLOR_SELECTOR_CMYK;
119 120
  selector_class->set_color  = colorsel_cmyk_set_color;
  selector_class->set_config = colorsel_cmyk_set_config;
121 122

  gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (klass), "ColorselCmyk");
123 124
}

125 126 127 128 129
static void
colorsel_cmyk_class_finalize (ColorselCmykClass *klass)
{
}

130 131 132
static void
colorsel_cmyk_init (ColorselCmyk *module)
{
133 134
  GtkWidget *grid;
  gint       i;
135

136
  static const gchar * const cmyk_labels[] =
137
  {
138
    /* Cyan        */
139
    N_("_C"),
140
    /* Magenta     */
141
    N_("_M"),
142
    /* Yellow      */
143
    N_("_Y"),
144
    /* Key (Black) */
145 146
    N_("_K")
  };
147
  static const gchar * const cmyk_tips[] =
148 149 150 151 152 153 154
  {
    N_("Cyan"),
    N_("Magenta"),
    N_("Yellow"),
    N_("Black")
  };

155 156 157
  module->config   = NULL;
  module->rgb2cmyk = NULL;
  module->cmyk2rgb = NULL;
158

159 160
  gtk_box_set_spacing (GTK_BOX (module), 6);

161
  grid = gtk_grid_new ();
162

163 164
  gtk_grid_set_row_spacing (GTK_GRID (grid), 1);
  gtk_grid_set_column_spacing (GTK_GRID (grid), 2);
165

166 167
  gtk_box_pack_start (GTK_BOX (module), grid, FALSE, FALSE, 0);
  gtk_widget_show (grid);
168 169 170

  for (i = 0; i < 4; i++)
    {
171 172 173 174 175 176 177 178 179 180 181 182
      module->adj[i] = gimp_scale_entry_new (GTK_GRID (grid), 1, i,
                                             gettext (cmyk_labels[i]),
                                             -1, -1,
                                             0.0,
                                             0.0, 100.0,
                                             1.0, 10.0,
                                             0,
                                             TRUE, 0.0, 0.0,
                                             gettext (cmyk_tips[i]),
                                             NULL);

      g_signal_connect (module->adj[i], "value-changed",
183 184
                        G_CALLBACK (colorsel_cmyk_adj_update),
                        module);
185 186
    }

187
  module->name_label = gtk_label_new (NULL);
188
  gtk_label_set_xalign (GTK_LABEL (module->name_label), 0.0);
189 190 191 192 193 194 195
  gtk_label_set_ellipsize (GTK_LABEL (module->name_label), PANGO_ELLIPSIZE_END);
  gimp_label_set_attributes (GTK_LABEL (module->name_label),
                             PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
                             -1);
  gtk_box_pack_start (GTK_BOX (module), module->name_label, FALSE, FALSE, 0);
  gtk_widget_show (module->name_label);
}
196

197 198 199 200
static void
colorsel_cmyk_dispose (GObject *object)
{
  ColorselCmyk *module = COLORSEL_CMYK (object);
201

202
  module->in_destruction = TRUE;
203

204
  colorsel_cmyk_set_config (GIMP_COLOR_SELECTOR (object), NULL);
205

206
  G_OBJECT_CLASS (colorsel_cmyk_parent_class)->dispose (object);
207 208 209 210
}

static void
colorsel_cmyk_set_color (GimpColorSelector *selector,
211 212
                         const GimpRGB     *rgb,
                         const GimpHSV     *hsv)
213
{
Sven Neumann's avatar
Sven Neumann committed
214
  ColorselCmyk *module = COLORSEL_CMYK (selector);
215 216 217 218 219 220 221 222 223 224 225 226
  gdouble       values[4];
  gint          i;

  if (module->rgb2cmyk)
    {
      gdouble rgb_values[3];
      gdouble cmyk_values[4];

      rgb_values[0] = rgb->r;
      rgb_values[1] = rgb->g;
      rgb_values[2] = rgb->b;

227 228 229 230 231 232
      gimp_color_transform_process_pixels (module->rgb2cmyk,
                                           babl_format ("R'G'B' double"),
                                           rgb_values,
                                           babl_format ("CMYK double"),
                                           cmyk_values,
                                           1);
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268

      module->cmyk.c = cmyk_values[0] / 100.0;
      module->cmyk.m = cmyk_values[1] / 100.0;
      module->cmyk.y = cmyk_values[2] / 100.0;
      module->cmyk.k = cmyk_values[3] / 100.0;
    }
  else
    {
      gimp_rgb_to_cmyk (rgb, 1.0, &module->cmyk);
    }

  values[0] = module->cmyk.c * 100.0;
  values[1] = module->cmyk.m * 100.0;
  values[2] = module->cmyk.y * 100.0;
  values[3] = module->cmyk.k * 100.0;

  for (i = 0; i < 4; i++)
    {
      g_signal_handlers_block_by_func (module->adj[i],
                                       colorsel_cmyk_adj_update,
                                       module);

      gtk_adjustment_set_value (module->adj[i], values[i]);

      g_signal_handlers_unblock_by_func (module->adj[i],
                                         colorsel_cmyk_adj_update,
                                         module);
    }
}

static void
colorsel_cmyk_set_config (GimpColorSelector *selector,
                          GimpColorConfig   *config)
{
  ColorselCmyk *module = COLORSEL_CMYK (selector);

269
  if (config != module->config)
270
    {
271
      if (module->config)
272 273 274
        g_signal_handlers_disconnect_by_func (module->config,
                                              colorsel_cmyk_config_changed,
                                              module);
275

276
      g_set_object (&module->config, config);
277 278

      if (module->config)
279 280 281
        g_signal_connect_swapped (module->config, "notify",
                                  G_CALLBACK (colorsel_cmyk_config_changed),
                                  module);
282 283

      colorsel_cmyk_config_changed (module);
284
    }
285 286 287 288
}

static void
colorsel_cmyk_adj_update (GtkAdjustment *adj,
289
                          ColorselCmyk  *module)
290
{
Sven Neumann's avatar
Sven Neumann committed
291
  GimpColorSelector *selector = GIMP_COLOR_SELECTOR (module);
292
  gint               i;
293
  gdouble            value;
294 295 296 297 298

  for (i = 0; i < 4; i++)
    if (module->adj[i] == adj)
      break;

299
  value = gtk_adjustment_get_value (adj) / 100.0;
300

301 302 303
  switch (i)
    {
    case 0:
304
      module->cmyk.c = value;
305 306
      break;
    case 1:
307
      module->cmyk.m = value;
308 309
      break;
    case 2:
310
      module->cmyk.y = value;
311 312
      break;
    case 3:
313
      module->cmyk.k = value;
314 315 316 317 318
      break;
    default:
      return;
    }

319 320 321 322 323 324 325 326 327 328
  if (module->cmyk2rgb)
    {
      gdouble cmyk_values[4];
      gdouble rgb_values[3];

      cmyk_values[0] = module->cmyk.c * 100.0;
      cmyk_values[1] = module->cmyk.m * 100.0;
      cmyk_values[2] = module->cmyk.y * 100.0;
      cmyk_values[3] = module->cmyk.k * 100.0;

329
      gimp_color_transform_process_pixels (module->cmyk2rgb,
330 331 332 333 334
                                           babl_format ("CMYK double"),
                                           cmyk_values,
                                           babl_format ("R'G'B' double"),
                                           rgb_values,
                                           1);
335 336 337 338 339 340 341 342 343 344

      selector->rgb.r = rgb_values[0];
      selector->rgb.g = rgb_values[1];
      selector->rgb.b = rgb_values[2];
    }
  else
    {
      gimp_cmyk_to_rgb (&module->cmyk, &selector->rgb);
    }

345 346 347 348
  gimp_rgb_to_hsv (&selector->rgb, &selector->hsv);

  gimp_color_selector_color_changed (selector);
}
349 350

static void
351
colorsel_cmyk_config_changed (ColorselCmyk *module)
352
{
353 354 355 356 357 358
  GimpColorSelector       *selector     = GIMP_COLOR_SELECTOR (module);
  GimpColorConfig         *config       = module->config;
  GimpColorTransformFlags  flags        = 0;
  GimpColorProfile        *rgb_profile  = NULL;
  GimpColorProfile        *cmyk_profile = NULL;
  gchar                   *text;
359 360 361

  if (module->rgb2cmyk)
    {
362
      g_object_unref (module->rgb2cmyk);
363 364 365 366 367
      module->rgb2cmyk = NULL;
    }

  if (module->cmyk2rgb)
    {
368
      g_object_unref (module->cmyk2rgb);
369 370 371 372 373 374 375 376 377
      module->cmyk2rgb = NULL;
    }

  gtk_label_set_text (GTK_LABEL (module->name_label), _("Profile: (none)"));
  gimp_help_set_help_data (module->name_label, NULL, NULL);

  if (! config)
    goto out;

378
  cmyk_profile = gimp_color_config_get_cmyk_color_profile (config, NULL);
379
  if (! cmyk_profile)
380 381
    goto out;

382
  rgb_profile = gimp_color_profile_new_rgb_srgb ();
383

384 385
  text = g_strdup_printf (_("Profile: %s"),
                          gimp_color_profile_get_label (cmyk_profile));
386
  gtk_label_set_text (GTK_LABEL (module->name_label), text);
387
  g_free (text);
388 389 390 391

  gimp_help_set_help_data (module->name_label,
                           gimp_color_profile_get_summary (cmyk_profile),
                           NULL);
392

393
  flags |= GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE;
394
  flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION;
395

396 397 398 399
  module->rgb2cmyk = gimp_color_transform_new (rgb_profile,
                                               babl_format ("R'G'B' double"),
                                               cmyk_profile,
                                               babl_format ("CMYK double"),
400
                                               GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
401 402 403 404 405
                                               flags);
  module->cmyk2rgb = gimp_color_transform_new (cmyk_profile,
                                               babl_format ("CMYK double"),
                                               rgb_profile,
                                               babl_format ("R'G'B' double"),
406
                                               GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
407
                                               flags);
408 409

 out:
410 411

  if (rgb_profile)
412
    g_object_unref (rgb_profile);
413 414

  if (cmyk_profile)
415
    g_object_unref (cmyk_profile);
416

417 418
  if (! module->in_destruction)
    colorsel_cmyk_set_color (selector, &selector->rgb, &selector->hsv);
419
}