color_cmds.c 66.2 KB
Newer Older
1
/* The GIMP -- an image manipulation program
2
 * Copyright (C) 1995-2003 Spencer Kimball and Peter Mattis
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (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
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

19 20
/* NOTE: This file is autogenerated by pdbgen.pl. */

21 22 23
#include "config.h"


24
#include <glib-object.h>
25

26
#include "pdb-types.h"
27
#include "gimppdb.h"
28
#include "gimpprocedure.h"
29
#include "core/gimpparamspecs.h"
30

31
#include "base/color-balance.h"
32
#include "base/colorize.h"
33
#include "base/curves.h"
34
#include "base/gimphistogram.h"
35
#include "base/gimplut.h"
36
#include "base/hue-saturation.h"
37
#include "base/levels.h"
38
#include "base/lut-funcs.h"
39 40
#include "base/pixel-processor.h"
#include "base/pixel-region.h"
41
#include "base/threshold.h"
Sven Neumann's avatar
Sven Neumann committed
42
#include "core/gimp.h"
43 44
#include "core/gimpdrawable-desaturate.h"
#include "core/gimpdrawable-equalize.h"
45
#include "core/gimpdrawable-histogram.h"
46
#include "core/gimpdrawable-invert.h"
47
#include "core/gimpdrawable-levels.h"
48 49
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
50
#include "gimp-intl.h"
51

52

53 54 55 56 57 58
static GValueArray *
brightness_contrast_invoker (GimpProcedure     *procedure,
                             Gimp              *gimp,
                             GimpContext       *context,
                             GimpProgress      *progress,
                             const GValueArray *args)
59 60 61 62 63 64
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gint32 brightness;
  gint32 contrast;

65 66 67
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  brightness = g_value_get_int (&args->values[1]);
  contrast = g_value_get_int (&args->values[2]);
68 69 70

  if (success)
    {
71 72
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable))
73
        success = FALSE;
74

75
      if (success)
76
        {
77
          gint x, y, width, height;
78

79
          /* The application should occur only within selection bounds */
80 81 82 83
          if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
            {
              GimpLut     *lut;
              PixelRegion  srcPR, destPR;
84

85 86 87
              lut = brightness_contrast_lut_new (brightness / 255.0,
                                                 contrast / 127.0,
                                                 gimp_drawable_bytes (drawable));
88

89
              pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
90
                                 x, y, width, height, FALSE);
91
              pixel_region_init (&destPR, gimp_drawable_get_shadow_tiles (drawable),
92
                                 x, y, width, height, TRUE);
93

94 95
              pixel_regions_process_parallel ((PixelProcessorFunc)
                                              gimp_lut_process,
96
                                              lut, 2, &srcPR, &destPR);
97

98 99 100 101 102
              gimp_lut_free (lut);

              gimp_drawable_merge_shadow (drawable, TRUE, _("Brightness-Contrast"));
              gimp_drawable_update (drawable, x, y, width, height);
            }
103
        }
104
    }
105

106
  return gimp_procedure_get_return_values (procedure, success);
107
}
108

109 110 111 112 113 114
static GValueArray *
levels_invoker (GimpProcedure     *procedure,
                Gimp              *gimp,
                GimpContext       *context,
                GimpProgress      *progress,
                const GValueArray *args)
115
{
116 117 118
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gint32 channel;
119 120 121 122 123
  gint32 low_input;
  gint32 high_input;
  gdouble gamma;
  gint32 low_output;
  gint32 high_output;
124

125 126 127 128 129 130 131
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  channel = g_value_get_enum (&args->values[1]);
  low_input = g_value_get_int (&args->values[2]);
  high_input = g_value_get_int (&args->values[3]);
  gamma = g_value_get_double (&args->values[4]);
  low_output = g_value_get_int (&args->values[5]);
  high_output = g_value_get_int (&args->values[6]);
132

133 134
  if (success)
    {
135 136
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable) ||
137 138 139 140 141
          (! gimp_drawable_has_alpha (drawable) &&
           channel == GIMP_HISTOGRAM_ALPHA) ||
          (gimp_drawable_is_gray (drawable) &&
           channel != GIMP_HISTOGRAM_VALUE && channel != GIMP_HISTOGRAM_ALPHA))
        success = FALSE;
142

143
      if (success)
144 145
        gimp_drawable_levels (drawable, context,
                              channel,
146
                              low_input, high_input,
147
                              gamma,
148
                              low_output, high_output);
149 150
    }

151
  return gimp_procedure_get_return_values (procedure, success);
152 153
}

154 155 156 157 158 159
static GValueArray *
levels_auto_invoker (GimpProcedure     *procedure,
                     Gimp              *gimp,
                     GimpContext       *context,
                     GimpProgress      *progress,
                     const GValueArray *args)
160 161 162 163
{
  gboolean success = TRUE;
  GimpDrawable *drawable;

164
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
165 166 167

  if (success)
    {
168 169
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable))
170
        success = FALSE;
171

172
      if (success)
173
        gimp_drawable_levels_stretch (drawable, context);
174 175
    }

