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

« back to all changes in this revision

Viewing changes to plug-ins/common/gauss.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
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
18
18
 
19
19
#include "config.h"
20
20
 
21
 
#include <stdio.h>
22
 
#include <stdlib.h>
23
21
#include <string.h>
24
22
 
25
 
#include <gtk/gtk.h>
26
 
 
27
23
#include <libgimp/gimp.h>
28
24
#include <libgimp/gimpui.h>
29
25
 
30
26
#include "libgimp/stdplugins-intl.h"
31
27
 
 
28
#define GAUSS_PROC      "plug-in-gauss"
 
29
#define GAUSS_IIR_PROC  "plug-in-gauss-iir"
 
30
#define GAUSS_IIR2_PROC "plug-in-gauss-iir2"
 
31
#define GAUSS_RLE_PROC  "plug-in-gauss-rle"
 
32
#define GAUSS_RLE2_PROC "plug-in-gauss-rle2"
 
33
#define PLUG_IN_BINARY  "gauss"
 
34
 
32
35
typedef enum
33
36
{
34
37
  BLUR_IIR,
52
55
                         gint             *nreturn_vals,
53
56
                         GimpParam       **return_vals);
54
57
 
55
 
static void      gauss             (GimpDrawable     *drawable,
56
 
                                    gdouble           horizontal,
57
 
                                    gdouble           vertical,
58
 
                                    BlurMethod        method,
59
 
                                    GtkWidget        *preview);
 
58
static void      gauss             (GimpDrawable *drawable,
 
59
                                    gdouble       horizontal,
 
60
                                    gdouble       vertical,
 
61
                                    BlurMethod    method,
 
62
                                    GtkWidget    *preview);
60
63
 
61
 
static void      update_preview    (GtkWidget        *preview,
62
 
                                    GtkWidget        *size);
 
64
static void      update_preview    (GtkWidget    *preview,
 
65
                                    GtkWidget    *size);
63
66
/*
64
67
 * Gaussian blur interface
65
68
 */
66
 
static gboolean  gauss_dialog      (gint32            image_ID,
67
 
                                    GimpDrawable     *drawable);
 
69
static gboolean  gauss_dialog      (gint32        image_ID,
 
70
                                    GimpDrawable *drawable);
68
71
 
69
72
/*
70
73
 * Gaussian blur helper functions
71
74
 */
72
 
static void      find_constants    (gdouble  n_p[],
73
 
                                    gdouble  n_m[],
74
 
                                    gdouble  d_p[],
75
 
                                    gdouble  d_m[],
76
 
                                    gdouble  bd_p[],
77
 
                                    gdouble  bd_m[],
78
 
                                    gdouble  std_dev);
79
 
static void      transfer_pixels   (gdouble *src1,
80
 
                                    gdouble *src2,
81
 
                                    guchar  *dest,
82
 
                                    gint     bytes,
83
 
                                    gint     width);
84
 
 
85
 
static gint *    make_curve        (gdouble    sigma,
86
 
                                    gint      *length);
87
 
static void      run_length_encode (guchar    *src,
88
 
                                    gint      *dest,
89
 
                                    gint       bytes,
90
 
                                    gint       width);
91
 
 
92
 
 
93
 
GimpPlugInInfo PLUG_IN_INFO =
 
75
static void      find_iir_constants    (gdouble  n_p[],
 
76
                                        gdouble  n_m[],
 
77
                                        gdouble  d_p[],
 
78
                                        gdouble  d_m[],
 
79
                                        gdouble  bd_p[],
 
80
                                        gdouble  bd_m[],
 
81
                                        gdouble  std_dev);
 
82
 
 
83
static void      transfer_pixels   (const gdouble *src1,
 
84
                                    const gdouble *src2,
 
85
                                    guchar        *dest,
 
86
                                    gint           bytes,
 
87
                                    gint           width);
 
88
 
 
89
static void      make_rle_curve    (gdouble   sigma,
 
90
                                    gint    **p_curve,
 
91
                                    gint     *p_length,
 
92
                                    gint    **p_sum,
 
93
                                    gint     *p_total);
 
94
 
 
95
static void      free_rle_curve    (gint     *curve,
 
96
                                    gint      length,
 
97
                                    gint     *sum);
 
98
 
 
99
static inline gint run_length_encode (const guchar *src,
 
100
                                      gint         *repeat,
 
101
                                      gint         *dest,
 
102
                                      gint          bytes,
 
103
                                      gint          width,
 
104
                                      gint          border,
 
105
                                      gboolean      pack);
 
