~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/common/despeckle.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * "$Id: despeckle.c,v 1.75 2004/12/23 23:19:43 neo Exp $"
 
1
/* GIMP - The GNU Image Manipulation Program
 
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 *
4
 
 *   Despeckle (adaptive median) filter for The GIMP -- an image manipulation
5
 
 *   program
 
4
 *   Despeckle (adaptive median) filter
6
5
 *
7
6
 *   Copyright 1997-1998 Michael Sweet (mike@easysw.com)
8
7
 *
23
22
 
24
23
#include "config.h"
25
24
 
26
 
#include <stdio.h>
27
25
#include <stdlib.h>
28
 
#include <string.h>
29
 
 
30
 
#include <gtk/gtk.h>
31
26
 
32
27
#include <libgimp/gimp.h>
33
28
#include <libgimp/gimpui.h>
35
30
#include "libgimp/stdplugins-intl.h"
36
31
 
37
32
 
38
 
typedef enum
39
 
{
40
 
  MEDIAN
41
 
} FilterMethod;
42
 
 
43
 
typedef struct
44
 
{
45
 
  gint          diameter;
46
 
  FilterMethod  method;
47
 
} FilterValues;
48
 
 
49
33
/*
50
34
 * Constants...
51
35
 */
52
36
 
53
 
#define PLUG_IN_NAME     "plug_in_despeckle"
54
 
#define PLUG_IN_VERSION  "1.3.2 - 17 May 1998"
55
 
#define HELP_ID          "plug-in-despeckle"
 
37
#define PLUG_IN_PROC     "plug-in-despeckle"
 
38
#define PLUG_IN_BINARY   "despeckle"
 
39
#define PLUG_IN_VERSION  "May 1998"
56
40
#define SCALE_WIDTH      100
57
41
#define ENTRY_WIDTH        3
58
42
#define MAX_RADIUS        20
67
51
#define update_toggle    (despeckle_vals[4])    /* Update the preview? */
68
52
 
69
53
#define VALUE_SWAP(a,b)   { register  gdouble t = (a); (a) = (b); (b) = t; }
70
 
#define POINTER_SWAP(a,b) { register  guchar* t = (a); (a) = (b); (b) = t; }
 
54
#define POINTER_SWAP(a,b) { register  guchar *t = (a); (a) = (b); (b) = t; }
71
55
 
72
56
 
73
57
 
103
87
static gint      quick_median_select       (guchar       **p,
104
88
                                            guchar        *i,
105
89
                                            gint           n);
106
 
static guchar    pixel_intensity           (const guchar  *p,
 
90
static inline guchar  pixel_luminance      (const guchar  *p,
107
91
                                            gint           bpp);
108
 
static void      pixel_copy                (guchar        *dest,
 
92
static inline void    pixel_copy           (guchar        *dest,
109
93
                                            const guchar  *src,
110
 
                                            gint           n);
 
94
                                            gint           bpp);
111
95
 
112
96
/*
113
97
 * Globals...
114
98
 */
115
99
 
116
 
GimpPlugInInfo PLUG_IN_INFO =
 
100
const GimpPlugInInfo PLUG_IN_INFO =
117
101
{
118
102
  NULL,  /* init  */
119
103
  NULL,  /* quit  */
121
105
  run    /* run   */
122
106
};
123
107
 
124
 
static GtkWidget      *preview;                 /* Preview widget */
125
 
 
126
 
static GimpDrawable   *drawable = NULL;         /* Current image */
 
108
static GtkWidget    *preview;                 /* Preview widget   */
 
109
static GimpDrawable *drawable = NULL;         /* Current drawable */
127
110
 
128
111
 
129
112
static gint despeckle_vals[7] =
135
118
  TRUE                /* Default value for the update toggle */
136
119
};
137
120
 
138
 
static FilterValues fvals =
139
 
{
140
 
  3.0,  /*  y diameter  */
141
 
  MEDIAN
142
 
};
143
 
 
144
121
 