176
  return gimp_procedure_get_return_values (procedure, success);
177 178
}

179 180 181 182 183 184
static GValueArray *
levels_stretch_invoker (GimpProcedure     *procedure,
                        Gimp              *gimp,
                        GimpContext       *context,
                        GimpProgress      *progress,
                        const GValueArray *args)
185 186 187 188
{
  gboolean success = TRUE;
  GimpDrawable *drawable;

189
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
190 191 192

  if (success)
    {
193 194
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable))
195 196 197 198 199 200
        success = FALSE;

      if (success)
        gimp_drawable_levels_stretch (drawable, context);
    }

201
  return gimp_procedure_get_return_values (procedure, success);
202 203
}

204 205 206 207 208 209
static GValueArray *
posterize_invoker (GimpProcedure     *procedure,
                   Gimp              *gimp,
                   GimpContext       *context,
                   GimpProgress      *progress,
                   const GValueArray *args)
210
{
211
  gboolean success = TRUE;
212
  GimpDrawable *drawable;
213 214
  gint32 levels;

215 216
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  levels = g_value_get_int (&args->values[1]);
217

218 219
  if (success)
    {
220 221
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable))
222
        success = FALSE;
223

224
      if (success)
225
        {
226
          gint x, y, width, height;
227

228
          /* The application should occur only within selection bounds */
229 230 231 232
          if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
            {
              GimpLut     *lut;
              PixelRegion  srcPR, destPR;
233

234
              lut = posterize_lut_new (levels, gimp_drawable_bytes (drawable));
235

236
              pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
237
                                 x, y, width, height, FALSE);
238
              pixel_region_init (&destPR, gimp_drawable_get_shadow_tiles (drawable),
239
                                 x, y, width, height, TRUE);
240

241 242
              pixel_regions_process_parallel ((PixelProcessorFunc)
                                              gimp_lut_process,
243
                                              lut, 2, &srcPR, &destPR);
244

245 246 247 248 249
              gimp_lut_free (lut);

              gimp_drawable_merge_shadow (drawable, TRUE, _("Posterize"));
              gimp_drawable_update (drawable, x, y, width, height);
            }
250
        }
251 252
    }

253
  return gimp_procedure_get_return_values (procedure, success);
254 255
}

256 257 258 259 260 261
static GValueArray *
desaturate_invoker (GimpProcedure     *procedure,
                    Gimp              *gimp,
                    GimpContext       *context,
                    GimpProgress      *progress,
                    const GValueArray *args)
262 263 264 265
{
  gboolean success = TRUE;
  GimpDrawable *drawable;

266
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
267 268 269

  if (success)
    {
270 271
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          ! gimp_drawable_is_rgb (drawable))
272
        success = FALSE;
273 274

      if (success)
275
        gimp_drawable_desaturate (drawable, GIMP_DESATURATE_LIGHTNESS);
276 277
    }

278
  return gimp_procedure_get_return_values (procedure, success);
279 280
}

281 282 283 284 285 286
static GValueArray *
desaturate_full_invoker (GimpProcedure     *procedure,
                         Gimp              *gimp,
                         GimpContext       *context,
                         GimpProgress      *progress,
                         const GValueArray *args)
287 288 289 290 291
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gint32 desaturate_mode;

292 293
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  desaturate_mode = g_value_get_enum (&args->values[1]);
294 295 296 297 298 299 300 301

  if (success)
    {
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          ! gimp_drawable_is_rgb (drawable))
        success = FALSE;

      if (success)
302
        gimp_drawable_desaturate (drawable, desaturate_mode);
303 304
    }

305
  return gimp_procedure_get_return_values (procedure, success);
306 307
}

308 309 310 311 312 313
static GValueArray *
equalize_invoker (GimpProcedure     *procedure,
                  Gimp              *gimp,
                  GimpContext       *context,
                  GimpProgress      *progress,
                  const GValueArray *args)
314 315 316 317 318
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gboolean mask_only;

319 320
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  mask_only = g_value_get_boolean (&args->values[1]);
321 322 323

  if (success)
    {
324 325
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable))
326
        success = FALSE;
327 328 329

      if (success)
        gimp_drawable_equalize (drawable, mask_only);
330 331
    }

332
  return gimp_procedure_get_return_values (procedure, success);
333 334
}

335 336 337 338 339 340
static GValueArray *
invert_invoker (GimpProcedure     *procedure,
                Gimp              *gimp,
                GimpContext       *context,
                GimpProgress      *progress,
                const GValueArray *args)
341 342 343 344
{
  gboolean success = TRUE;
  GimpDrawable *drawable;

345
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
346 347 348

  if (success)
    {
349 350
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable))
351
        success = FALSE;
352 353 354

      if (success)
        gimp_drawable_invert (drawable);
355 356
    }

357
  return gimp_procedure_get_return_values (procedure, success);
358 359
}

360 361 362 363 364 365
static GValueArray *
curves_spline_invoker (GimpProcedure     *procedure,
                       Gimp              *gimp,
                       GimpContext       *context,
                       GimpProgress      *progress,
                       const GValueArray *args)