106
 
 
107
 
 
108
const GimpPlugInInfo PLUG_IN_INFO =
94
109
{
95
110
  NULL,  /* init_proc  */
96
111
  NULL,  /* quit_proc  */
102
117
{
103
118
  5.0,  /*  x radius  */
104
119
  5.0,  /*  y radius  */
105
 
  BLUR_IIR
 
120
  BLUR_RLE
106
121
};
107
122
 
108
123
 
111
126
static void
112
127
query (void)
113
128
{
114
 
  static GimpParamDef args[] =
115
 
  {
116
 
    { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
117
 
    { GIMP_PDB_IMAGE, "image", "Input image" },
118
 
    { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
119
 
    { GIMP_PDB_FLOAT, "horizontal", "Horizontal radius of gaussian blur (in pixels, > 0.0)" },
120
 
    { GIMP_PDB_FLOAT, "vertical",   "Vertical radius of gaussian blur (in pixels, > 0.0)" },
121
 
    { GIMP_PDB_INT32, "method",   "IIR (0) or RLE (1)" }
122
 
  };
123
 
 
124
 
  static GimpParamDef args1[] =
125
 
  {
126
 
    { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
127
 
    { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
128
 
    { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
129
 
    { GIMP_PDB_FLOAT, "radius", "Radius of gaussian blur (in pixels, > 0.0)" },
130
 
    { GIMP_PDB_INT32, "horizontal", "Blur in horizontal direction" },
131
 
    { GIMP_PDB_INT32, "vertical", "Blur in vertical direction" }
132
 
  };
133
 
 
134
 
  static GimpParamDef args2[] =
135
 
  {
136
 
    { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
137
 
    { GIMP_PDB_IMAGE, "image", "Input image" },
138
 
    { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
139
 
    { GIMP_PDB_FLOAT, "horizontal", "Horizontal radius of gaussian blur (in pixels, > 0.0)" },
140
 
    { GIMP_PDB_FLOAT, "vertical",   "Vertical radius of gaussian blur (in pixels, > 0.0)" }
141
 
  };
142
 
 
143
 
  gimp_install_procedure ("plug_in_gauss",
144
 
                          "Applies a gaussian blur to the specified drawable.",
 
129
  static const GimpParamDef args[] =
 
130
  {
 
131
    { GIMP_PDB_INT32,    "run-mode",   "Interactive, non-interactive" },
 
132
    { GIMP_PDB_IMAGE,    "image",      "Input image" },
 
133
    { GIMP_PDB_DRAWABLE, "drawable",   "Input drawable" },
 
134
    { GIMP_PDB_FLOAT,    "horizontal", "Horizontal radius of gaussian blur (in pixels, > 0.0)" },
 
135
    { GIMP_PDB_FLOAT,    "vertical",   "Vertical radius of gaussian blur (in pixels, > 0.0)" },
 
136
    { GIMP_PDB_INT32,    "method",     "IIR (0) or RLE (1)" }
 
137
  };
 
138
 
 
139
  static const GimpParamDef args1[] =
 
140
  {
 
141
    { GIMP_PDB_INT32,    "run-mode",   "Interactive, non-interactive" },
 
142
    { GIMP_PDB_IMAGE,    "image",      "Input image (unused)" },
 
143
    { GIMP_PDB_DRAWABLE, "drawable",   "Input drawable" },
 
144
    { GIMP_PDB_FLOAT,    "radius",     "Radius of gaussian blur (in pixels, > 0.0)" },
 
145
    { GIMP_PDB_INT32,    "horizontal", "Blur in horizontal direction" },
 
146
    { GIMP_PDB_INT32,    "vertical",   "Blur in vertical direction" }
 
147
  };
 
148
 
 
149
  static const GimpParamDef args2[] =
 
150
  {
 
151
    { GIMP_PDB_INT32,    "run-mode",   "Interactive, non-interactive" },
 
152
    { GIMP_PDB_IMAGE,    "image",      "Input image" },
 
153
    { GIMP_PDB_DRAWABLE, "drawable",   "Input drawable" },
 
154
    { GIMP_PDB_FLOAT,    "horizontal", "Horizontal radius of gaussian blur (in pixels, > 0.0)" },
 
155
    { GIMP_PDB_FLOAT,    "vertical",   "Vertical radius of gaussian blur (in pixels, > 0.0)" }
 
156
  };
 
157
 
 
158
  gimp_install_procedure (GAUSS_PROC,
 
159
                          N_("Simplest, most commonly used way of blurring"),
145
160
                          "Applies a gaussian blur to the drawable, with "
146
161
                          "specified radius of affect.  The standard deviation "
147
162
                          "of the normal distribution used to modify pixel "
160
175
                          G_N_ELEMENTS (args), 0,
161
176
                          args, NULL);
162
177
 
163
 
  gimp_install_procedure ("plug_in_gauss_iir",
164
 
                          "Applies a gaussian blur to the specified drawable.",
 
178
  gimp_install_procedure (GAUSS_IIR_PROC,
 
179
                          N_("Apply a gaussian blur"),
165
180
                          "Applies a gaussian blur to the drawable, with "
166
181
                          "specified radius of affect.  The standard deviation "
167
182
                          "of the normal distribution used to modify pixel "
180
195
                          G_N_ELEMENTS (args1), 0,
181
196
                          args1, NULL);
182
197
 
183
 
  gimp_install_procedure ("plug_in_gauss_iir2",
184
 
                          "Applies a gaussian blur to the specified drawable.",
 
198
  gimp_install_procedure (GAUSS_IIR2_PROC,
 
199
                          N_("Apply a gaussian blur"),
185
200
                          "Applies a gaussian blur to the drawable, with "
186
201
                          "specified radius of affect.  The standard deviation "
187
202
                          "of the normal distribution used to modify pixel "
200
215
                          G_N_ELEMENTS (args2), 0,
201
216
                          args2, NULL);
202
217
 
203
 
  gimp_install_procedure ("plug_in_gauss_rle",
204
 
                          "Applies a gaussian blur to the specified drawable.",
 
218
  gimp_install_procedure (GAUSS_RLE_PROC,
 
219
                          N_("Apply a gaussian blur"),
205
220
                          "Applies a gaussian blur to the drawable, with "
206
221
                          "specified radius of affect.  The standard deviation "
207
222
                          "of the normal distribution used to modify pixel "
220
235
                          G_N_ELEMENTS (args1), 0,
221
236
                          args1, NULL);
222
237
 
223
 
  gimp_install_procedure ("plug_in_gauss_rle2",
224
 
                          "Applies a gaussian blur to the specified drawable.",
 
238
  gimp_install_procedure (GAUSS_RLE2_PROC,
 
239
                          N_("Apply a gaussian blur"),
225
240
                          "Applies a gaussian blur to the drawable, with "
226
241
                          "specified radius of affect.  The standard deviation "
227
242
                          "of the normal distribution used to modify pixel "
240
255
                          G_N_ELEMENTS (args2), 0,
241
256
                          args2, NULL);
242
257
 
243
 
  gimp_plugin_menu_register ("plug_in_gauss", "<Image>/Filters/Blur");
 
258
  gimp_plugin_menu_register (GAUSS_PROC, "<Image>/Filters/Blur");
244
259
}
245
260
 
246
261
static void
272
287
  drawable = gimp_drawable_get (param[2].data.d_drawable);
273
288
 
274
289
  /*  set the tile cache size so that the gaussian blur works well  */
275
 
  gimp_tile_cache_ntiles (2 *
 
290
  gimp_tile_cache_ntiles (2*
276
291
                          (MAX (drawable->width, drawable->height) /
277
292
                           gimp_tile_width () + 1));
278
293
 
279
294
 
280
 
  if (strcmp (name, "plug_in_gauss") == 0)
 
295
  if (strcmp (name, GAUSS_PROC) == 0)
281
296
    {
282
297
      switch (run_mode)
283
298
        {
284
299
        case GIMP_RUN_INTERACTIVE:
285
300
          /*  Possibly retrieve data  */
286
 
          gimp_get_data ("plug_in_gauss", &bvals);
 
301
          gimp_get_data (GAUSS_PROC, &bvals);
287
302
 
288
303
          /*  First acquire information with a dialog  */
289
304
          if (! gauss_dialog (image_ID, drawable))
308
323
 
309
324
        case GIMP_RUN_WITH_LAST_VALS:
310
325
          /*  Possibly retrieve data  */
311
 
          gimp_get_data ("plug_in_gauss", &bvals);
 
326
          gimp_get_data (GAUSS_PROC, &bvals);
312
327
          break;
313
328
 
314
329
        default:
315
330
          break;
316
331
        }
317
332
    }
318
 
  else if (strcmp (name, "plug_in_gauss_iir") == 0)
 
333
  else if (strcmp (name, GAUSS_IIR_PROC) == 0)
319
334
    {
320
335
      if (nparams != 6)
321
336
        status = GIMP_PDB_CALLING_ERROR;
337
352
            return;
338
353
        }
339
354
    }
340
 
  else if (strcmp (name, "plug_in_gauss_iir2") == 0)
 
355
  else if (strcmp (name, GAUSS_IIR2_PROC) == 0)
341
356
    {
342
357
      if (nparams != 5)
343
358
        status = GIMP_PDB_CALLING_ERROR;
358
373
            return;
359
374
        }
360
375
    }
361
 
  else if (strcmp (name, "plug_in_gauss_rle") == 0)
 
376
  else if (strcmp (name, GAUSS_RLE_PROC) == 0)
362
377
    {
363
378
      if (nparams != 6)
364
379
        status = GIMP_PDB_CALLING_ERROR;
380
395
            return;
381
396
        }
382
397
    }
383
 
  else if (strcmp (name, "plug_in_gauss_rle2") == 0)
 
398
  else if (strcmp (name, GAUSS_RLE2_PROC) == 0)
384
399
    {
385
400
      if (nparams != 5)
386
401
        status = GIMP_PDB_CALLING_ERROR;
410
425
      if (gimp_drawable_is_rgb (drawable->drawable_id) ||
411
426
          gimp_drawable_is_gray (drawable->drawable_id))
412
427
        {
413
 
          gimp_progress_init (_("Gaussian Blur..."));
 
428
          gimp_progress_init (_("Gaussian Blur"));
414
429
 
415
430
          /*  run the gaussian blur  */
416
431
          gauss (drawable,
420
435
 
421
436
          /*  Store data  */
422
437
          if (run_mode == GIMP_RUN_INTERACTIVE)
423
 
            gimp_set_data ("plug_in_gauss",
424
 
                           &bvals, sizeof (BlurValues));
 
438
            gimp_set_data (GAUSS_PROC, &bvals, sizeof (BlurValues));
425
439
 
426
440
          if (run_mode != GIMP_RUN_NONINTERACTIVE)
427
441
            gimp_displays_flush ();
449
463
  GtkWidget *frame;
450
464
  GtkWidget *size;
451
465
  GtkWidget *hbox;
 
466
  GtkWidget *button;
452
467
  GtkWidget *preview;
453
468
 
454
469
  GimpUnit   unit;
456
471
  gdouble    yres;
457
472
  gboolean   run;
458
473
 
459
 
  gimp_ui_init ("gaussian_blur", FALSE);
 
474
  gimp_ui_init (PLUG_IN_BINARY, FALSE);
460
475
 
461
 
  dialog = gimp_dialog_new (_("Gaussian Blur"), "gaussian_blur",
 
476
  dialog = gimp_dialog_new (_("Gaussian Blur"), PLUG_IN_BINARY,
462
477
                            NULL, 0,
463
 
                            gimp_standard_help_func, "plug-in-gauss",
 
478
                            gimp_standard_help_func, GAUSS_PROC,
464
479
 
465
480
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
466
481
                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
467
482
 
468
483
                            NULL);
469
484
 
 
485
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
 
486
                                           GTK_RESPONSE_OK,
 
487
                                           GTK_RESPONSE_CANCEL,
 
488
                                           -1);
 
489
 
 
490
  gimp_window_set_transient (GTK_WINDOW (dialog));
 
491
 
470
492
  main_vbox = gtk_vbox_new (FALSE, 12);
471
493
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
472
494
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
482
504
 
483
505
  /*  parameter settings  */
484
506
  frame = gimp_frame_new (_("Blur Radius"));
485
 
  gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
 
507
  gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
486
508
  gtk_widget_show (frame);
487
509
 
488
510
  /*  Get the image resolution and unit  */
511
533
 
512
534
  /*  FIXME: Shouldn't need two signal connections here,
513
535
             gimp_coordinates_new() seems to be severily broken.  */
514
 
  g_signal_connect_swapped (size, "value_changed",
 
536
  g_signal_connect_swapped (size, "value-changed",
515
537
                            G_CALLBACK (gimp_preview_invalidate),
516
538
                            preview);
517
 
  g_signal_connect_swapped (size, "refval_changed",
 
539
  g_signal_connect_swapped (size, "refval-changed",
518
540
                            G_CALLBACK (gimp_preview_invalidate),
519
541
                            preview);
520
542
 
526
548
                                    G_CALLBACK (gimp_radio_button_update),
527
549
                                    &bvals.method, bvals.method,
528
550
 
529
 
                                    _("_IIR"), BLUR_IIR, NULL,
 
551
                                    _("_IIR"), BLUR_IIR, &button,
530
552
                                    _("_RLE"), BLUR_RLE, NULL,
531
553
 
532
554
                                    NULL);
533
555
 
 
556
  g_signal_connect_swapped (button, "toggled",
 
557
                            G_CALLBACK (gimp_preview_invalidate),
 
558
                            preview);
 
559
 
534
560
  gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
535
561
  gtk_widget_show (frame);
536
562
 
604
630
    }
605
631
}
606
632
 
607
 
static void
608
 
gauss (GimpDrawable *drawable,
609
 
       gdouble       horz,
610
 
       gdouble       vert,
611
 
       BlurMethod    method,
612
 
       GtkWidget    *preview)
 
633
/*
 
634
 * run_length_encode (src, rle, pix, dist, width, border, pack);
 
635
 *
 
636
 * Copy 'width' 8bit pixels from 'src' to 'pix' and extend both sides
 
637
 * by 'border' pixels so 'pix[]' is filled from '-border' to 'width+border-1'.
 
638
 *
 
639
 * 'dist' is the distance between the pixels in 'src'.
 
640
 *
 
641
 * If 'pack' is TRUE, then 'rle' is filled with a run-length encoding
 
642
 * of the pixels. In plain english, that means that rle[i] gives the
 
643
 * number of times the same pixel is found pix[i], pix[i+1], ...  A
 
644
 * standalone pixel has a rle value of 1.
 
645
 *
 
646
 * The function returns the number of times 2 identical consecutive pixels
 
647
 * were found.
 
648
 *
 
649
 * Note: The function must be inlined to insure that all tests on
 
650
 *       'pack' are efficiently resolved by the compiler (they are in
 
651
 *       the critical loop).  As a consequence, the function should
 
652
 *       only be called with known constant value for 'pack'.  In the
 
653
 *       current implementation, 'pack' is always TRUE but it might be
 
654
 *       more efficient to have an 'adaptive' algorithm that switches
 
655
 *       to FALSE when the run-length is innefficient.
 
656
 */
 
657
static inline gint
 
658
run_length_encode (const guchar *src,
 
659
                   gint         *rle,
 
660
                   gint         *pix,
 
661
                   gint          dist,  /* distance between 2 src pixels */
 
662
                   gint          width,
 
663
                   gint          border,
 
664
                   gboolean      pack)
 
665
{
 
666
  gint last;
 
667
  gint count = 0;
 
668
  gint i     = width;
 
669
  gint same  = 0;
 
670
 
 
671
  src += dist * (width - 1);
 
672
 
 
673
  if (pack)
 
674
    rle += width + border - 1;
 
675
 
 
676
  pix += width + border - 1;
 
677
 
 
678
  last  = *src;
 
679
  count = 0;
 
680
 
 
681
  /* the 'end' border */
 
682
  for (i = 0; i < border; i++)
 
683
    {
 
684
      count++;
 
685
      *pix--  = last;
 
686
 
 
687
      if (pack)
 
688
        *rle-- = count;
 
689
  }
 
690
 
 
691
  /* the real pixels */
 
692
  for (i = 0; i < width; i++)
 
693
    {
 
694
      gint c = *src;
 
695
      src -= dist;
 
696
 
 
697
      if (pack && c==last)
 
698
        {
 
699
          count++;
 
700
          *pix-- = last;
 
701
          *rle-- = count;
 
702
          same++;
 
703
        }
 
704
      else
 
705
        {
 
706
          count   = 1;
 
707
          last    = c;
 
708
          *pix--  = last;
 
709
 
 
710
          if (pack)
 
711
            *rle-- = count;
 
712
        }
 
713
    }
 
714
 
 
715
  /* the start pixels */
 
716
  for (i = 0; i < border; i++)
 
717
    {
 
718
      count++;
 
719
      *pix-- = last;
 
720
 
 
721
      if (pack)
 
722
        *rle-- = count;
 
723
  }
 
724
 
 
725
  return same;
 
726
}
 
727
 
 
728
 
 
729
static void
 
730
do_encoded_lre (const gint *enc,
 
731
                const gint *src,
 
732
                guchar     *dest,
 
733
                gint        width,
 
734
                gint        length,
 
735
                gint        dist,
 
736
                const gint *curve,
 
737
                gint        ctotal,
 
738
                const gint *csum)
 
739
{
 
740
  gint col;
 
741
 
 
742
  for (col = 0; col < width; col++)
 
743
    {
 
744
      const gint *rpt;
 
745
      const gint *pix;
 
746
      gint        nb;
 
747
      gint        s1;
 
748
      gint        i;
 
749
      gint        val   = 0;
 
750
      gint        start = - length;
 
751
 
 
752
      rpt = &enc[col + start];
 
753
      pix = &src[col + start];
 
754
 
 
755
      s1 = csum[start];
 
756
      nb = rpt[0];
 
757
      i  = start + nb;
 
758
 
 
759
      while (i <= length)
 
760
        {
 
761
          gint s2 = csum[i];
 
762
 
 
763
          val += pix[0] * (s2-s1);
 
764
          s1 = s2;
 
765
          rpt = &rpt[nb];
 
766
          pix = &pix[nb];
 
767
          nb = rpt[0];
 
768
          i += nb;
 
769
        }
 
770
 
 
771
      val += pix[0] * (csum[length] - s1);
 
772
 
 
773
      *dest = val / ctotal;
 
774
 
 
775
      dest += dist;
 
776
    }
 
777
}
 
778
 
 
779
static void
 
780
do_full_lre (const gint *src,
 
781
             guchar     *dest,
 
782
             gint        width,
 
783
             gint        length,
 
784
             gint        dist,
 
785
             const gint *curve,
 
786
             gint        ctotal)
 
787
{
 
788
  gint col;
 
789
 
 
790
  for (col = 0; col < width; col++)
 
791
    {
 
792
      const gint *x1;
 
793
      const gint *x2;
 
794
      const gint *c = &curve[0];
 
795
      gint        i;
 
796
      gint        val;
 
797
 
 
798
      x1 = x2 = &src[col];
 
799
 
 
800
      /* The central point is a special case since it should only be
 
801
       * processed ONCE
 
802
       */
 
803
 
 
804
      val = x1[0] * c[0];
 
805
 
 
806
      c  += 1;
 
807
      x1 += 1;
 
808
      x2 -= 1;
 
809
      i   = length;
 
810
 
 
811
      /* Processing multiple points in a single iteration should be
 
812
       * faster but is not strictly required.
 
813
       * Some precise benchmarking will be needed to figure out
 
814
       * if this is really interesting.
 
815
       */
 
816
      while (i >= 8)
 
817
        {
 
818
          val += (x1[0] + x2[-0]) * c[0];
 
819
          val += (x1[1] + x2[-1]) * c[1];
 
820
          val += (x1[2] + x2[-2]) * c[2];
 
821
          val += (x1[3] + x2[-3]) * c[3];
 
822
          val += (x1[4] + x2[-4]) * c[4];
 
823
          val += (x1[5] + x2[-5]) * c[5];
 
824
          val += (x1[6] + x2[-6]) * c[6];
 
825
          val += (x1[7] + x2[-7]) * c[7];
 
826
 
 
827
          c  += 8;
 
828
          x1 += 8;
 
829
          x2 -= 8;
 
830
          i  -= 8;
 
831
        }
 
832
 
 
833
      while (i >= 4)
 
834
        {
 
835
          val += (x1[0] + x2[-0]) * c[0];
 
836
          val += (x1[1] + x2[-1]) * c[1];
 
837
          val += (x1[2] + x2[-2]) * c[2];
 
838
          val += (x1[3] + x2[-3]) * c[3];
 
839
          c  += 4;
 
840
          x1 += 4;
 
841
          x2 -= 4;
 
842
          i  -= 4;
 
843
        }
 
844
 
 
845
      /* Only that final loop is strictly required */
 
846
 
 
847
      while (i >= 1)
 
848
        {
 
849
          /* process the pixels at the distance i before and after the
 
850
           * central point. They must have the same coefficient
 
851
           */
 
852
          val += (x1[0] + x2[-0]) * c[0];
 
853
          c  += 1;
 
854
          x1 += 1;
 
855
          x2 -= 1;
 
856
          i  -= 1;
 
857
        }
 
858
 
 
859
      *dest = val / ctotal;
 
860
      dest += dist;
 
861
 
 
862
    }
 
863
}
 
864
 
 
865
static void
 
866
gauss_iir (GimpDrawable *drawable,
 
867
           gdouble       horz,
 
868
           gdouble       vert,
 
869
           BlurMethod    method,
 
870
           guchar       *preview_buffer,
 
871
           gint          x1,
 
872
           gint          y1,
 
873
           gint          width,
 
874
           gint          height)
613
875
{
614
876
  GimpPixelRgn  src_rgn, dest_rgn;
615
 
  gint          width, height;
616
877
  gint          bytes;
617
878
  gint          has_alpha;
618
 
  guchar       *dest, *dp;
619
 
  guchar       *src, *sp, *sp_p, *sp_m;
620
 
  gint         *buf = NULL;
621
 
  gint         *bb;
 
879
  guchar       *dest;
 
880
  guchar       *src,  *sp_p, *sp_m;
622
881
  gdouble       n_p[5], n_m[5];
623
882
  gdouble       d_p[5], d_m[5];
624
883
  gdouble       bd_p[5], bd_m[5];
625
884
  gdouble      *val_p = NULL;
626
885
  gdouble      *val_m = NULL;
627
886
  gdouble      *vp, *vm;
628
 
  gint          x1, y1, x2, y2;
629
887
  gint          i, j;
630
888
  gint          row, col, b;
631
889
  gint          terms;
633
891
  gint          initial_p[4];
634
892
  gint          initial_m[4];
635
893
  gdouble       std_dev;
636
 
  gint          pixels;
 
894
  gboolean      direct;
 
895
  gint          progress_step;
 
896
 
 
897
 
 
898
  direct = (preview_buffer == NULL);
 
899
 
 
900
  bytes = drawable->bpp;
 
901
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
 
902
 
 
903
  val_p = g_new (gdouble, MAX (width, height) * bytes);
 
904
  val_m = g_new (gdouble, MAX (width, height) * bytes);
 
905
 
 
906
  src =  g_new (guchar, MAX (width, height) * bytes);
 
907
  dest = g_new (guchar, MAX (width, height) * bytes);
 
908
 
 
909
  gimp_pixel_rgn_init (&src_rgn,
 
910
                       drawable, 0, 0, drawable->width, drawable->height,
 
911
                       FALSE, FALSE);
 
912
  if (direct)
 
913
    {
 
914
      gimp_pixel_rgn_init (&dest_rgn,
 
915
                           drawable, 0, 0, drawable->width, drawable->height,
 
916
                           TRUE, TRUE);
 
917
    }
 
918
 
 
919
 
 
920
  progress = 0.0;
 
921
  max_progress  = (horz <= 0.0) ? 0 : width * height * horz;
 
922
  max_progress += (vert <= 0.0) ? 0 : width * height * vert;
 
923
 
 
924
 
 
925
  /*  First the vertical pass  */
 
926
  if (vert > 0.0)
 
927
    {
 
928
      vert = fabs (vert) + 1.0;
 
929
      std_dev = sqrt (-(vert * vert) / (2 * log (1.0 / 255.0)));
 
930
 
 
931
      /* We do not want too many progress updates because they
 
932
       * can slow down the processing significantly for very
 
933
       * large images
 
934
       */
 
935
      progress_step = width / 100;
 
936
      if (progress_step < 5)
 
937
        progress_step = 5;
 
938
 
 
939
      /*  derive the constants for calculating the gaussian
 
940
       *  from the std dev
 
941
       */
 
942
 
 
943
      find_iir_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
 
944
 
 
945
      for (col = 0; col < width; col++)
 
946
        {
 
947
          memset (val_p, 0, height * bytes * sizeof (gdouble));
 
948
          memset (val_m, 0, height * bytes * sizeof (gdouble));
 
949
 
 
950
          gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, height);
 
951
 
 
952
          if (has_alpha)
 
953
            multiply_alpha (src, height, bytes);
 
954
 
 
955
          sp_p = src;
 
956
          sp_m = src + (height - 1) * bytes;
 
957
          vp = val_p;
 
958
          vm = val_m + (height - 1) * bytes;
 
959
 
 
960
          /*  Set up the first vals  */
 
961
          for (i = 0; i < bytes; i++)
 
962
            {
 
963
              initial_p[i] = sp_p[i];
 
964
              initial_m[i] = sp_m[i];
 
965
            }
 
966
 
 
967
          for (row = 0; row < height; row++)
 
968
            {
 
969
              gdouble *vpptr, *vmptr;
 
970
              terms = (row < 4) ? row : 4;
 
971
 
 
972
              for (b = 0; b < bytes; b++)
 
973
                {
 
974
                  vpptr = vp + b; vmptr = vm + b;
 
975
                  for (i = 0; i <= terms; i++)
 
976
                    {
 
977
                      *vpptr += n_p[i] * sp_p[(-i * bytes) + b] - d_p[i] * vp[(-i * bytes) + b];
 
978
                      *vmptr += n_m[i] * sp_m[(i * bytes) + b] - d_m[i] * vm[(i * bytes) + b];
 
979
                    }
 
980
                  for (j = i; j <= 4; j++)
 
981
                    {
 
982
                      *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
 
983
                      *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
 
984
                    }
 
985
                }
 
986
 
 
987
              sp_p += bytes;
 
988
              sp_m -= bytes;
 
989
              vp += bytes;
 
990
              vm -= bytes;
 
991
            }
 
992
 
 
993
          transfer_pixels (val_p, val_m, dest, bytes, height);
 
994
 
 
995
 
 
996
          if (has_alpha)
 
997
            separate_alpha (dest, height, bytes);
 
998
 
 
999
          if (direct)
 
1000
            {
 
1001
              gimp_pixel_rgn_set_col(&dest_rgn, dest, col + x1, y1, height);
 
1002
 
 
1003
              progress += height * vert;
 
1004
              if ((col % progress_step) == 0)
 
1005
                gimp_progress_update (progress / max_progress);
 
1006
            }
 
1007
          else
 
1008
            {
 
1009
              for (row = 0; row < height; row++)
 
1010
                memcpy (preview_buffer + (row * width + col) * bytes,
 
1011
                        dest + row * bytes,
 
1012
                        bytes);
 
1013
            }
 
1014
        }
 
1015
 
 
1016
      /*  prepare for the horizontal pass  */
 
1017
      gimp_pixel_rgn_init (&src_rgn,
 
1018
                           drawable,
 
1019
                           0, 0,
 
1020
                           drawable->width, drawable->height,
 
1021
                           FALSE, TRUE);
 
1022
    }
 
1023
  else if (!direct)
 
1024
    {
 
1025
      gimp_pixel_rgn_get_rect (&src_rgn,
 
1026
                               preview_buffer,
 
1027
                               x1, y1,
 
1028
                               width, height);
 
1029
    }
 
1030
 
 
1031
  /*  Now the horizontal pass  */
 
1032
  if (horz > 0.0)
 
1033
    {
 
1034
 
 
1035
      /* We do not want too many progress updates because they
 
1036
       * can slow down the processing significantly for very
 
1037
       * large images
 
1038
       */
 
1039
      progress_step = height / 100;
 
1040
 
 
1041
      if (progress_step < 5)
 
1042
        progress_step = 5;
 
1043
 
 
1044
      horz = fabs (horz) + 1.0;
 
1045
 
 
1046
      if (horz != vert)
 
1047
        {
 
1048
          std_dev = sqrt (-(horz * horz) / (2 * log (1.0 / 255.0)));
 
1049
 
 
1050
          /*  derive the constants for calculating the gaussian
 
1051
           *  from the std dev
 
1052
           */
 
1053
          find_iir_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
 
1054
 
 
1055
        }
 
1056
 
 
1057
 
 
1058
      for (row = 0; row < height; row++)
 
1059
        {
 
1060
 
 
1061
          memset (val_p, 0, width * bytes * sizeof (gdouble));
 
1062
          memset (val_m, 0, width * bytes * sizeof (gdouble));
 
1063
 
 
1064
          if (direct)
 
1065
            {
 
1066
              gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, width);
 
1067
            }
 
1068
          else
 
1069
            {
 
1070
              memcpy (src,
 
1071
                      preview_buffer + row * width * bytes,
 
1072
                      width * bytes);
 
1073
            }
 
1074
 
 
1075
 
 
1076
          if (has_alpha)
 
1077
            multiply_alpha (src, width, bytes);
 
1078
 
 
1079
 
 
1080
          sp_p = src;
 
1081
          sp_m = src + (width - 1) * bytes;
 
1082
          vp = val_p;
 
1083
          vm = val_m + (width - 1) * bytes;
 
1084
 
 
1085
          /*  Set up the first vals  */
 
1086
          for (i = 0; i < bytes; i++)
 
1087
            {
 
1088
              initial_p[i] = sp_p[i];
 
1089
              initial_m[i] = sp_m[i];
 
1090
            }
 
1091
 
 
1092
          for (col = 0; col < width; col++)
 
1093
            {
 
1094
              gdouble *vpptr, *vmptr;
 
1095
 
 
1096
              terms = (col < 4) ? col : 4;
 
1097
 
 
1098
              for (b = 0; b < bytes; b++)
 
1099
                {
 
1100
                  vpptr = vp + b; vmptr = vm + b;
 
1101
 
 
1102
                  for (i = 0; i <= terms; i++)
 
1103
                    {
 
1104
                      *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
 
1105
                        d_p[i] * vp[(-i * bytes) + b];
 
1106
                      *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
 
1107
                        d_m[i] * vm[(i * bytes) + b];
 
1108
                    }
 
1109
                  for (j = i; j <= 4; j++)
 
1110
                    {
 
1111
                      *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
 
1112
                      *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
 
1113
                    }
 
1114
                }
 
1115
 
 
1116
              sp_p += bytes;
 
1117
              sp_m -= bytes;
 
1118
              vp += bytes;
 
1119
              vm -= bytes;
 
1120
            }
 
1121
 
 
1122
          transfer_pixels (val_p, val_m, dest, bytes, width);
 
1123
 
 
1124
          if (has_alpha)
 
1125
            separate_alpha (dest, width, bytes);
 
1126
 
 
1127
          if (direct)
 
1128
            {
 
1129
              gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, width);
 
1130
 
 
1131
              progress += width * horz;
 
1132
 
 
1133
              if ((row % progress_step) == 0)
 
1134
                gimp_progress_update (progress / max_progress);
 
1135
            }
 
1136
          else
 
1137
            {
 
1138
              memcpy (preview_buffer + row * width * bytes,
 
1139
                      dest,
 
1140
                      width * bytes);
 
1141
            }
 
1142
        }
 
1143
    }
 
1144
 
 
1145
  /*  free up buffers  */
 
1146
 
 
1147
  g_free (val_p);
 
1148
  g_free (val_m);
 
1149
 
 
1150
  g_free (src);
 
1151
  g_free (dest);
 
1152
}
 
1153
 
 
1154
 
 
1155
static void
 
1156
gauss_rle (GimpDrawable *drawable,
 
1157
           gdouble       horz,
 
1158
           gdouble       vert,
 
1159
           BlurMethod    method,
 
1160
           guchar       *preview_buffer,
 
1161
           gint          x1,
 
1162
           gint          y1,
 
1163
           gint          width,
 
1164
           gint          height)
 
1165
{
 
1166
  GimpPixelRgn  src_rgn, dest_rgn;
 
1167
  gint          bytes;
 
1168
  gboolean      has_alpha;
 
1169
  guchar       *dest;
 
1170
  guchar       *src;
 
1171
  gint          row, col, b;
 
1172
  gdouble       progress, max_progress;
 
1173
  gdouble       std_dev;
637
1174
  gint          total = 1;
638
 
  gint          start, end;
639
 
  gint         *curve;
640
 
  gint         *sum = NULL;
641
 
  gint          val;
 
1175
  gint         *curve = NULL;
 
1176
  gint         *sum   = NULL;
642
1177
  gint          length;
643
 
  gint          initial_pp, initial_mm;
644
 
  guchar       *preview_buffer1 = NULL;
645
 
  guchar       *preview_buffer2 = NULL;
 
1178
  gboolean      direct;
 
1179
  gint          progress_step;
 
1180
 
 
1181
  direct = (preview_buffer == NULL);
 
1182
 
 
1183
  bytes = drawable->bpp;
 
1184
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
 
1185
 
 
1186
  src  = g_new (guchar, MAX (width, height) * bytes);
 
1187
  dest = g_new (guchar, MAX (width, height) * bytes);
 
1188
 
 
1189
  gimp_pixel_rgn_init (&src_rgn,
 
1190
                       drawable, 0, 0, drawable->width, drawable->height,
 
1191
                       FALSE, FALSE);
 
1192
 
 
1193
  if (direct)
 
1194
    gimp_pixel_rgn_init (&dest_rgn,
 
1195
                         drawable, 0, 0, drawable->width, drawable->height,
 
1196
                         TRUE, TRUE);
 
1197
 
 
1198
  progress = 0.0;
 
1199
  max_progress  = (horz <= 0.0) ? 0 : width * height * horz;
 
1200
  max_progress += (vert <= 0.0) ? 0 : width * height * vert;
 
1201
 
 
1202
 
 
1203
  /*  First the vertical pass  */
 
1204
  if (vert > 0.0)
 
1205
    {
 
1206
      gint   * rle = NULL;
 
1207
      gint   * pix = NULL;
 
1208
 
 
1209
      vert = fabs (vert) + 1.0;
 
1210
      std_dev = sqrt (-(vert * vert) / (2 * log (1.0 / 255.0)));
 
1211
 
 
1212
      /* Insure that we do not have too many progress updates for
 
1213
       * images with a lot of rows or columns
 
1214
       */
 
1215
      progress_step = width / 150;
 
1216
 
 
1217
      if (progress_step < 5)
 
1218
        progress_step = 5;
 
1219
 
 
1220
      make_rle_curve (std_dev, &curve, &length, &sum, &total);
 
1221
 
 
1222
      rle = g_new (gint, height + 2 * length);
 
1223
      rle += length; /* rle[] extends from -length to height+length-1 */
 
1224
 
 
1225
      pix = g_new (gint, height + 2 * length);
 
1226
      pix += length; /* pix[] extends from -length to height+length-1 */
 
1227
 
 
1228
      for (col = 0; col < width; col++)
 
1229
        {
 
1230
 
 
1231
          gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, height);
 
1232
 
 
1233
          if (has_alpha)
 
1234
            multiply_alpha (src, height, bytes);
 
1235
 
 
1236
          for (b = 0; b < bytes; b++)
 
1237
            {
 
1238
              gint same =  run_length_encode (src + b, rle, pix, bytes,
 
1239
                                              height, length, TRUE);
 
1240
 
 
1241
              if (same > (3 * height) / 4)
 
1242
                {
 
1243
                  /* encoded_rle is only fastest if there are a lot of
 
1244
                   * repeating pixels
 
1245
                   */
 
1246
                  do_encoded_lre (rle, pix, dest + b, height, length, bytes,
 
1247
                                  curve, total, sum);
 
1248
                }
 
1249
              else
 
1250
                {
 
1251
                  /* else a full but more simple algorithm is better */
 
1252
                  do_full_lre (pix, dest + b, height, length, bytes,
 
1253
                               curve, total);
 
1254
                }
 
1255
            }
 
1256
 
 
1257
          if (has_alpha)
 
1258
            separate_alpha (dest, height, bytes);
 
1259
 
 
1260
          if (direct)
 
1261
            {
 
1262
              gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, height);
 
1263
 
 
1264
              progress += height * vert;
 
1265
              if ((col % progress_step) == 0)
 
1266
                gimp_progress_update (progress / max_progress);
 
1267
            }
 
1268
          else
 
1269
            {
 
1270
              for (row = 0; row < height; row++)
 
1271
                memcpy (preview_buffer + (row * width + col) * bytes,
 
1272
                        dest + row * bytes,
 
1273
                        bytes);
 
1274
            }
 
1275
 
 
1276
        }
 
1277
 
 
1278
 
 
1279
      g_free (rle - length);
 
1280
      g_free (pix - length);
 
1281
 
 
1282
      /* prepare for the horizontal pass  */
 
1283
      gimp_pixel_rgn_init (&src_rgn,
 
1284
                           drawable, 0, 0, drawable->width, drawable->height,
 
1285
                           FALSE, TRUE);
 
1286
    }
 
1287
  else if (!direct)
 
1288
    {
 
1289
      gimp_pixel_rgn_get_rect (&src_rgn,
 
1290
                               preview_buffer, x1, y1, width, height);
 
1291
    }
 
1292
 
 
1293
  /*  Now the horizontal pass  */
 
1294
  if (horz > 0.0)
 
1295
    {
 
1296
      gint   * rle = NULL;
 
1297
      gint   * pix = NULL;
 
1298
 
 
1299
      /* Insure that we do not have too many progress updates for
 
1300
       * images with a lot of rows or columns
 
1301
       */
 
1302
      progress_step = height / 150;
 
1303
      if (progress_step < 5) {
 
1304
        progress_step = 5;
 
1305
      }
 
1306
 
 
1307
      horz = fabs (horz) + 1.0;
 
1308
 
 
1309
      /* euse the same curve if possible else recompute a new one */
 
1310
      if (horz != vert)
 
1311
        {
 
1312
 
 
1313
          std_dev = sqrt (-(horz * horz) / (2 * log (1.0 / 255.0)));
 
1314
 
 
1315
          if (curve != NULL) {
 
1316
            free_rle_curve(curve, length, sum);
 
1317
          }
 
1318
 
 
1319
          make_rle_curve(std_dev, &curve, &length, &sum, &total);
 
1320
 
 
1321
        }
 
1322
 
 
1323
 
 
1324
      rle = g_new (gint, width+2*length);
 
1325
      rle += length; /* so rle[] extends from -width to width+length-1 */
 
1326
 
 
1327
      pix = g_new (gint, width+2*length);
 
1328
      pix += length; /* so pix[] extends from -width to width+length-1 */
 
1329
 
 
1330
      for (row = 0; row < height; row++)
 
1331
        {
 
1332
          if (direct)
 
1333
            {
 
1334
              gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, width);
 
1335
            }
 
1336
          else
 
1337
            {
 
1338
              memcpy (src,
 
1339
                      preview_buffer + row * width * bytes,
 
1340
                      width * bytes);
 
1341
            }
 
1342
 
 
1343
          if (has_alpha)
 
1344
            multiply_alpha (src, width, bytes);
 
1345
 
 
1346
          for (b = 0; b < bytes; b++)
 
1347
            {
 
1348
              gint same = run_length_encode (src + b, rle, pix, bytes,
 
1349
                                             width, length, TRUE);
 
1350
 
 
1351
              if (same > (3 * width) / 4)
 
1352
                {
 
1353
                  /* encoded_rle is only fastest if there are a lot of
 
1354
                   * repeating pixels
 
1355
                   */
 
1356
                  do_encoded_lre (rle, pix, dest + b, width, length, bytes,
 
1357
                                  curve, total, sum);
 
1358
                }
 
1359
              else
 
1360
                {
 
1361
                  /* else a full but more simple algorithm is better */
 
1362
                  do_full_lre (pix, dest + b, width, length, bytes,
 
1363
                               curve, total);
 
1364
                }
 
1365
            }
 
1366
 
 
1367
 
 
1368
          if (has_alpha)
 
1369
            separate_alpha (dest, width, bytes);
 
1370
 
 
1371
          if (direct)
 
1372
            {
 
1373
              gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, width);
 
1374
 
 
1375
              progress += width * horz;
 
1376
              if ((row % progress_step) == 0)
 
1377
                gimp_progress_update (progress / max_progress);
 
1378
            }
 
1379
          else
 
1380
            {
 
1381
              memcpy (preview_buffer + row * width * bytes,
 
1382
                      dest,
 
1383
                      width * bytes);
 
1384
            }
 
1385
        }
 
1386
 
 
1387
      g_free (rle - length);
 
1388
      g_free (pix - length);
 
1389
    }
 
1390
 
 
1391
  if (curve)
 
1392
    free_rle_curve (curve, length, sum);
 
1393
 
 
1394
  g_free (src);
 
1395
  g_free (dest);
 
1396
}
 
1397
 
 
1398
 
 
1399
static void
 
1400
gauss (GimpDrawable *drawable,
 
1401
       gdouble       horz,
 
1402
       gdouble       vert,
 
1403
       BlurMethod    method,
 
1404
       GtkWidget    *preview)
 
1405
{
 
1406
 
 
1407
  gint    x1, y1, x2, y2;
 
1408
  gint    width, height;
 
1409
  guchar *preview_buffer;
646
1410
 
647
1411
  /*
648
1412
   * IIR goes wrong if the blur radius is less than 1, so we silently
655
1419
    {
656
1420
      if (preview)
657
1421
        gimp_preview_draw (GIMP_PREVIEW (preview));
658
 
 
659
1422
      return;
660
1423
    }
661
1424
 
663
1426
    {
664
1427
      gimp_preview_get_position (GIMP_PREVIEW (preview), &x1, &y1);
665
1428
      gimp_preview_get_size (GIMP_PREVIEW (preview), &width, &height);
 
1429
 
 
1430
      if (width < 1 || height < 1)
 
1431
        return;
 
1432
 
 
1433
      preview_buffer = g_new (guchar, width * height * drawable->bpp);
 
1434
 
666
1435
    }
667
1436
  else
668
1437
    {
670
1439
 
671
1440
      width  = (x2 - x1);
672
1441
      height = (y2 - y1);
673
 
    }
674
 
 
675
 
  if (width < 1 || height < 1)
676
 
    return;
677
 
 
678
 
  bytes = drawable->bpp;
679
 
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
680
 
 
681
 
  switch (method)
682
 
    {
683
 
    case BLUR_IIR:
684
 
      val_p = g_new (gdouble, MAX (width, height) * bytes);
685
 
      val_m = g_new (gdouble, MAX (width, height) * bytes);
686
 
      break;
687
 
 
688
 
    case BLUR_RLE:
689
 
      buf = g_new (gint, MAX (width, height) * 2);
690
 
      break;
691
 
    }
692
 
 
693
 
  src =  g_new (guchar, MAX (width, height) * bytes);
694
 
  dest = g_new (guchar, MAX (width, height) * bytes);
695
 
 
696
 
  gimp_pixel_rgn_init (&src_rgn,
697
 
                       drawable, 0, 0, drawable->width, drawable->height,
698
 
                       FALSE, FALSE);
699
 
  if (preview)
700
 
    {
701
 
      preview_buffer1 = g_new (guchar, width * height * bytes);
702
 
      preview_buffer2 = g_new (guchar, width * height * bytes);
703
 
    }
 
1442
 
 
1443
      if (width < 1 || height < 1)
 
1444
        return;
 
1445
 
 
1446
      preview_buffer = NULL;
 
1447
 
 
1448
    }
 
1449
 
 
1450
 
 
1451
  if (method == BLUR_IIR)
 
1452
    gauss_iir (drawable,
 
1453
               horz, vert, method, preview_buffer, x1, y1, width, height);
704
1454
  else
705
 
    {
706
 
      gimp_pixel_rgn_init (&dest_rgn,
707
 
                           drawable, 0, 0, drawable->width, drawable->height,
708
 
                           TRUE, TRUE);
709
 
    }
710
 
 
711
 
  progress = 0.0;
712
 
  max_progress  = (horz <= 0.0 ) ? 0 : width * height * horz;
713
 
  max_progress += (vert <= 0.0 ) ? 0 : width * height * vert;
714
 
 
715
 
 
716
 
  /*  First the vertical pass  */
717
 
  if (vert > 0.0)
718
 
    {
719
 
      vert = fabs (vert) + 1.0;
720
 
      std_dev = sqrt (-(vert * vert) / (2 * log (1.0 / 255.0)));
721
 
 
722
 
      switch (method)
723
 
        {
724
 
        case BLUR_IIR:
725
 
          /*  derive the constants for calculating the gaussian
726
 
           *  from the std dev
727
 
           */
728
 
          find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
729
 
          break;
730
 
 
731
 
        case BLUR_RLE:
732
 
          curve = make_curve (std_dev, &length);
733
 
          sum = g_new (gint, 2 * length + 1);
734
 
 
735
 
          sum[0] = 0;
736
 
 
737
 
          for (i = 1; i <= length*2; i++)
738
 
            sum[i] = curve[i-length-1] + sum[i-1];
739
 
          sum += length;
740
 
 
741
 
          total = sum[length] - sum[-length];
742
 
          break;
743
 
        }
744
 
 
745
 
      for (col = 0; col < width; col++)
746
 
        {
747
 
          switch (method)
748
 
            {
749
 
            case BLUR_IIR:
750
 
              memset (val_p, 0, height * bytes * sizeof (gdouble));
751
 
              memset (val_m, 0, height * bytes * sizeof (gdouble));
752
 
              break;
753
 
 
754
 
            case BLUR_RLE:
755
 
              break;
756
 
            }
757
 
 
758
 
          gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, height);
759
 
 
760
 
          if (has_alpha)
761
 
            multiply_alpha (src, height, bytes);
762
 
 
763
 
          switch (method)
764
 
            {
765
 
            case BLUR_IIR:
766
 
              sp_p = src;
767
 
              sp_m = src + (height - 1) * bytes;
768
 
              vp = val_p;
769
 
              vm = val_m + (height - 1) * bytes;
770
 
 
771
 
              /*  Set up the first vals  */
772
 
              for (i = 0; i < bytes; i++)
773
 
                {
774
 
                  initial_p[i] = sp_p[i];
775
 
                  initial_m[i] = sp_m[i];
776
 
                }
777
 
 
778
 
              for (row = 0; row < height; row++)
779
 
                {
780
 
                  gdouble *vpptr, *vmptr;
781
 
                  terms = (row < 4) ? row : 4;
782
 
 
783
 
                  for (b = 0; b < bytes; b++)
784
 
                    {
785
 
                      vpptr = vp + b; vmptr = vm + b;
786
 
                      for (i = 0; i <= terms; i++)
787
 
                        {
788
 
                          *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
789
 
                            d_p[i] * vp[(-i * bytes) + b];
790
 
                          *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
791
 
                            d_m[i] * vm[(i * bytes) + b];
792
 
                        }
793
 
                      for (j = i; j <= 4; j++)
794
 
                        {
795
 
                          *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
796
 
                          *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
797
 
                        }
798
 
                    }
799
 
 
800
 
                  sp_p += bytes;
801
 
                  sp_m -= bytes;
802
 
                  vp += bytes;
803
 
                  vm -= bytes;
804
 
                }
805
 
 
806
 
              transfer_pixels (val_p, val_m, dest, bytes, height);
807
 
              break;
808
 
 
809
 
            case BLUR_RLE:
810
 
              sp = src;
811
 
              dp = dest;
812
 
 
813
 
              for (b = 0; b < bytes; b++)
814
 
                {
815
 
                  initial_pp = sp[b];
816
 
                  initial_mm = sp[(height-1) * bytes + b];
817
 
 
818
 
                  /*  Determine a run-length encoded version of the row  */
819
 
                  run_length_encode (sp + b, buf, bytes, height);
820
 
 
821
 
                  for (row = 0; row < height; row++)
822
 
                    {
823
 
                      start = (row < length) ? -row : -length;
824
 
                      end = (height <= (row + length) ?
825
 
                             (height - row - 1) : length);
826
 
 
827
 
                      val = 0;
828
 
                      i = start;
829
 
                      bb = buf + (row + i) * 2;
830
 
 
831
 
                      if (start != -length)
832
 
                        val += initial_pp * (sum[start] - sum[-length]);
833
 
 
834
 
                      while (i < end)
835
 
                        {
836
 
                          pixels = bb[0];
837
 
                          i += pixels;
838
 
                          if (i > end)
839
 
                            i = end;
840
 
                          val += bb[1] * (sum[i] - sum[start]);
841
 
                          bb += (pixels * 2);
842
 
                          start = i;
843
 
                        }
844
 
 
845
 
                      if (end != length)
846
 
                        val += initial_mm * (sum[length] - sum[end]);
847
 
 
848
 
                      dp[row * bytes + b] = val / total;
849
 
                    }
850
 
                 }
851
 
              break;
852
 
            }
853
 
 
854
 
          if (has_alpha)
855
 
            separate_alpha (src, height, bytes);
856
 
 
857
 
          if (preview)
858
 
            {
859
 
              for (row = 0 ; row < height ; row++)
860
 
                memcpy (preview_buffer1 + (row * width + col) * bytes,
861
 
                        dest + row * bytes,
862
 
                        bytes);
863
 
            }
864
 
          else
865
 
            {
866
 
              gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, height);
867
 
 
868
 
              progress += height * vert;
869
 
              if ((col % 5) == 0)
870
 
                gimp_progress_update (progress / max_progress);
871
 
            }
872
 
        }
873
 
 
874
 
      /*  prepare for the horizontal pass  */
875
 
      gimp_pixel_rgn_init (&src_rgn,
876
 
                           drawable, 0, 0, drawable->width, drawable->height,
877
 
                           FALSE, TRUE);
878
 
    }
879
 
  else if (preview)
880
 
    {
881
 
      gimp_pixel_rgn_get_rect (&src_rgn,
882
 
                               preview_buffer1, x1, y1, width, height);
883
 
    }
884
 
 
885
 
  /*  Now the horizontal pass  */
886
 
  if (horz > 0.0)
887
 
    {
888
 
      horz = fabs (horz) + 1.0;
889
 
 
890
 
      if (horz != vert)
891
 
        {
892
 
          std_dev = sqrt (-(horz * horz) / (2 * log (1.0 / 255.0)));
893
 
 
894
 
          switch (method)
895
 
            {
896
 
            case BLUR_IIR:
897
 
              /*  derive the constants for calculating the gaussian
898
 
               *  from the std dev
899
 
               */
900
 
              find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
901
 
              break;
902
 
 
903
 
            case BLUR_RLE:
904
 
              curve = make_curve (std_dev, &length);
905
 
              sum = g_new (gint, 2 * length + 1);
906
 
 
907
 
              sum[0] = 0;
908
 
 
909
 
              for (i = 1; i <= length*2; i++)
910
 
                sum[i] = curve[i-length-1] + sum[i-1];
911
 
              sum += length;
912
 
 
913
 
              total = sum[length] - sum[-length];
914
 
              break;
915
 
            }
916
 
        }
917
 
 
918
 
      for (row = 0; row < height; row++)
919
 
        {
920
 
          switch (method)
921
 
            {
922
 
            case BLUR_IIR:
923
 
              memset (val_p, 0, width * bytes * sizeof (gdouble));
924
 
              memset (val_m, 0, width * bytes * sizeof (gdouble));
925
 
              break;
926
 
 
927
 
            case BLUR_RLE:
928
 
              break;
929
 
            }
930
 
 
931
 
          if (preview)
932
 
            {
933
 
              memcpy (src,
934
 
                      preview_buffer1 + row * width * bytes,
935
 
                      width * bytes);
936
 
            }
937
 
          else
938
 
            {
939
 
              gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, width);
940
 
            }
941
 
 
942
 
          if (has_alpha)
943
 
            multiply_alpha (dest, width, bytes);
944
 
 
945
 
          switch (method)
946
 
            {
947
 
            case BLUR_IIR:
948
 
              sp_p = src;
949
 
              sp_m = src + (width - 1) * bytes;
950
 
              vp = val_p;
951
 
              vm = val_m + (width - 1) * bytes;
952
 
 
953
 
              /*  Set up the first vals  */
954
 
              for (i = 0; i < bytes; i++)
955
 
                {
956
 
                  initial_p[i] = sp_p[i];
957
 
                  initial_m[i] = sp_m[i];
958
 
                }
959
 
 
960
 
              for (col = 0; col < width; col++)
961
 
                {
962
 
                  gdouble *vpptr, *vmptr;
963
 
                  terms = (col < 4) ? col : 4;
964
 
 
965
 
                  for (b = 0; b < bytes; b++)
966
 
                    {
967
 
                      vpptr = vp + b; vmptr = vm + b;
968
 
                      for (i = 0; i <= terms; i++)
969
 
                        {
970
 
                          *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
971
 
                            d_p[i] * vp[(-i * bytes) + b];
972
 
                          *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
973
 
                            d_m[i] * vm[(i * bytes) + b];
974
 
                        }
975
 
                      for (j = i; j <= 4; j++)
976
 
                        {
977
 
                          *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
978
 
                          *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
979
 
                        }
980
 
                    }
981
 
 
982
 
                  sp_p += bytes;
983
 
                  sp_m -= bytes;
984
 
                  vp += bytes;
985
 
                  vm -= bytes;
986
 
                }
987
 
 
988
 
              transfer_pixels (val_p, val_m, dest, bytes, width);
989
 
              break;
990
 
 
991
 
            case BLUR_RLE:
992
 
              sp = src;
993
 
              dp = dest;
994
 
 
995
 
              for (b = 0; b < bytes; b++)
996
 
                {
997
 
                  initial_pp = sp[b];
998
 
                  initial_mm = sp[(width-1) * bytes + b];
999
 
 
1000
 
                  /*  Determine a run-length encoded version of the row  */
1001
 
                  run_length_encode (sp + b, buf, bytes, width);
1002
 
 
1003
 
                  for (col = 0; col < width; col++)
1004
 
                    {
1005
 
                      start = (col < length) ? -col : -length;
1006
 
                      end = (width <= (col + length)) ? (width - col - 1) : length;
1007
 
 
1008
 
                      val = 0;
1009
 
                      i = start;
1010
 
                      bb = buf + (col + i) * 2;
1011
 
 
1012
 
                      if (start != -length)
1013
 
                        val += initial_pp * (sum[start] - sum[-length]);
1014
 
 
1015
 
                      while (i < end)
1016
 
                        {
1017
 
                          pixels = bb[0];
1018
 
                          i += pixels;
1019
 
                          if (i > end)
1020
 
                            i = end;
1021
 
                          val += bb[1] * (sum[i] - sum[start]);
1022
 
                          bb += (pixels * 2);
1023
 
                          start = i;
1024
 
                        }
1025
 
 
1026
 
                      if (end != length)
1027
 
                        val += initial_mm * (sum[length] - sum[end]);
1028
 
 
1029
 
                      dp[col * bytes + b] = val / total;
1030
 
                    }
1031
 
                }
1032
 
              break;
1033
 
            }
1034
 
 
1035
 
          if (has_alpha)
1036
 
            separate_alpha (dest, width, bytes);
1037
 
 
1038
 
          if (preview)
1039
 
            {
1040
 
              memcpy (preview_buffer2 + row * width * bytes,
1041
 
                      dest,
1042
 
                      width * bytes);
1043
 
            }
1044
 
          else
1045
 
            {
1046
 
              gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, width);
1047
 
 
1048
 
              progress += width * horz;
1049
 
              if ((row % 5) == 0)
1050
 
                gimp_progress_update (progress / max_progress);
1051
 
            }
1052
 
        }
1053
 
    }
1054
 
  else if (preview)
1055
 
    {
1056
 
      memcpy (preview_buffer2, preview_buffer1, width * height * bytes);
1057
 
    }
 
1455
    gauss_rle (drawable,
 
1456
               horz, vert, method, preview_buffer, x1, y1, width, height);
1058
1457
 
1059
1458
  if (preview)
1060
1459
    {
1061
1460
      gimp_preview_draw_buffer (GIMP_PREVIEW (preview),
1062
 
                                preview_buffer2, width * bytes);
1063
 
      g_free (preview_buffer1);
1064
 
      g_free (preview_buffer2);
 
1461
                                preview_buffer, width * drawable->bpp);
 
1462
      g_free (preview_buffer);
1065
1463
    }
1066
1464
  else
1067
1465
    {
1070
1468
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
1071
1469
      gimp_drawable_update (drawable->drawable_id, x1, y1, width, height);
1072
1470
    }
1073
 
 
1074
 
  /*  free up buffers  */
1075
 
  switch (method)
1076
 
    {
1077
 
    case BLUR_IIR:
1078
 
      g_free (val_p);
1079
 
      g_free (val_m);
1080
 
      break;
1081
 
 
1082
 
    case BLUR_RLE:
1083
 
      g_free (buf);
1084
 
      break;
1085
 
    }
1086
 
 
1087
 
  g_free (src);
1088
 
  g_free (dest);
1089
1471
}
1090
1472
 
1091
1473
static void
1092
 
transfer_pixels (gdouble *src1,
1093
 
                 gdouble *src2,
1094
 
                 guchar  *dest,
1095
 
                 gint     bytes,
1096
 
                 gint     width)
 
1474
transfer_pixels (const gdouble *src1,
 
1475
                 const gdouble *src2,
 
1476
                 guchar        *dest,
 
1477
                 gint           bytes,
 
1478
                 gint           width)
1097
1479
{
1098
1480
  gint    b;
1099
1481
  gint    bend = bytes * width;
1100
1482
  gdouble sum;
1101
1483
 
1102
 
  for(b = 0; b < bend; b++)
 
1484
  for (b = 0; b < bend; b++)
1103
1485
    {
1104
1486
      sum = *src1++ + *src2++;
1105
 
      if (sum > 255) sum = 255;
1106
 
      else if(sum < 0) sum = 0;
 
1487
 
 
1488
      if (sum > 255)
 
1489
        sum = 255;
 
1490
      else if (sum < 0)
 
1491
        sum = 0;
1107
1492
 
1108
1493
      *dest++ = (guchar) sum;
1109
1494
    }
1110
1495
}
1111
1496
 
1112
1497
static void
1113
 
find_constants (gdouble n_p[],
1114
 
                gdouble n_m[],
1115
 
                gdouble d_p[],
1116
 
                gdouble d_m[],
1117
 
                gdouble bd_p[],
1118
 
                gdouble bd_m[],
1119
 
                gdouble std_dev)
 
1498
find_iir_constants (gdouble *n_p,
 
1499
                    gdouble *n_m,
 
1500
                    gdouble *d_p,
 
1501
                    gdouble *d_m,
 
1502
                    gdouble *bd_p,
 
1503
                    gdouble *bd_m,
 
1504
                    gdouble  std_dev)
1120
1505
{
1121
1506
  gint    i;
1122
 
  gdouble constants [8];
 
1507
  gdouble x0;
 
1508
  gdouble x1;
 
1509
  gdouble x2;
 
1510
  gdouble x3;
 
1511
  gdouble x4;
 
1512
  gdouble x5;
 
1513
  gdouble x6;
 
1514
  gdouble x7;
1123
1515
  gdouble div;
1124
1516
 
1125
1517
  /*  The constants used in the implemenation of a casual sequence
1127
1519
   */
1128
1520
 
1129
1521
  div = sqrt(2 * G_PI) * std_dev;
1130
 
  constants [0] = -1.783 / std_dev;
1131
 
  constants [1] = -1.723 / std_dev;
1132
 
  constants [2] = 0.6318 / std_dev;
1133
 
  constants [3] = 1.997  / std_dev;
1134
 
  constants [4] = 1.6803 / div;
1135
 
  constants [5] = 3.735 / div;
1136
 
  constants [6] = -0.6803 / div;
1137
 
  constants [7] = -0.2598 / div;
 
1522
  x0 = -1.783 / std_dev;
 
1523
  x1 = -1.723 / std_dev;
 
1524
  x2 = 0.6318 / std_dev;
 
1525
  x3 = 1.997  / std_dev;
 
1526
  x4 = 1.6803 / div;
 
1527
  x5 = 3.735 / div;
 
1528
  x6 = -0.6803 / div;
 
1529
  x7 = -0.2598 / div;
1138
1530
 
1139
 
  n_p [0] = constants[4] + constants[6];
1140
 
  n_p [1] = exp (constants[1]) *
1141
 
    (constants[7] * sin (constants[3]) -
1142
 
     (constants[6] + 2 * constants[4]) * cos (constants[3])) +
1143
 
       exp (constants[0]) *
1144
 
         (constants[5] * sin (constants[2]) -
1145
 
          (2 * constants[6] + constants[4]) * cos (constants[2]));
1146
 
  n_p [2] = 2 * exp (constants[0] + constants[1]) *
1147
 
    ((constants[4] + constants[6]) * cos (constants[3]) * cos (constants[2]) -
1148
 
     constants[5] * cos (constants[3]) * sin (constants[2]) -
1149
 
     constants[7] * cos (constants[2]) * sin (constants[3])) +
1150
 
       constants[6] * exp (2 * constants[0]) +
1151
 
         constants[4] * exp (2 * constants[1]);
1152
 
  n_p [3] = exp (constants[1] + 2 * constants[0]) *
1153
 
    (constants[7] * sin (constants[3]) - constants[6] * cos (constants[3])) +
1154
 
      exp (constants[0] + 2 * constants[1]) *
1155
 
        (constants[5] * sin (constants[2]) - constants[4] * cos (constants[2]));
 
1531
  n_p [0] = x4 + x6;
 
1532
  n_p [1] = (exp(x1)*(x7*sin(x3)-(x6+2*x4)*cos(x3)) +
 
1533
             exp(x0)*(x5*sin(x2) - (2*x6+x4)*cos (x2)));
 
1534
  n_p [2] = (2 * exp(x0+x1) *
 
1535
             ((x4+x6)*cos(x3)*cos(x2) - x5*cos(x3)*sin(x2) -
 
1536
              x7*cos(x2)*sin(x3)) +
 
1537
             x6*exp(2*x0) + x4*exp(2*x1));
 
1538
  n_p [3] = (exp(x1+2*x0) * (x7*sin(x3) - x6*cos(x3)) +
 
1539
             exp(x0+2*x1) * (x5*sin(x2) - x4*cos(x2)));
1156
1540
  n_p [4] = 0.0;
1157
1541
 
1158
1542
  d_p [0] = 0.0;
1159
 
  d_p [1] = -2 * exp (constants[1]) * cos (constants[3]) -
1160
 
    2 * exp (constants[0]) * cos (constants[2]);
1161
 
  d_p [2] = 4 * cos (constants[3]) * cos (constants[2]) * exp (constants[0] + constants[1]) +
1162
 
    exp (2 * constants[1]) + exp (2 * constants[0]);
1163
 
  d_p [3] = -2 * cos (constants[2]) * exp (constants[0] + 2 * constants[1]) -
1164
 
    2 * cos (constants[3]) * exp (constants[1] + 2 * constants[0]);
1165
 
  d_p [4] = exp (2 * constants[0] + 2 * constants[1]);
 
1543
  d_p [1] = -2 * exp(x1) * cos(x3) -  2 * exp(x0) * cos (x2);
 
1544
  d_p [2] = 4 * cos(x3) * cos(x2) * exp(x0 + x1) +  exp(2 * x1) + exp(2 * x0);
 
1545
  d_p [3] = -2 * cos(x2) * exp(x0 + 2*x1) -  2*cos(x3) * exp(x1 + 2*x0);
 
1546
  d_p [4] = exp(2*x0 + 2*x1);
1166
1547
 
1167
1548
  for (i = 0; i <= 4; i++)
1168
 
    d_m [i] = d_p [i];
 
1549
    d_m[i] = d_p[i];
1169
1550
 
1170
1551
  n_m[0] = 0.0;
 
1552
 
1171
1553
  for (i = 1; i <= 4; i++)
1172
 
    n_m [i] = n_p[i] - d_p[i] * n_p[0];
 
1554
    n_m[i] = n_p[i] - d_p[i] * n_p[0];
1173
1555
 
1174
1556
  {
1175
1557
    gdouble sum_n_p, sum_n_m, sum_d;
1178
1560
    sum_n_p = 0.0;
1179
1561
    sum_n_m = 0.0;
1180
1562
    sum_d = 0.0;
 
1563
 
1181
1564
    for (i = 0; i <= 4; i++)
1182
1565
      {
1183
1566
        sum_n_p += n_p[i];
1198
1581
 
1199
1582
 
1200
1583
/*
1201
 
 * The equations: g(r) = exp (- r^2 / (2 * sigma^2))
1202
 
 *                   r = sqrt (x^2 + y ^2)
 
1584
 * make_rle_curve(sigma, &curve, &length, &sum, &total)
 
1585
 *
 
1586
 *
 
1587
 * Fill the Gauss curve.
 
1588
 *
 
1589
 *               g(r) = exp (- r^2 / (2 * sigma^2))
 
1590
 *                  r = sqrt (x^2 + y ^2)
 
1591
 *
 
1592
 * o length is filled with the length the curve (in both directions)
 
1593
 * o curve[-length .. length] is allocated and filled with the
 
1594
 *   (scaled) gauss curve.
 
1595
 * o sum[-length .. length]   is allocated and filled with the 'summed' curve.
 
1596
 * o total is filled with the sum of all elements in the curve (for
 
1597
 *   normalization).
 
1598
 *
 
1599
 *
 
1600
 *
1203
1601
 */
1204
1602
 
1205
 
static gint *
1206
 
make_curve (gdouble  sigma,
1207
 
            gint    *length)
 
1603
 
 
1604
static void
 
1605
make_rle_curve (gdouble   sigma,
 
1606
                gint    **p_curve,
 
1607
                gint     *p_length,
 
1608
                gint    **p_sum,
 
1609
                gint     *p_total)
1208
1610
{
1209
1611
  gint    *curve;
1210
1612
  gdouble  sigma2;
1211
1613
  gdouble  l;
1212
1614
  gint     temp;
1213
1615
  gint     i, n;
 
1616
  gint     length;
 
1617
  gint    *sum;
1214
1618
 
1215
1619
  sigma2 = 2 * sigma * sigma;
1216
1620
  l = sqrt (-sigma2 * log (1.0 / 255.0));
1221
1625
 
1222
1626
  curve = g_new (gint, n);
1223
1627
 
1224
 
  *length = n / 2;
1225
 
  curve += *length;
 
1628
  length = n / 2;
 
1629
  curve += length; /* 'center' the curve[] */
1226
1630
  curve[0] = 255;
1227
1631
 
1228
 
  for (i = 1; i <= *length; i++)
 
1632
  for (i = 1; i <= length; i++)
1229
1633
    {
1230
1634
      temp = (gint) (exp (- (i * i) / sigma2) * 255);
1231
1635
      curve[-i] = temp;
1232
1636
      curve[i] = temp;
1233
1637
    }
1234
1638
 
1235
 
  return curve;
 
1639
  sum   = g_new (gint, 2 * length + 1);
 
1640
 
 
1641
  sum[0] = 0;
 
1642
  for (i = 1; i <= length*2; i++)
 
1643
    {
 
1644
      sum[i] = curve[i-length-1] + sum[i-1];
 
1645
    }
 
1646
 
 
1647
  sum += length; /* 'center' the sum[] */
 
1648
 
 
1649
  *p_total  = sum[length] - sum[-length];
 
1650
  *p_curve  = curve;
 
1651
  *p_sum    = sum;
 
1652
  *p_length = length;
 
1653
 
1236
1654
}
1237
1655
 
 
1656
/*
 
1657
 * Free a curve previously allocated with make_rle_curve
 
1658
 */
1238
1659
static void
1239
 
run_length_encode (guchar *src,
1240
 
                   gint   *dest,
1241
 
                   gint    bytes,
1242
 
                   gint    width)
 
1660
free_rle_curve (gint *curve,
 
1661
                gint  length,
 
1662
                gint *sum)
1243
1663
{
1244
 
  gint   start;
1245
 
  gint   i;
1246
 
  gint   j;
1247
 
  guchar last;
1248
 
 
1249
 
  last = *src;
1250
 
  src += bytes;
1251
 
  start = 0;
1252
 
 
1253
 
  for (i = 1; i < width; i++)
1254
 
    {
1255
 
      if (*src != last)
1256
 
        {
1257
 
          for (j = start; j < i; j++)
1258
 
            {
1259
 
              *dest++ = (i - j);
1260
 
              *dest++ = last;
1261
 
            }
1262
 
          start = i;
1263
 
          last = *src;
1264
 
        }
1265
 
      src += bytes;
1266
 
    }
1267
 
 
1268
 
  for (j = start; j < i; j++)
1269
 
    {
1270
 
      *dest++ = (i - j);
1271
 
      *dest++ = last;
1272
 
    }
 
1664
  g_free (sum - length);
 
1665
  g_free (curve - length);
1273
1666
}
1274