145
122
/*
146
123
 * 'main()' - Main entry - just call gimp_main()...
155
132
static void
156
133
query (void)
157
134
{
158
 
  static GimpParamDef   args[] =
 
135
  static const GimpParamDef   args[] =
159
136
  {
160
 
    { GIMP_PDB_INT32,    "run_mode", "Interactive, non-interactive" },
 
137
    { GIMP_PDB_INT32,    "run-mode", "Interactive, non-interactive" },
161
138
    { GIMP_PDB_IMAGE,    "image",    "Input image" },
162
139
    { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
163
140
    { GIMP_PDB_INT32,    "radius",   "Filter box radius (default = 3)" },
164
141
    { GIMP_PDB_INT32,    "type",     "Filter type (0 = median, 1 = adaptive, 2 = recursive-median, 3 = recursive-adaptive)" },
165
 
    { GIMP_PDB_INT32,    "black",    "Black level (-1 to 255)" },
166
 
    { GIMP_PDB_INT32,    "white",    "White level (0 to 256)" }
 
142
    { GIMP_PDB_INT32,    "black",    "Black level (0 to 255)" },
 
143
    { GIMP_PDB_INT32,    "white",    "White level (0 to 255)" }
167
144
  };
168
145
 
169
 
  gimp_install_procedure (PLUG_IN_NAME,
170
 
                          "Despeckle filter, typically used to \'despeckle\' "
171
 
                          "a photographic image.",
 
146
  gimp_install_procedure (PLUG_IN_PROC,
 
147
                          N_("Remove speckle noise from the image"),
172
148
                          "This plug-in selectively performs a median or "
173
149
                          "adaptive box filter on an image.",
174
150
                          "Michael Sweet <mike@easysw.com>",
180
156
                          G_N_ELEMENTS (args), 0,
181
157
                          args, NULL);
182
158
 
183
 
  gimp_plugin_menu_register (PLUG_IN_NAME, "<Image>/Filters/Enhance");
 
159
  gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Enhance");
184
160
}
185
161
 
186
162
 
233
209
       * Possibly retrieve data...
234
210
       */
235
211
 
236
 
      gimp_get_data (PLUG_IN_NAME, &despeckle_radius);
 
212
      gimp_get_data (PLUG_IN_PROC, &despeckle_radius);
237
213
 
238
214
      /*
239
215
       * Get information from the dialog...
289
265
       */
290
266
 
291
267
      INIT_I18N();
292
 
      gimp_get_data (PLUG_IN_NAME, despeckle_vals);
 
268
      gimp_get_data (PLUG_IN_PROC, despeckle_vals);
293
269
        break;
294
270
 
295
271
    default:
325
301
           */
326
302
 
327
303
          if (run_mode == GIMP_RUN_INTERACTIVE)
328
 
            gimp_set_data (PLUG_IN_NAME,
 
304
            gimp_set_data (PLUG_IN_PROC,
329
305
                           despeckle_vals, sizeof (despeckle_vals));
330
306
        }
331
307
      else
406
382
  GtkWidget *dialog;
407
383
  GtkWidget *main_vbox;
408
384
  GtkWidget *vbox;
409
 
  GtkWidget *hbox;
410
385
  GtkWidget *table;
411
386
  GtkWidget *frame;
412
387
  GtkWidget *button;
413
388
  GtkObject *adj;
414
389
  gboolean   run;
415
390
 
416
 
  gimp_ui_init ("despeckle", TRUE);
 
391
  gimp_ui_init (PLUG_IN_BINARY, TRUE);
417
392
 
418
 
  dialog = gimp_dialog_new (_("Despeckle"), "despeckle",
 
393
  dialog = gimp_dialog_new (_("Despeckle"), PLUG_IN_BINARY,
419
394
                            NULL, 0,
420
 
                            gimp_standard_help_func, HELP_ID,
 
395
                            gimp_standard_help_func, PLUG_IN_PROC,
421
396
 
422
397
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
423
398
                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
424
399
 
425
400
                            NULL);
426
401
 
 
402
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
 
403
                                           GTK_RESPONSE_OK,
 
404
                                           GTK_RESPONSE_CANCEL,
 
405
                                           -1);
 
406
 
 
407
  gimp_window_set_transient (GTK_WINDOW (dialog));
 
408
 
427
409
  main_vbox = gtk_vbox_new (FALSE, 12);
428
410
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
429
411
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
437
419
                    G_CALLBACK (preview_update),