366 367 368 369 370
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gint32 channel;
  gint32 num_points;
371
  const guint8 *control_pts;
372

373 374 375 376
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  channel = g_value_get_enum (&args->values[1]);
  num_points = g_value_get_int (&args->values[2]);
  control_pts = gimp_value_get_int8array (&args->values[3]);
377 378 379

  if (success)
    {
380 381
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable) || (num_points & 1) ||
382 383 384 385 386
          (! gimp_drawable_has_alpha (drawable) &&
           channel == GIMP_HISTOGRAM_ALPHA) ||
          (gimp_drawable_is_gray (drawable) &&
           channel != GIMP_HISTOGRAM_VALUE && channel != GIMP_HISTOGRAM_ALPHA))
        success = FALSE;
387

388
      if (success)
389
        {
390
          gint x, y, width, height;
391

392 393 394 395 396 397 398
          /* The application should occur only within selection bounds */
          if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
            {
              Curves       c;
              gint         j;
              PixelRegion  srcPR, destPR;
              GimpLut     *lut;
399

400 401 402 403
              /* FIXME: hack */
              if (gimp_drawable_is_gray (drawable) &&
                  channel == GIMP_HISTOGRAM_ALPHA)
                channel = 1;
404

405
              lut = gimp_lut_new ();
406

407
              curves_init (&c);
408

409 410 411
              /*  unset the last point  */
              c.points[channel][CURVES_NUM_POINTS - 1][0] = -1;
              c.points[channel][CURVES_NUM_POINTS - 1][1] = -1;
412

413 414 415 416 417
              for (j = 0; j < num_points / 2; j++)
                {
                  c.points[channel][j][0] = control_pts[j * 2];
                  c.points[channel][j][1] = control_pts[j * 2 + 1];
                }
418

419 420 421 422 423 424
              curves_calculate_curve (&c, channel);

              gimp_lut_setup (lut,
                              (GimpLutFunc) curves_lut_func,
                              &c,
                              gimp_drawable_bytes (drawable));
425

426
              pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
427
                                 x, y, width, height, FALSE);
428
              pixel_region_init (&destPR, gimp_drawable_get_shadow_tiles (drawable),
429
                                 x, y, width, height, TRUE);
430

431 432
              pixel_regions_process_parallel ((PixelProcessorFunc)
                                              gimp_lut_process,
433
                                              lut, 2, &srcPR, &destPR);
434

435
              gimp_lut_free (lut);
436

437 438 439
              gimp_drawable_merge_shadow (drawable, TRUE, _("Curves"));
              gimp_drawable_update (drawable, x, y, width, height);
            }
440
        }
441 442
    }

443
  return gimp_procedure_get_return_values (procedure, success);
444 445
}

446 447 448 449 450 451
static GValueArray *
curves_explicit_invoker (GimpProcedure     *procedure,
                         Gimp              *gimp,
                         GimpContext       *context,
                         GimpProgress      *progress,
                         const GValueArray *args)
452 453 454 455 456
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gint32 channel;
  gint32 num_bytes;
457
  const guint8 *curve;
458

459 460 461 462
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  channel = g_value_get_enum (&args->values[1]);
  num_bytes = g_value_get_int (&args->values[2]);
  curve = gimp_value_get_int8array (&args->values[3]);
463 464 465

  if (success)
    {
466 467
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable) || (num_bytes != 256) ||
468 469 470 471 472
          (! gimp_drawable_has_alpha (drawable) &&
           channel == GIMP_HISTOGRAM_ALPHA) ||
          (gimp_drawable_is_gray (drawable) &&
           channel != GIMP_HISTOGRAM_VALUE && channel != GIMP_HISTOGRAM_ALPHA))
        success = FALSE;
473

474
      if (success)
475
        {
476 477 478 479 480 481 482 483 484
          gint x, y, width, height;

          /* The application should occur only within selection bounds */
          if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
            {
              Curves       c;
              gint         j;
              PixelRegion  srcPR, destPR;
              GimpLut     *lut;
485

486 487 488 489
              /* FIXME: hack */
              if (gimp_drawable_is_gray (drawable) &&
                  channel == GIMP_HISTOGRAM_ALPHA)
                channel = 1;
490

491
              lut = gimp_lut_new ();
492

493
              curves_init (&c);
494

495 496
              for (j = 0; j < 256; j++)
                c.curve[channel][j] = curve[j];
497

498 499 500 501
              gimp_lut_setup (lut,
                              (GimpLutFunc) curves_lut_func,
                              &c,
                              gimp_drawable_bytes (drawable));
502

503
              pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
504
                                 x, y, width, height, FALSE);
505
              pixel_region_init (&destPR, gimp_drawable_get_shadow_tiles (drawable),
506
                                 x, y, width, height, TRUE);
507

508 509
              pixel_regions_process_parallel ((PixelProcessorFunc)
                                              gimp_lut_process,
510
                                              lut, 2, &srcPR, &destPR);
511

512
              gimp_lut_free (lut);
513

514 515 516
              gimp_drawable_merge_shadow (drawable, TRUE, _("Curves"));
              gimp_drawable_update (drawable, x, y, width, height);
            }