438
420
                    NULL);
439
421
 
440
 
  /*
441
 
   * Filter type controls...
442
 
   */
443
 
 
444
 
  frame = gimp_frame_new (_("Type"));
 
422
  frame = gimp_frame_new (_("Median"));
445
423
  gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
446
424
  gtk_widget_show (frame);
447
425
 
448
 
 
449
 
   hbox = gtk_hbox_new (FALSE, 12);
450
 
  gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
451
 
  gtk_widget_show (hbox);
452
 
  fvals.method = MEDIAN;
453
 
  /*  parameter settings  */
454
 
  frame = gimp_frame_new (_("Median"));
455
 
 
456
426
  vbox = gtk_vbox_new (FALSE, 6);
457
427
  gtk_container_add (GTK_CONTAINER (frame), vbox);
458
428
  gtk_widget_show (vbox);
460
430
  button = gtk_check_button_new_with_mnemonic (_("_Adaptive"));
461
431
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
462
432
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
463
 
                                (filter_type & FILTER_ADAPTIVE) ? TRUE : FALSE);
 
433
                                filter_type & FILTER_ADAPTIVE);
464
434
  gtk_widget_show (button);
465
435
 
466
436
  g_signal_connect (button, "toggled",
470
440
  button = gtk_check_button_new_with_mnemonic (_("R_ecursive"));
471
441
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
472
442
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
473
 
                                (filter_type & FILTER_RECURSIVE) ? TRUE : FALSE);
 
443
                                filter_type & FILTER_RECURSIVE);
474
444
  gtk_widget_show (button);
475
445
 
476
446
  g_signal_connect (button, "toggled",
477
447
                    G_CALLBACK (dialog_recursive_callback),
478
448
                    NULL);
479
449
 
480
 
  gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
481
 
  gtk_widget_show (frame);
482
 
 
483
450
  table = gtk_table_new (4, 3, FALSE);
484
451
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
485
452
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
495
462
                              despeckle_radius, 1, MAX_RADIUS, 1, 5, 0,
496
463
                              TRUE, 0, 0,
497
464
                              NULL, NULL);
498
 
  g_signal_connect (adj, "value_changed",
 
465
  g_signal_connect (adj, "value-changed",
499
466
                    G_CALLBACK (gimp_int_adjustment_update),
500
467
                    &despeckle_radius);
501
 
  g_signal_connect_swapped (adj, "value_changed",
 
468
  g_signal_connect_swapped (adj, "value-changed",
502
469
                            G_CALLBACK (gimp_preview_invalidate),
503
470
                            preview);
504
471
 
508
475
 
509
476
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
510
477
                              _("_Black level:"), SCALE_WIDTH, ENTRY_WIDTH,
511
 
                              black_level, -1, 255, 1, 8, 0,
 
478
                              black_level, 0, 255, 1, 8, 0,
512
479
                              TRUE, 0, 0,
513
480
                              NULL, NULL);
514
 
  g_signal_connect (adj, "value_changed",
 
481
  g_signal_connect (adj, "value-changed",
515
482
                    G_CALLBACK (gimp_int_adjustment_update),
516
483
                    &black_level);
517
 
  g_signal_connect_swapped (adj, "value_changed",
 
484
  g_signal_connect_swapped (adj, "value-changed",
518
485
                            G_CALLBACK (gimp_preview_invalidate),
519
486
                            preview);
520
487
 
524
491
 
525
492
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
526
493
                              _("_White level:"), SCALE_WIDTH, ENTRY_WIDTH,
527
 
                              white_level, 0, 256, 1, 8, 0,
 
494
                              white_level, 0, 255, 1, 8, 0,
528
495
                              TRUE, 0, 0,
529
496
                              NULL, NULL);
530
 
  g_signal_connect (adj, "value_changed",
 
497
  g_signal_connect (adj, "value-changed",
531
498
                    G_CALLBACK (gimp_int_adjustment_update),
532
499
                    &white_level);
533
 
  g_signal_connect_swapped (adj, "value_changed",
 
500
  g_signal_connect_swapped (adj, "value-changed",
534
501
                            G_CALLBACK (gimp_preview_invalidate),
535
502
                            preview);
536
503
 
566
533
  gint          x1,y1;
567
534
  gint          width, height;
568
535
 
569
 
  img_bpp    = gimp_drawable_bpp (drawable->drawable_id);
570
536
  preview = GIMP_PREVIEW (widget);
571
537
 
 
538
  img_bpp = gimp_drawable_bpp (drawable->drawable_id);
 
539
 
572
540
  width  = preview->width;
573
541
  height = preview->height;
574
 
  /*
575
 
   * Setup for filter...
576
 
   */
 
542
 
577
543
  gimp_preview_get_position (preview, &x1, &y1);
578
544
 
579
545
  gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, width, height, FALSE, FALSE);
580
546
 
581
 
  /*
582
 
   * Pre-load the preview rectangle...
583
 
   */
584
547
  dst = g_new (guchar, width * height * img_bpp);
585
548
  src = g_new (guchar, width * height * img_bpp);
 
549
 
586
550
  gimp_pixel_rgn_get_rect (&src_rgn, src, x1, y1, width, height);
587
551
 
588
552
  despeckle_median (src, dst, width, height, img_bpp, despeckle_radius, TRUE);
589
553
 
590
 
  /*
591
 
   * Update the screen...
592
 
   */
593
554
  gimp_preview_draw_buffer (preview, dst, width * img_bpp);
 
555
 
 
556
  g_free (src);
594
557
  g_free (dst);
595
 
  g_free (src);
596
558
}
597
559
 
598
560
 
629
591
                  gint      radius,
630
592
                  gboolean  preview)
631
593
{
632
 
  gint      pos1, pos2, med, x, y, jh,jv, box, hist0, hist255, diameter;
633
 
  guchar  **buf;
634
 
  guchar   *ibuf;
635
 
  guchar   *pixel;
636
 
  gdouble   prog, maxprog;
637
 
 
638
 
  if (!preview)
639
 
    {
640
 
      gimp_progress_init(_("Despeckle"));
641
 
      gimp_progress_update (0.0);
642
 
    }
643
 
 
644
 
  maxprog  = width * height;
645
 
  prog     = 0;
 
594
  guchar **buf;
 
595
  guchar  *ibuf;
 
596
  guchar  *pixel;
 
597
  guint    progress;
 
598
  guint    max_progress;
 
599
  gint     x, y;
 
600
  gint     u, v;
 
601
  gint     diameter;
 
602
  gint     box;
 
603
 
 
604
  progress     = 0;
 
605
  max_progress = width * height;
646
606
 
647
607
  diameter = (2 * radius) + 1;
648
608
  box      = SQR (diameter);
649
609
  buf      = g_new (guchar *, box);
650
610
  ibuf     = g_new (guchar, box);
651
611
 
652
 
  for (x = 0; x < width; x++)
 
612
  if (!preview)
 
613
    gimp_progress_init(_("Despeckle"));
 
614
 
 
615
  for (y = 0; y < height; y++)
653
616
    {
654
 
      for (y = 0; y < height; y++)
 
617
      gint off  = y * width * bpp;
 
618
      gint ymin = MAX (0, y - radius);
 
619
      gint ymax = MIN (height, y + radius);
 
620
 
 
621
      for (x = 0; x < width; x++, off += bpp)
655
622
        {
656
 
          hist0   = 0;
657
 
          hist255 = 0;
658
 
          if (x >= radius && y >= radius &&
659
 
              x + radius < width && y + radius < height)
660
 
            {
661
 
              /* Make sure Svm is ininialized to a sufficient large value */
662
 
              med = -1;
663
 
 
664
 
              for (jh = x-radius; jh <= x+radius; jh++)
665
 
                {
666
 
                  for (jv = y-radius, pos1 = 0; jv <= y+radius; jv++)
667
 
                    {
668
 
                      pos2 = (jh + (jv * width)) * bpp;
669
 
                      if (src[pos2] > black_level && src[pos2] < white_level)
670
 
                        {
671
 
                          med++;
672
 
                          buf[med]  = src + pos2;
673
 
                          ibuf[med] = pixel_intensity (src + pos2, bpp);
674
 
                        }
675
 
                      else
676
 
                        {
677
 
                          if (src[pos2] > black_level)
678
 
                            hist0++;
679
 
 
680
 
                          if (src[pos2] >= white_level)
681
 
                            hist255++;
682
 
                        }
683
 
                    }
684
 
                }
685
 
 
686
 
              if (med < 1)
687
 
                {
688
 
                  pos1 = (x + ( y * width)) * bpp;
689
 
                  pixel_copy (dst + pos1, src + pos1, bpp);
690
 
                }
691
 
              else
692
 
                {
693
 
                  pos1 = (x + (y * width)) * bpp;
694
 
                  med  = quick_median_select (buf, ibuf, med + 1);
695
 
                  pixel = buf[med];
696
 
 
697
 
                  if (filter_type & FILTER_RECURSIVE)
698
 
                    pixel_copy (src + pos1, pixel, bpp);
699
 
 
700
 
                  pixel_copy (dst + pos1, pixel, bpp);
701
 
                }
 
623
          gint xmin    = MAX (0, x - radius);
 
624
          gint xmax    = MIN (width, x + radius);
 
625
          gint hist0   = 0;
 
626
          gint hist255 = 0;
 
627
          gint count   = 0;
 
628
 
 
629
          for (v = ymin; v < ymax; v++)
 
630
            {
 
631
              gint off2 = v * width * bpp;
 
632
 
 
633
              for (u = xmin, off2 += xmin * bpp; u < xmax; u++, off2 += bpp)
 
634
                {
 
635
                  guchar value = pixel_luminance (src + off2, bpp);
 
636
 
 
637
                  if (value < black_level)
 
638
                    {
 
639
                      hist0++;
 
640
                    }
 
641
                  else if (value > white_level)
 
642
                    {
 
643
                      hist255++;
 
644
                    }
 
645
                  else
 
646
                    {
 
647
                      buf[count]  = src + off2;
 
648
                      ibuf[count] = value;
 
649
                      count++;
 
650
                    }
 
651
                }
 
652
            }
 
653
 
 
654
          if (count < 2)
 
655
            {
 
656
              pixel_copy (dst + off, src + off, bpp);
702
657
            }
703
658
          else
704
659
            {
705
 
              pos1 = (x + (y * width)) * bpp;
706
 
              pixel_copy (dst + pos1, src + pos1, bpp);
 
660
              pixel = buf[quick_median_select (buf, ibuf, count)];
 
661
 
 
662
              if (filter_type & FILTER_RECURSIVE)
 
663
                pixel_copy (src + off, pixel, bpp);
 
664
 
 
665
              pixel_copy (dst + off, pixel, bpp);
707
666
            }
708
667
 
709
668
          /*
721
680
                  radius--;
722
681
                }
723
682
            }
 
683
 
724
684
        }
725
685
 
726
 
      prog += height;
 
686
      progress += width;
727
687
 
728
 
      if (!preview && x % 5 == 0)
729
 
        gimp_progress_update (prog / maxprog);
 
688
      if (!preview && y % 20 == 0)
 
689
        gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
730
690
    }
731
691
 
732
692
  if (!preview)
733
693
    gimp_progress_update (1.0);
734
694
 
 
695
  g_free (ibuf);
735
696
  g_free (buf);
736
 
  g_free (ibuf);
737
697
}
738
698
 
739
 
/* * This Quickselect routine is based on the algorithm described in
740
 
* "Numerical recipes in C", Second Edition,
741
 
* Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
742
 
* This code by Nicolas Devillard - 1998. Public domain.
743
 
*
744
 
* modified to swap pointers: swap is done by comparing intensity value
745
 
* for the pointer to RGB
746
 
*/
 
699
/*
 
700
 * This Quickselect routine is based on the algorithm described in
 
701
 * "Numerical recipes in C", Second Edition,
 
702
 * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5
 
703
 * This code by Nicolas Devillard - 1998. Public domain.
 
704
 *
 
705
 * Modified to swap pointers: swap is done by comparing luminance
 
706
 * value for the pointer to RGB.
 
707
 */
747
708
static gint
748
709
quick_median_select (guchar **p,
749
710
                     guchar  *i,
750
711
                     gint     n)
751
712
{
752
 
  gint low, high ;
753
 
  gint median;
754
 
  gint middle, ll, hh;
755
 
 
756
 
  low = 0 ;
757
 
  high = n-1 ;
758
 
  median = (low + high) / 2;
759
 
 
760
 
  for (;;)
 
713
  gint low    = 0;
 
714
  gint high   = n - 1;
 
715
  gint median = (low + high) / 2;
 
716
 
 
717
  while (TRUE)
761
718
    {
 
719
      gint middle, ll, hh;
 
720
 
762
721
      if (high <= low) /* One element only */
763
722
        return median;
764
723
 
767
726
          /* Two elements only */
768
727
          if (i[low] > i[high])
769
728
            {
770
 
               VALUE_SWAP (i[low], i[high]) ;
771
 
               POINTER_SWAP (p[low], p[high]) ;
 
729
               VALUE_SWAP (i[low], i[high]);
 
730
               POINTER_SWAP (p[low], p[high]);
772
731
            }
773
732
 
774
733
          return median;
779
738
 
780
739
      if (i[middle] > i[high])
781
740
        {
782
 
           VALUE_SWAP (i[middle], i[high]) ;
783
 
           POINTER_SWAP (p[middle], p[high]) ;
 
741
           VALUE_SWAP (i[middle], i[high]);
 
742
           POINTER_SWAP (p[middle], p[high]);
784
743
        }
785
744
 
786
745
      if (i[low] > i[high])
787
746
        {
788
 
           VALUE_SWAP (i[low], i[high]) ;
789
 
           POINTER_SWAP (p[low], p[high]) ;
 
747
           VALUE_SWAP (i[low], i[high]);
 
748
           POINTER_SWAP (p[low], p[high]);
790
749
        }
791
750
 
792
751
      if (i[middle] > i[low])
793
752
        {
794
 
          VALUE_SWAP (i[middle], i[low]) ;
795
 
          POINTER_SWAP (p[middle], p[low]) ;
 
753
          VALUE_SWAP (i[middle], i[low]);
 
754
          POINTER_SWAP (p[middle], p[low]);
796
755
        }
797
756
 
798
757
      /* Swap low item (now in position middle) into position (low+1) */
799
 
      VALUE_SWAP (i[middle], i[low+1]) ;
800
 
      POINTER_SWAP (p[middle], p[low+1])
 
758
      VALUE_SWAP (i[middle], i[low+1]);
 
759
      POINTER_SWAP (p[middle], p[low+1]);
801
760
 
802
761
      /* Nibble from each end towards middle, swapping items when stuck */
803
762
      ll = low + 1;
804
763
      hh = high;
805
764
 
806
 
      for (;;)
 
765
      while (TRUE)
807
766
        {
808
767
           do ll++;
809
768
           while (i[low] > i[ll]);
812
771
           while (i[hh]  > i[low]);
813
772
 
814
773
           if (hh < ll)
815
 
              break;
 
774
             break;
816
775
 
817
776
           VALUE_SWAP (i[ll], i[hh]);
818
777
           POINTER_SWAP (p[ll], p[hh]);
830
789
    }
831
790
}
832
791
 
833
 
static guchar
834
 
pixel_intensity (const guchar *p,
835
 
                 gint          n)
 
792
static inline guchar
 
793
pixel_luminance (const guchar *p,
 
794
                 gint          bpp)
836
795
{
837
 
  if (n != 3)
838
 
    return p[0];
839
 
 
840
 
  return GIMP_RGB_INTENSITY (p[0], p[1], p[2]);
 
796
  switch (bpp)
 
797
    {
 
798
    case 1:
 
799
    case 2:
 
800
      return p[0];
 
801
 
 
802
    case 3:
 
803
    case 4:
 
804
      return GIMP_RGB_LUMINANCE (p[0], p[1], p[2]);
 
805
 
 
806
    default:
 
807
      return 0; /* should not be reached */
 
808
    }
841
809
}
842
810
 
843
 
static void
 
811
static inline void
844
812
pixel_copy (guchar       *dest,
845
813
            const guchar *src,
846
 
            gint          n)
 
814
            gint          bpp)
847
815
{
848
 
  for (; n > 0; n--, dest++, src++)
 
816
  for (; bpp > 0; bpp--, dest++, src++)
849
817
    *dest = *src;
850
818
}