517
        }
518 519
    }

520
  return gimp_procedure_get_return_values (procedure, success);
521 522
}

523 524 525 526 527 528
static GValueArray *
color_balance_invoker (GimpProcedure     *procedure,
                       Gimp              *gimp,
                       GimpContext       *context,
                       GimpProgress      *progress,
                       const GValueArray *args)
529 530 531 532 533 534 535 536 537
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gint32 transfer_mode;
  gboolean preserve_lum;
  gdouble cyan_red;
  gdouble magenta_green;
  gdouble yellow_blue;

538 539 540 541 542 543
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  transfer_mode = g_value_get_enum (&args->values[1]);
  preserve_lum = g_value_get_boolean (&args->values[2]);
  cyan_red = g_value_get_double (&args->values[3]);
  magenta_green = g_value_get_double (&args->values[4]);
  yellow_blue = g_value_get_double (&args->values[5]);
544 545 546

  if (success)
    {
547 548
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable))
549
        success = FALSE;
550

551
      if (success)
552
        {
553
          gint x, y, width, height;
554

555 556 557
          /* The application should occur only within selection bounds */
          if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
            {
558 559
              ColorBalance  cb;
              PixelRegion   srcPR, destPR;
560

561
              color_balance_init (&cb);
562

563
              cb.preserve_luminosity = preserve_lum;
564

565 566 567
              cb.cyan_red[transfer_mode]      = cyan_red;
              cb.magenta_green[transfer_mode] = magenta_green;
              cb.yellow_blue[transfer_mode]   = yellow_blue;
568

569
              color_balance_create_lookup_tables (&cb);
570

571
              pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
572
                                 x, y, width, height, FALSE);
573
              pixel_region_init (&destPR, gimp_drawable_get_shadow_tiles (drawable),
574 575
                                 x, y, width, height, TRUE);

576 577
              pixel_regions_process_parallel ((PixelProcessorFunc) color_balance,
                                              &cb, 2, &srcPR, &destPR);
578

579 580 581
              gimp_drawable_merge_shadow (drawable, TRUE, _("Color Balance"));
              gimp_drawable_update (drawable, x, y, width, height);
            }
582
        }
583 584
    }

585
  return gimp_procedure_get_return_values (procedure, success);
586 587
}

588 589 590 591 592 593
static GValueArray *
colorize_invoker (GimpProcedure     *procedure,
                  Gimp              *gimp,
                  GimpContext       *context,
                  GimpProgress      *progress,
                  const GValueArray *args)
594 595 596 597 598 599 600
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gdouble hue;
  gdouble saturation;
  gdouble lightness;

601 602 603 604
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  hue = g_value_get_double (&args->values[1]);
  saturation = g_value_get_double (&args->values[2]);
  lightness = g_value_get_double (&args->values[3]);
605 606 607

  if (success)
    {
608 609
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          ! gimp_drawable_is_rgb (drawable))
610 611 612 613
        success = FALSE;

      if (success)
        {
614
          gint x, y, width, height;
615

616 617 618
          /* The application should occur only within selection bounds */
          if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
            {
619 620
              Colorize     colors;
              PixelRegion  srcPR, destPR;
621

622
              colorize_init (&colors);
623

624 625 626
              colors.hue        = hue;
              colors.saturation = saturation;
              colors.lightness  = lightness;
627

628
              colorize_calculate (&colors);
629

630
              pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
631
                                 x, y, width, height, FALSE);
632
              pixel_region_init (&destPR, gimp_drawable_get_shadow_tiles (drawable),
633 634
                                 x, y, width, height, TRUE);

635 636
              pixel_regions_process_parallel ((PixelProcessorFunc) colorize,
                                              &colors, 2, &srcPR, &destPR);
637

638 639 640
              gimp_drawable_merge_shadow (drawable, TRUE, _("Colorize"));
              gimp_drawable_update (drawable, x, y, width, height);
            }
641 642 643
        }
    }

644
  return gimp_procedure_get_return_values (procedure, success);
645 646
}

647 648 649 650 651 652
static GValueArray *
histogram_invoker (GimpProcedure     *procedure,
                   Gimp              *gimp,
                   GimpContext       *context,
                   GimpProgress      *progress,
                   const GValueArray *args)
653 654
{
  gboolean success = TRUE;
655
  GValueArray *return_vals;
656 657 658 659
  GimpDrawable *drawable;
  gint32 channel;
  gint32 start_range;
  gint32 end_range;
660 661 662 663 664 665
  gdouble mean = 0.0;
  gdouble std_dev = 0.0;
  gdouble median = 0.0;
  gdouble pixels = 0.0;
  gdouble count = 0.0;
  gdouble percentile = 0.0;
666

667 668 669 670
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  channel = g_value_get_enum (&args->values[1]);
  start_range = g_value_get_int (&args->values[2]);
  end_range = g_value_get_int (&args->values[3]);
671 672 673

  if (success)
    {
674 675
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable) ||
676 677 678 679 680
          (! gimp_drawable_has_alpha (drawable) &&
           channel == GIMP_HISTOGRAM_ALPHA) ||
          (gimp_drawable_is_gray (drawable) &&
           channel != GIMP_HISTOGRAM_VALUE && channel != GIMP_HISTOGRAM_ALPHA))
        success = FALSE;
681

682
      if (success)
683
        {
684
          GimpHistogram *histogram = gimp_histogram_new ();
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700

          gimp_drawable_calculate_histogram (drawable, histogram);

          mean       = gimp_histogram_get_mean (histogram, channel,
                                                 start_range, end_range);
          std_dev    = gimp_histogram_get_std_dev (histogram, channel,
                                                   start_range, end_range);
          median     = gimp_histogram_get_median (histogram, channel,
                                                  start_range, end_range);
          pixels     = gimp_histogram_get_count (histogram, channel, 0, 255);
          count      = gimp_histogram_get_count (histogram, channel,
                                                 start_range, end_range);
          percentile = count / pixels;

          gimp_histogram_free (histogram);
        }
701 702
    }

703
  return_vals = gimp_procedure_get_return_values (procedure, success);
704 705 706

  if (success)
    {
707 708 709 710 711 712
      g_value_set_double (&return_vals->values[1], mean);
      g_value_set_double (&return_vals->values[2], std_dev);
      g_value_set_double (&return_vals->values[3], median);
      g_value_set_double (&return_vals->values[4], pixels);
      g_value_set_double (&return_vals->values[5], count);
      g_value_set_double (&return_vals->values[6], percentile);
713 714
    }

715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
  return return_vals;
}

static GValueArray *
hue_saturation_invoker (GimpProcedure     *procedure,
                        Gimp              *gimp,
                        GimpContext       *context,
                        GimpProgress      *progress,
                        const GValueArray *args)
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
  gint32 hue_range;
  gdouble hue_offset;
  gdouble lightness;
  gdouble saturation;

  drawable = gimp_value_get_drawable (&args->values[0], gimp);
  hue_range = g_value_get_enum (&args->values[1]);
  hue_offset = g_value_get_double (&args->values[2]);
  lightness = g_value_get_double (&args->values[3]);
  saturation = g_value_get_double (&args->values[4]);

  if (success)
    {
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
          gimp_drawable_is_indexed (drawable))
        success = FALSE;

      if (success)
        {
          gint x, y, width, height;

          /* The application should occur only within selection bounds */
          if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
            {
              HueSaturation  hs;
              PixelRegion    srcPR, destPR;

              hue_saturation_init (&hs);

              hs.hue[hue_range]        = hue_offset;
              hs.lightness[hue_range]  = lightness;
              hs.saturation[hue_range] = saturation;

              /* Calculate the transfer arrays */
              hue_saturation_calculate_transfers (&hs);

763
              pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
764
                                 x, y, width, height, FALSE);
765
              pixel_region_init (&destPR, gimp_drawable_get_shadow_tiles (drawable),
766 767 768 769 770 771 772 773 774 775 776 777
                                 x, y, width, height, TRUE);

              pixel_regions_process_parallel ((PixelProcessorFunc) hue_saturation,
                                              &hs, 2, &srcPR, &destPR);

              gimp_drawable_merge_shadow (drawable, TRUE, _("Hue-Saturation"));
              gimp_drawable_update (drawable, x, y, width, height);
            }
        }
    }

  return gimp_procedure_get_return_values (procedure, success);
778 779
}

780
static GValueArray *
781 782 783 784 785
threshold_invoker (GimpProcedure     *procedure,
                   Gimp              *gimp,
                   GimpContext       *context,
                   GimpProgress      *progress,
                   const GValueArray *args)
786 787 788
{
  gboolean success = TRUE;
  GimpDrawable *drawable;
789 790
  gint32 low_threshold;
  gint32 high_threshold;
791

792
  drawable = gimp_value_get_drawable (&args->values[0], gimp);
793 794
  low_threshold = g_value_get_int (&args->values[1]);
  high_threshold = g_value_get_int (&args->values[2]);
795 796 797

  if (success)
    {
798
      if (! gimp_item_is_attached (GIMP_ITEM (drawable)) ||
799 800
          gimp_drawable_is_indexed (drawable) ||
          (low_threshold >= high_threshold))
801
        success = FALSE;
802

803
      if (success)
804
        {
805
          gint x, y, width, height;
806

807 808 809
          /* The application should occur only within selection bounds */
          if (gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
            {
810 811
              Threshold   tr;
              PixelRegion srcPR, destPR;
812

813 814 815
              tr.color          = gimp_drawable_is_rgb (drawable);
              tr.low_threshold  = low_threshold;
              tr.high_threshold = high_threshold;
816

817
              pixel_region_init (&srcPR, gimp_drawable_get_tiles (drawable),
818
                                 x, y, width, height, FALSE);
819
              pixel_region_init (&destPR, gimp_drawable_get_shadow_tiles (drawable),
820 821
                                 x, y, width, height, TRUE);

822 823
              pixel_regions_process_parallel ((PixelProcessorFunc) threshold,
                                              &tr, 2, &srcPR, &destPR);
824

825
              gimp_drawable_merge_shadow (drawable, TRUE, _("Threshold"));
826 827
              gimp_drawable_update (drawable, x, y, width, height);
            }
828
        }
829 830
    }

831
  return gimp_procedure_get_return_values (procedure, success);
832 833
}

834
void
835
register_color_procs (GimpPDB *pdb)
836 837 838 839 840 841
{
  GimpProcedure *procedure;

  /*
   * gimp-brightness-contrast
   */
842
  procedure = gimp_procedure_new (brightness_contrast_invoker);
843
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-brightness-contrast");
844 845 846 847 848 849 850 851 852 853 854 855
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-brightness-contrast",
                                     "Modify brightness/contrast in the specified drawable.",
                                     "This procedures allows the brightness and contrast of the specified drawable to be modified. Both 'brightness' and 'contrast' parameters are defined between -127 and 127.",
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1997",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
856
                                                            pdb->gimp, FALSE,
857 858 859 860
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("brightness",
                                                      "brightness",
861
                                                      "Brightness adjustment",
862 863 864 865 866
                                                      -127, 127, -127,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("contrast",
                                                      "contrast",
867
                                                      "Contrast adjustment",
868 869
                                                      -127, 127, -127,
                                                      GIMP_PARAM_READWRITE));
870
  gimp_pdb_register_procedure (pdb, procedure);
871
  g_object_unref (procedure);
872 873 874 875

  /*
   * gimp-levels
   */
876
  procedure = gimp_procedure_new (levels_invoker);
877
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-levels");
878 879 880 881 882 883 884 885 886 887 888 889
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-levels",
                                     "Modifies intensity levels in the specified drawable.",
                                     "This tool allows intensity levels in the specified drawable to be remapped according to a set of parameters. The low/high input levels specify an initial mapping from the source intensities. The gamma value determines how intensities between the low and high input intensities are interpolated. A gamma value of 1.0 results in a linear interpolation. Higher gamma values result in more high-level intensities. Lower gamma values result in more low-level intensities. The low/high output levels constrain the final intensity mapping--that is, no final intensity will be lower than the low output level and no final intensity will be higher than the high output level. This tool is only valid on RGB color and grayscale images. It will not operate on indexed drawables.",
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1995-1996",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
890
                                                            pdb->gimp, FALSE,
891 892 893 894
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("channel",
                                                  "channel",
895
                                                  "The channel to modify",
896 897 898 899 900 901
                                                  GIMP_TYPE_HISTOGRAM_CHANNEL,
                                                  GIMP_HISTOGRAM_VALUE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("low-input",
                                                      "low input",
902
                                                      "Intensity of lowest input",
903 904 905 906 907
                                                      0, 255, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("high-input",
                                                      "high input",
908
                                                      "Intensity of highest input",
909 910 911 912 913
                                                      0, 255, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("gamma",
                                                    "gamma",
914
                                                    "Gamma correction factor",
915 916 917 918 919
                                                    0.1, 10, 0.1,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("low-output",
                                                      "low output",
920
                                                      "Intensity of lowest output",
921 922 923 924 925
                                                      0, 255, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("high-output",
                                                      "high output",
926
                                                      "Intensity of highest output",
927 928
                                                      0, 255, 0,
                                                      GIMP_PARAM_READWRITE));
929
  gimp_pdb_register_procedure (pdb, procedure);
930
  g_object_unref (procedure);
931 932 933 934

  /*
   * gimp-levels-auto
   */
935
  procedure = gimp_procedure_new (levels_auto_invoker);
936
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-levels-auto");
937 938
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-levels-auto",
939 940
                                     "This procedure is deprecated! Use 'gimp-levels-stretch' instead.",
                                     "This procedure is deprecated! Use 'gimp-levels-stretch' instead.",
941 942 943
                                     "",
                                     "",
                                     "",
944
                                     "gimp-levels-stretch");
945 946 947 948
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
949
                                                            pdb->gimp, FALSE,
950
                                                            GIMP_PARAM_READWRITE));
951
  gimp_pdb_register_procedure (pdb, procedure);
952
  g_object_unref (procedure);
953 954 955 956

  /*
   * gimp-levels-stretch
   */
957
  procedure = gimp_procedure_new (levels_stretch_invoker);
958
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-levels-stretch");
959 960 961 962 963 964 965 966 967 968 969 970
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-levels-stretch",
                                     "Automatically modifies intensity levels in the specified drawable.",
                                     "This procedure allows intensity levels in the specified drawable to be remapped according to a set of guessed parameters. It is equivalent to clicking the \"Auto\" button in the Levels tool. This procedure is only valid on RGB color and grayscale images. It will not operate on indexed drawables.",
                                     "Joao S.O. Bueno, Shawn Willden",
                                     "Joao S.O. Bueno, Shawn Willden",
                                     "2003",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
971
                                                            pdb->gimp, FALSE,
972
                                                            GIMP_PARAM_READWRITE));
973
  gimp_pdb_register_procedure (pdb, procedure);
974
  g_object_unref (procedure);
975 976 977 978

  /*
   * gimp-posterize
   */
979
  procedure = gimp_procedure_new (posterize_invoker);
980
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-posterize");
981 982 983 984 985 986 987 988 989 990 991 992
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-posterize",
                                     "Posterize the specified drawable.",
                                     "This procedures reduces the number of shades allows in each intensity channel to the specified 'levels' parameter.",
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1997",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
993
                                                            pdb->gimp, FALSE,
994 995 996 997
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("levels",
                                                      "levels",
998
                                                      "Levels of posterization",
999 1000
                                                      2, 255, 2,
                                                      GIMP_PARAM_READWRITE));
1001
  gimp_pdb_register_procedure (pdb, procedure);
1002
  g_object_unref (procedure);
1003 1004 1005 1006

  /*
   * gimp-desaturate
   */
1007
  procedure = gimp_procedure_new (desaturate_invoker);
1008
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-desaturate");
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-desaturate",
                                     "Desaturate the contents of the specified drawable.",
                                     "This procedure desaturates the contents of the specified drawable. This procedure only works on drawables of type RGB color.",
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1995-1996",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
1021
                                                            pdb->gimp, FALSE,
1022
                                                            GIMP_PARAM_READWRITE));
1023
  gimp_pdb_register_procedure (pdb, procedure);
1024
  g_object_unref (procedure);
1025 1026 1027 1028

  /*
   * gimp-desaturate-full
   */
1029
  procedure = gimp_procedure_new (desaturate_full_invoker);
1030
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-desaturate-full");
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-desaturate-full",
                                     "Desaturate the contents of the specified drawable, with the specified formula.",
                                     "This procedure desaturates the contents of the specified drawable, with the specified formula. This procedure only works on drawables of type RGB color.",
                                     "Karine Delvare",
                                     "Karine Delvare",
                                     "2005",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
1043
                                                            pdb->gimp, FALSE,
1044 1045 1046 1047 1048 1049 1050 1051
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("desaturate-mode",
                                                  "desaturate mode",
                                                  "The formula to use to desaturate",
                                                  GIMP_TYPE_DESATURATE_MODE,
                                                  GIMP_DESATURATE_LIGHTNESS,
                                                  GIMP_PARAM_READWRITE));
1052
  gimp_pdb_register_procedure (pdb, procedure);
1053
  g_object_unref (procedure);
1054 1055 1056 1057

  /*
   * gimp-equalize
   */
1058
  procedure = gimp_procedure_new (equalize_invoker);
1059
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-equalize");
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-equalize",
                                     "Equalize the contents of the specified drawable.",
                                     "This procedure equalizes the contents of the specified drawable. Each intensity channel is equalizeed independently. The equalized intensity is given as inten' = (255 - inten). Indexed color drawables are not valid for this operation. The 'mask_only' option specifies whether to adjust only the area of the image within the selection bounds, or the entire image based on the histogram of the selected area. If there is no selection, the entire image is adjusted based on the histogram for the entire image.",
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1995-1996",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
1072
                                                            pdb->gimp, FALSE,
1073 1074 1075 1076 1077 1078 1079
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("mask-only",
                                                     "mask only",
                                                     "Equalization option",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
1080
  gimp_pdb_register_procedure (pdb, procedure);
1081
  g_object_unref (procedure);
1082 1083 1084 1085

  /*
   * gimp-invert
   */
1086
  procedure = gimp_procedure_new (invert_invoker);
1087
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-invert");
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-invert",
                                     "Invert the contents of the specified drawable.",
                                     "This procedure inverts the contents of the specified drawable. Each intensity channel is inverted independently. The inverted intensity is given as inten' = (255 - inten). Indexed color drawables are not valid for this operation.",
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1995-1996",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
1100
                                                            pdb->gimp, FALSE,
1101
                                                            GIMP_PARAM_READWRITE));
1102
  gimp_pdb_register_procedure (pdb, procedure);
1103
  g_object_unref (procedure);
1104 1105 1106 1107

  /*
   * gimp-curves-spline
   */
1108
  procedure = gimp_procedure_new (curves_spline_invoker);
1109
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-curves-spline");
1110 1111 1112
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-curves-spline",
                                     "Modifies the intensity curve(s) for specified drawable.",
1113
                                     "Modifies the intensity mapping for one channel in the specified drawable. The drawable must be either grayscale or RGB, and the channel can be either an intensity component, or the value. The 'control_pts' parameter is an array of integers which define a set of control points which describe a Catmull Rom spline which yields the final intensity curve. Use the 'gimp-curves-explicit' function to explicitly modify intensity levels.",
1114 1115 1116 1117 1118 1119 1120 1121
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1995-1996",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
1122
                                                            pdb->gimp, FALSE,
1123 1124 1125 1126
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("channel",
                                                  "channel",
1127
                                                  "The channel to modify",
1128 1129 1130 1131 1132 1133
                                                  GIMP_TYPE_HISTOGRAM_CHANNEL,
                                                  GIMP_HISTOGRAM_VALUE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("num-points",
                                                      "num points",
1134
                                                      "The number of values in the control point array",
1135 1136 1137 1138 1139 1140 1141
                                                      4, 34, 4,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int8_array ("control-pts",
                                                           "control pts",
                                                           "The spline control points: { cp1.x, cp1.y, cp2.x, cp2.y, ... }",
                                                           GIMP_PARAM_READWRITE));
1142
  gimp_pdb_register_procedure (pdb, procedure);
1143
  g_object_unref (procedure);
1144 1145 1146 1147

  /*
   * gimp-curves-explicit
   */
1148
  procedure = gimp_procedure_new (curves_explicit_invoker);
1149
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-curves-explicit");
1150 1151 1152
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-curves-explicit",
                                     "Modifies the intensity curve(s) for specified drawable.",
1153
                                     "Modifies the intensity mapping for one channel in the specified drawable. The drawable must be either grayscale or RGB, and the channel can be either an intensity component, or the value. The 'curve' parameter is an array of bytes which explicitly defines how each pixel value in the drawable will be modified. Use the 'gimp-curves-spline' function to modify intensity levels with Catmull Rom splines.",
1154 1155 1156 1157 1158 1159 1160 1161
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1995-1996",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
1162
                                                            pdb->gimp, FALSE,
1163 1164 1165 1166
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("channel",
                                                  "channel",
1167
                                                  "The channel to modify",
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
                                                  GIMP_TYPE_HISTOGRAM_CHANNEL,
                                                  GIMP_HISTOGRAM_VALUE,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int32 ("num-bytes",
                                                      "num bytes",
                                                      "The number of bytes in the new curve (always 256)",
                                                      0, G_MAXINT32, 0,
                                                      GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_int8_array ("curve",
                                                           "curve",
                                                           "The explicit curve",
                                                           GIMP_PARAM_READWRITE));
1182
  gimp_pdb_register_procedure (pdb, procedure);
1183
  g_object_unref (procedure);
1184 1185 1186 1187

  /*
   * gimp-color-balance
   */
1188
  procedure = gimp_procedure_new (color_balance_invoker);
1189
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-color-balance");
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-color-balance",
                                     "Modify the color balance of the specified drawable.",
                                     "Modify the color balance of the specified drawable. There are three axis which can be modified: cyan-red, magenta-green, and yellow-blue. Negative values increase the amount of the former, positive values increase the amount of the latter. Color balance can be controlled with the 'transfer_mode' setting, which allows shadows, midtones, and highlights in an image to be affected differently. The 'preserve_lum' parameter, if TRUE, ensures that the luminosity of each pixel remains fixed.",
                                     "Spencer Kimball & Peter Mattis",
                                     "Spencer Kimball & Peter Mattis",
                                     "1997",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
1202
                                                            pdb->gimp, FALSE,
1203 1204 1205 1206
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_enum ("transfer-mode",
                                                  "transfer mode",
1207
                                                  "Transfer mode",
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
                                                  GIMP_TYPE_TRANSFER_MODE,
                                                  GIMP_SHADOWS,
                                                  GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_boolean ("preserve-lum",
                                                     "preserve lum",
                                                     "Preserve luminosity values at each pixel",
                                                     FALSE,
                                                     GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("cyan-red",
                                                    "cyan red",
1220
                                                    "Cyan-Red color balance",
1221 1222 1223 1224 1225
                                                    -100, 100, -100,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("magenta-green",
                                                    "magenta green",
1226
                                                    "Magenta-Green color balance",
1227 1228 1229 1230 1231
                                                    -100, 100, -100,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("yellow-blue",
                                                    "yellow blue",
1232
                                                    "Yellow-Blue color balance",
1233 1234
                                                    -100, 100, -100,
                                                    GIMP_PARAM_READWRITE));
1235
  gimp_pdb_register_procedure (pdb, procedure);
1236
  g_object_unref (procedure);
1237

1238 1239 1240
  /*
   * gimp-colorize
   */
1241
  procedure = gimp_procedure_new (colorize_invoker);
1242
  gimp_object_set_static_name (GIMP_OBJECT (procedure), "gimp-colorize");
1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
  gimp_procedure_set_static_strings (procedure,
                                     "gimp-colorize",
                                     "Render the drawable as a grayscale image seen through a colored glass.",
                                     "Desatures the drawable, then tints it with the specified color. This tool is only valid on RGB color images. It will not operate on grayscale or indexed drawables.",
                                     "Sven Neumann <sven@gimp.org>",
                                     "Sven Neumann",
                                     "2004",
                                     NULL);
  gimp_procedure_add_argument (procedure,
                               gimp_param_spec_drawable_id ("drawable",
                                                            "drawable",
                                                            "The drawable",
1255
                                                            pdb->gimp, FALSE,
1256 1257 1258 1259
                                                            GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("hue",
                                                    "hue",
1260
                                                    "Hue in degrees",
1261 1262 1263 1264 1265
                                                    0, 360, 0,
                                                    GIMP_PARAM_READWRITE));
  gimp_procedure_add_argument (procedure,
                               g_param_spec_double ("saturation",
                                                    "saturation",
1266
                                                    "Saturation in percent",
1267 1268 1269 1270