~ubuntu-branches/ubuntu/hoary/gimp/hoary

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2005-04-04 14:51:23 UTC
  • Revision ID: james.westby@ubuntu.com-20050404145123-9py049eeelfymur8
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* The GIMP -- an image manipulation program
 
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
17
 */
 
18
 
 
19
/* Softglow filter for the GIMP for BIPS
 
20
 *  -Spencer Kimball
 
21
 *
 
22
 * This filter screens a desaturated, sigmoidally transferred
 
23
 *  and gaussian blurred version of the drawable over itself
 
24
 *  to create a "softglow" photographic effect.
 
25
 */
 
26
 
 
27
#include "config.h"
 
28
 
 
29
#include <string.h>
 
30
 
 
31
#include <libgimp/gimp.h>
 
32
#include <libgimp/gimpui.h>
 
33
 
 
34
#include "libgimp/stdplugins-intl.h"
 
35
 
 
36
 
 
37
/* Some useful macros */
 
38
 
 
39
#define TILE_CACHE_SIZE 48
 
40
#define SIGMOIDAL_BASE  2
 
41
#define SIGMOIDAL_RANGE 20
 
42
 
 
43
#define INT_MULT(a,b,t)  ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
 
44
 
 
45
typedef struct
 
46
{
 
47
  gdouble glow_radius;
 
48
  gdouble brightness;
 
49
  gdouble sharpness;
 
50
} SoftglowVals;
 
51
 
 
52
 
 
53
/*
 
54
 * Function prototypes.
 
55
 */
 
56
 
 
57
static void      query             (void);
 
58
static void      run               (const gchar      *name,
 
59
                                    gint              nparams,
 
60
                                    const GimpParam  *param,
 
61
                                    gint             *nreturn_vals,
 
62
                                    GimpParam       **return_vals);
 
63
 
 
64
static void      softglow          (GimpDrawable     *drawable,
 
65
                                    GimpPreview      *preview);
 
66
static gboolean  softglow_dialog   (GimpDrawable     *drawable);
 
67
 
 
68
/*
 
69
 * Gaussian blur helper functions
 
70
 */
 
71
static void      find_constants    (gdouble  n_p[],
 
72
                                    gdouble  n_m[],
 
73
                                    gdouble  d_p[],
 
74
                                    gdouble  d_m[],
 
75
                                    gdouble  bd_p[],
 
76
                                    gdouble  bd_m[],
 
77
                                    gdouble  std_dev);
 
78
static void      transfer_pixels   (gdouble *src1,
 
79
                                    gdouble *src2,
 
80
                                    guchar  *dest,
 
81
                                    gint     jump,
 
82
                                    gint     width);
 
83
 
 
84
/***** Local vars *****/
 
85
 
 
86
GimpPlugInInfo PLUG_IN_INFO =
 
87
{
 
88
  NULL,  /* init  */
 
89
  NULL,  /* quit  */
 
90
  query, /* query */
 
91
  run,   /* run   */
 
92
};
 
93
 
 
94
static SoftglowVals svals =
 
95
{
 
96
  10.0, /* glow_radius */
 
97
  0.75, /* brightness */
 
98
  0.85,  /* sharpness */
 
99
};
 
100
 
 
101
 
 
102
/***** Functions *****/
 
103
 
 
104
MAIN ()
 
105
 
 
106
static void
 
107
query (void)
 
108
{
 
109
  static GimpParamDef args[] =
 
110
  {
 
111
    { GIMP_PDB_INT32,    "run_mode",    "Interactive, non-interactive" },
 
112
    { GIMP_PDB_IMAGE,    "image",       "Input image (unused)" },
 
113
    { GIMP_PDB_DRAWABLE, "drawable",    "Input drawable" },
 
114
    { GIMP_PDB_FLOAT,    "glow_radius", "Glow radius (radius in pixels)" },
 
115
    { GIMP_PDB_FLOAT,    "brightness",  "Glow brightness (0.0 - 1.0)" },
 
116
    { GIMP_PDB_FLOAT,    "sharpness",   "Glow sharpness (0.0 - 1.0)" },
 
117
  };
 
118
 
 
119
  gchar *help_string =
 
120
    "Gives an image a softglow effect by intensifying the highlights in the "
 
121
    "image. This is done by screening a modified version of the drawable "
 
122
    "with itself. The modified version is desaturated and then a sigmoidal "
 
123
    "transfer function is applied to force the distribution of intensities "
 
124
    "into very small and very large only. This desaturated version is then "
 
125
    "blurred to give it a fuzzy 'vaseline-on-the-lens' effect. The glow "
 
126
    "radius parameter controls the sharpness of the glow effect. The "
 
127
    "brightness parameter controls the degree of intensification applied "
 
128
    "to image highlights. The sharpness parameter controls how defined or "
 
129
    "alternatively, diffuse, the glow effect should be.";
 
130
 
 
131
  gimp_install_procedure ("plug_in_softglow",
 
132
                          "Photographic 'softglow' effect by intensifying "
 
133
                          "the highlights",
 
134
                          help_string,
 
135
                          "Spencer Kimball",
 
136
                          "Bit Specialists, Inc.",
 
137
                          "2001",
 
138
                          N_("_Softglow..."),
 
139
                          "RGB*, GRAY*",
 
140
                          GIMP_PLUGIN,
 
141
                          G_N_ELEMENTS (args), 0,
 
142
                          args, NULL);
 
143
 
 
144
  gimp_plugin_menu_register ("plug_in_softglow", "<Image>/Filters/Artistic");
 
145
}
 
146
 
 
147
static void
 
148
run (const gchar      *name,
 
149
     gint              nparams,
 
150
     const GimpParam  *param,
 
151
     gint             *nreturn_vals,
 
152
     GimpParam       **return_vals)
 
153
{
 
154
  static GimpParam   values[1];
 
155
  GimpRunMode        run_mode;
 
156
  GimpDrawable      *drawable;
 
157
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
 
158
 
 
159
  run_mode = param[0].data.d_int32;
 
160
 
 
161
  /*  Get the specified drawable  */
 
162
  drawable = gimp_drawable_get (param[2].data.d_drawable);
 
163
 
 
164
  /*  set the tile cache size  */
 
165
  gimp_tile_cache_ntiles (TILE_CACHE_SIZE);
 
166
 
 
167
  *nreturn_vals = 1;
 
168
  *return_vals  = values;
 
169
 
 
170
  values[0].type          = GIMP_PDB_STATUS;
 
171
  values[0].data.d_status = status;
 
172
 
 
173
  INIT_I18N();
 
174
 
 
175
  switch (run_mode)
 
176
    {
 
177
    case GIMP_RUN_INTERACTIVE:
 
178
      /*  Possibly retrieve data  */
 
179
      gimp_get_data ("plug_in_softglow", &svals);
 
180
 
 
181
      /*  First acquire information with a dialog  */
 
182
      if (! softglow_dialog (drawable))
 
183
        return;
 
184
      break;
 
185
 
 
186
    case GIMP_RUN_NONINTERACTIVE:
 
187
      svals.glow_radius = param[3].data.d_float;
 
188
      svals.brightness  = param[4].data.d_float;
 
189
      svals.sharpness   = param[5].data.d_float;
 
190
      break;
 
191
 
 
192
    case GIMP_RUN_WITH_LAST_VALS:
 
193
      /*  Possibly retrieve data  */
 
194
      gimp_get_data ("plug_in_softglow", &svals);
 
195
      break;
 
196
 
 
197
    default:
 
198
      break;
 
199
    }
 
200
 
 
201
  if (status == GIMP_PDB_SUCCESS)
 
202
    {
 
203
      /*  Make sure that the drawable is RGB or GRAY color  */
 
204
      if (gimp_drawable_is_rgb (drawable->drawable_id) ||
 
205
          gimp_drawable_is_gray (drawable->drawable_id))
 
206
        {
 
207
          gimp_progress_init ("Softglow...");
 
208
 
 
209
          softglow (drawable, NULL);
 
210
 
 
211
          if (run_mode != GIMP_RUN_NONINTERACTIVE)
 
212
            gimp_displays_flush ();
 
213
 
 
214
          /*  Store data  */
 
215
          if (run_mode == GIMP_RUN_INTERACTIVE)
 
216
            gimp_set_data ("plug_in_softglow", &svals, sizeof (SoftglowVals));
 
217
        }
 
218
      else
 
219
        {
 
220
          g_message (_("Cannot operate on indexed color images."));
 
221
          status = GIMP_PDB_EXECUTION_ERROR;
 
222
        }
 
223
    }
 
224
 
 
225
  values[0].data.d_status = status;
 
226
 
 
227
  gimp_drawable_detach (drawable);
 
228
}
 
229
 
 
230
static void
 
231
softglow (GimpDrawable *drawable,
 
232
          GimpPreview  *preview)
 
233
{
 
234
  GimpPixelRgn  src_rgn, dest_rgn;
 
235
  GimpPixelRgn *pr;
 
236
  gint          width, height;
 
237
  gint          bytes;
 
238
  gboolean      has_alpha;
 
239
  guchar       *dest;
 
240
  guchar       *src, *sp_p, *sp_m;
 
241
  gdouble       n_p[5], n_m[5];
 
242
  gdouble       d_p[5], d_m[5];
 
243
  gdouble       bd_p[5], bd_m[5];
 
244
  gdouble      *val_p, *val_m, *vp, *vm;
 
245
  gint          x1, y1, x2, y2;
 
246
  gint          i, j;
 
247
  gint          row, col, b;
 
248
  gint          terms;
 
249
  gint          progress, max_progress;
 
250
  gint          initial_p[4];
 
251
  gint          initial_m[4];
 
252
  gint          tmp;
 
253
  gdouble       radius;
 
254
  gdouble       std_dev;
 
255
  gdouble       val;
 
256
 
 
257
  if (preview)
 
258
    {
 
259
      gimp_preview_get_position (preview, &x1, &y1);
 
260
      gimp_preview_get_size (preview, &width, &height);
 
261
      x2 = x1 + width;
 
262
      y2 = y1 + height;
 
263
    }
 
264
  else
 
265
    {
 
266
      gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
 
267
      width     = (x2 - x1);
 
268
      height    = (y2 - y1);
 
269
    }
 
270
 
 
271
  bytes     = drawable->bpp;
 
272
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
 
273
 
 
274
  val_p = g_new (gdouble, MAX (width, height));
 
275
  val_m = g_new (gdouble, MAX (width, height));
 
276
 
 
277
  dest = g_new0 (guchar, width * height);
 
278
 
 
279
  progress = 0;
 
280
  max_progress = width * height * 3;
 
281
 
 
282
  /* Initialize the pixel regions. */
 
283
  gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, width, height, FALSE, FALSE);
 
284
 
 
285
  for (pr = gimp_pixel_rgns_register (1, &src_rgn);
 
286
       pr != NULL;
 
287
       pr = gimp_pixel_rgns_process (pr))
 
288
    {
 
289
      guchar *src_ptr  = src_rgn.data;
 
290
      guchar *dest_ptr = dest + (src_rgn.y - y1) * width + (src_rgn.x - x1);
 
291
 
 
292
      for (row = 0; row < src_rgn.h; row++)
 
293
        {
 
294
          for (col = 0; col < src_rgn.w; col++)
 
295
            {
 
296
              /* desaturate */
 
297
              if (bytes > 2)
 
298
                dest_ptr[col] = (guchar) gimp_rgb_to_l_int (src_ptr[col * bytes + 0],
 
299
                                                            src_ptr[col * bytes + 1],
 
300
                                                            src_ptr[col * bytes + 2]);
 
301
              else
 
302
                dest_ptr[col] = (guchar) src_ptr[col * bytes];
 
303
 
 
304
              /* compute sigmoidal transfer */
 
305
              val = dest_ptr[col] / 255.0;
 
306
              val = 255.0 / (1 + exp (-(SIGMOIDAL_BASE + (svals.sharpness * SIGMOIDAL_RANGE)) * (val - 0.5)));
 
307
              val = val * svals.brightness;
 
308
              dest_ptr[col] = (guchar) CLAMP (val, 0, 255);
 
309
            }
 
310
 
 
311
          src_ptr  += src_rgn.rowstride;
 
312
          dest_ptr += width;
 
313
        }
 
314
 
 
315
      if (!preview)
 
316
        {
 
317
          progress += src_rgn.w * src_rgn.h;
 
318
          gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
 
319
        }
 
320
    }
 
321
 
 
322
  /*  Calculate the standard deviations  */
 
323
  radius  = fabs (svals.glow_radius) + 1.0;
 
324
  std_dev = sqrt (-(radius * radius) / (2 * log (1.0 / 255.0)));
 
325
 
 
326
  /*  derive the constants for calculating the gaussian from the std dev  */
 
327
  find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
 
328
 
 
329
  /*  First the vertical pass  */
 
330
  for (col = 0; col < width; col++)
 
331
    {
 
332
      memset (val_p, 0, height * sizeof (gdouble));
 
333
      memset (val_m, 0, height * sizeof (gdouble));
 
334
 
 
335
      src  = dest + col;
 
336
      sp_p = src;
 
337
      sp_m = src + width * (height - 1);
 
338
      vp   = val_p;
 
339
      vm   = val_m + (height - 1);
 
340
 
 
341
      /*  Set up the first vals  */
 
342
      initial_p[0] = sp_p[0];
 
343
      initial_m[0] = sp_m[0];
 
344
 
 
345
      for (row = 0; row < height; row++)
 
346
        {
 
347
          gdouble *vpptr, *vmptr;
 
348
 
 
349
          terms = (row < 4) ? row : 4;
 
350
 
 
351
          vpptr = vp; vmptr = vm;
 
352
          for (i = 0; i <= terms; i++)
 
353
            {
 
354
              *vpptr += n_p[i] * sp_p[-i * width] - d_p[i] * vp[-i];
 
355
              *vmptr += n_m[i] * sp_m[i * width] - d_m[i] * vm[i];
 
356
            }
 
357
          for (j = i; j <= 4; j++)
 
358
            {
 
359
              *vpptr += (n_p[j] - bd_p[j]) * initial_p[0];
 
360
              *vmptr += (n_m[j] - bd_m[j]) * initial_m[0];
 
361
            }
 
362
 
 
363
          sp_p += width;
 
364
          sp_m -= width;
 
365
          vp ++;
 
366
          vm --;
 
367
        }
 
368
 
 
369
      transfer_pixels (val_p, val_m, dest + col, width, height);
 
370
 
 
371
      if (!preview)
 
372
        {
 
373
          progress += height;
 
374
          if ((col % 5) == 0)
 
375
            gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
 
376
        }
 
377
    }
 
378
 
 
379
  for (row = 0; row < height; row++)
 
380
    {
 
381
      memset (val_p, 0, width * sizeof (gdouble));
 
382
      memset (val_m, 0, width * sizeof (gdouble));
 
383
 
 
384
      src = dest + row * width;
 
385
 
 
386
      sp_p = src;
 
387
      sp_m = src + width - 1;
 
388
      vp = val_p;
 
389
      vm = val_m + width - 1;
 
390
 
 
391
      /*  Set up the first vals  */
 
392
      initial_p[0] = sp_p[0];
 
393
      initial_m[0] = sp_m[0];
 
394
 
 
395
      for (col = 0; col < width; col++)
 
396
        {
 
397
          gdouble *vpptr, *vmptr;
 
398
 
 
399
          terms = (col < 4) ? col : 4;
 
400
 
 
401
          vpptr = vp; vmptr = vm;
 
402
 
 
403
          for (i = 0; i <= terms; i++)
 
404
            {
 
405
              *vpptr += n_p[i] * sp_p[-i] - d_p[i] * vp[-i];
 
406
              *vmptr += n_m[i] * sp_m[i] - d_m[i] * vm[i];
 
407
            }
 
408
 
 
409
          for (j = i; j <= 4; j++)
 
410
            {
 
411
              *vpptr += (n_p[j] - bd_p[j]) * initial_p[0];
 
412
              *vmptr += (n_m[j] - bd_m[j]) * initial_m[0];
 
413
            }
 
414
 
 
415
          sp_p ++;
 
416
          sp_m --;
 
417
          vp ++;
 
418
          vm --;
 
419
        }
 
420
 
 
421
      transfer_pixels (val_p, val_m, dest + row * width, 1, width);
 
422
 
 
423
      if (!preview)
 
424
        {
 
425
          progress += width;
 
426
          if ((row % 5) == 0)
 
427
            gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
 
428
        }
 
429
    }
 
430
 
 
431
  /* Initialize the pixel regions. */
 
432
  gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, width, height, FALSE, FALSE);
 
433
  gimp_pixel_rgn_init (&dest_rgn, drawable,
 
434
                       x1, y1, width, height, (preview == NULL), TRUE);
 
435
 
 
436
  for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn);
 
437
       pr != NULL;
 
438
       pr = gimp_pixel_rgns_process (pr))
 
439
    {
 
440
      guchar *src_ptr  = src_rgn.data;
 
441
      guchar *dest_ptr = dest_rgn.data;
 
442
      guchar *blur_ptr = dest + (src_rgn.y - y1) * width + (src_rgn.x - x1);
 
443
 
 
444
      for (row = 0; row < src_rgn.h; row++)
 
445
        {
 
446
          for (col = 0; col < src_rgn.w; col++)
 
447
            {
 
448
              /* screen op */
 
449
              for (b = 0; b < (has_alpha ? (bytes - 1) : bytes); b++)
 
450
                dest_ptr[col * bytes + b] =
 
451
                  255 - INT_MULT((255 - src_ptr[col * bytes + b]),
 
452
                                 (255 - blur_ptr[col]), tmp);
 
453
              if (has_alpha)
 
454
                dest_ptr[col * bytes + b] = src_ptr[col * bytes + b];
 
455
            }
 
456
 
 
457
          src_ptr  += src_rgn.rowstride;
 
458
          dest_ptr += dest_rgn.rowstride;
 
459
          blur_ptr += width;
 
460
        }
 
461
 
 
462
      if (preview)
 
463
        {
 
464
          gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
 
465
                                             &dest_rgn);
 
466
        }
 
467
      else
 
468
        {
 
469
          progress += src_rgn.w * src_rgn.h;
 
470
          gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
 
471
        }
 
472
    }
 
473
 
 
474
  if (! preview)
 
475
    {
 
476
      /*  merge the shadow, update the drawable  */
 
477
      gimp_drawable_flush (drawable);
 
478
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
 
479
      gimp_drawable_update (drawable->drawable_id,
 
480
                            x1, y1, (x2 - x1), (y2 - y1));
 
481
    }
 
482
 
 
483
  /*  free up buffers  */
 
484
  g_free (val_p);
 
485
  g_free (val_m);
 
486
  g_free (dest);
 
487
}
 
488
 
 
489
/*
 
490
 *  Gaussian blur helper functions
 
491
 */
 
492
 
 
493
static void
 
494
transfer_pixels (gdouble *src1,
 
495
                 gdouble *src2,
 
496
                 guchar  *dest,
 
497
                 gint     jump,
 
498
                 gint     width)
 
499
{
 
500
  gint    i;
 
501
  gdouble sum;
 
502
 
 
503
  for (i = 0; i < width; i++)
 
504
    {
 
505
      sum = src1[i] + src2[i];
 
506
 
 
507
      sum = CLAMP0255 (sum);
 
508
 
 
509
      *dest = (guchar) sum;
 
510
      dest += jump;
 
511
    }
 
512
}
 
513
 
 
514
static void
 
515
find_constants (gdouble n_p[],
 
516
                gdouble n_m[],
 
517
                gdouble d_p[],
 
518
                gdouble d_m[],
 
519
                gdouble bd_p[],
 
520
                gdouble bd_m[],
 
521
                gdouble std_dev)
 
522
{
 
523
  gint    i;
 
524
  gdouble constants [8];
 
525
  gdouble div;
 
526
 
 
527
  /*  The constants used in the implemenation of a casual sequence
 
528
   *  using a 4th order approximation of the gaussian operator
 
529
   */
 
530
 
 
531
  div = sqrt(2 * G_PI) * std_dev;
 
532
 
 
533
  constants [0] = -1.783  / std_dev;
 
534
  constants [1] = -1.723  / std_dev;
 
535
  constants [2] =  0.6318 / std_dev;
 
536
  constants [3] =  1.997  / std_dev;
 
537
  constants [4] =  1.6803 / div;
 
538
  constants [5] =  3.735  / div;
 
539
  constants [6] = -0.6803 / div;
 
540
  constants [7] = -0.2598 / div;
 
541
 
 
542
  n_p [0] = constants[4] + constants[6];
 
543
  n_p [1] = exp (constants[1]) *
 
544
    (constants[7] * sin (constants[3]) -
 
545
     (constants[6] + 2 * constants[4]) * cos (constants[3])) +
 
546
       exp (constants[0]) *
 
547
         (constants[5] * sin (constants[2]) -
 
548
          (2 * constants[6] + constants[4]) * cos (constants[2]));
 
549
  n_p [2] = 2 * exp (constants[0] + constants[1]) *
 
550
    ((constants[4] + constants[6]) * cos (constants[3]) * cos (constants[2]) -
 
551
     constants[5] * cos (constants[3]) * sin (constants[2]) -
 
552
     constants[7] * cos (constants[2]) * sin (constants[3])) +
 
553
       constants[6] * exp (2 * constants[0]) +
 
554
         constants[4] * exp (2 * constants[1]);
 
555
  n_p [3] = exp (constants[1] + 2 * constants[0]) *
 
556
    (constants[7] * sin (constants[3]) - constants[6] * cos (constants[3])) +
 
557
      exp (constants[0] + 2 * constants[1]) *
 
558
        (constants[5] * sin (constants[2]) - constants[4] * cos (constants[2]));
 
559
  n_p [4] = 0.0;
 
560
 
 
561
  d_p [0] = 0.0;
 
562
  d_p [1] = -2 * exp (constants[1]) * cos (constants[3]) -
 
563
    2 * exp (constants[0]) * cos (constants[2]);
 
564
  d_p [2] = 4 * cos (constants[3]) * cos (constants[2]) * exp (constants[0] + constants[1]) +
 
565
    exp (2 * constants[1]) + exp (2 * constants[0]);
 
566
  d_p [3] = -2 * cos (constants[2]) * exp (constants[0] + 2 * constants[1]) -
 
567
    2 * cos (constants[3]) * exp (constants[1] + 2 * constants[0]);
 
568
  d_p [4] = exp (2 * constants[0] + 2 * constants[1]);
 
569
 
 
570
#ifndef ORIGINAL_READABLE_CODE
 
571
  memcpy(d_m, d_p, 5 * sizeof(gdouble));
 
572
#else
 
573
  for (i = 0; i <= 4; i++)
 
574
    d_m [i] = d_p [i];
 
575
#endif
 
576
 
 
577
  n_m[0] = 0.0;
 
578
  for (i = 1; i <= 4; i++)
 
579
    n_m [i] = n_p[i] - d_p[i] * n_p[0];
 
580
 
 
581
  {
 
582
    gdouble sum_n_p, sum_n_m, sum_d;
 
583
    gdouble a, b;
 
584
 
 
585
    sum_n_p = 0.0;
 
586
    sum_n_m = 0.0;
 
587
    sum_d   = 0.0;
 
588
 
 
589
    for (i = 0; i <= 4; i++)
 
590
      {
 
591
        sum_n_p += n_p[i];
 
592
        sum_n_m += n_m[i];
 
593
        sum_d += d_p[i];
 
594
      }
 
595
 
 
596
#ifndef ORIGINAL_READABLE_CODE
 
597
    sum_d++;
 
598
    a = sum_n_p / sum_d;
 
599
    b = sum_n_m / sum_d;
 
600
#else
 
601
    a = sum_n_p / (1 + sum_d);
 
602
    b = sum_n_m / (1 + sum_d);
 
603
#endif
 
604
 
 
605
    for (i = 0; i <= 4; i++)
 
606
      {
 
607
        bd_p[i] = d_p[i] * a;
 
608
        bd_m[i] = d_m[i] * b;
 
609
      }
 
610
  }
 
611
}
 
612
 
 
613
/*******************************************************/
 
614
/*                    Dialog                           */
 
615
/*******************************************************/
 
616
 
 
617
static gboolean
 
618
softglow_dialog (GimpDrawable *drawable)
 
619
{
 
620
  GtkWidget *dialog;
 
621
  GtkWidget *main_vbox;
 
622
  GtkWidget *preview;
 
623
  GtkWidget *table;
 
624
  GtkObject *scale_data;
 
625
  gboolean   run;
 
626
 
 
627
  gimp_ui_init ("softglow", FALSE);
 
628
 
 
629
  dialog = gimp_dialog_new (_("Softglow"), "softglow",
 
630
                            NULL, 0,
 
631
                            gimp_standard_help_func, "plug-in-softglow",
 
632
 
 
633
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
634
                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
 
635
 
 
636
                            NULL);
 
637
 
 
638
  main_vbox = gtk_vbox_new (FALSE, 12);
 
639
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
 
640
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
 
641
  gtk_widget_show (main_vbox);
 
642
 
 
643
  preview = gimp_drawable_preview_new (drawable, NULL);
 
644
  gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0);
 
645
  gtk_widget_show (preview);
 
646
 
 
647
  g_signal_connect_swapped (preview, "invalidated",
 
648
                            G_CALLBACK (softglow),
 
649
                            drawable);
 
650
 
 
651
  table = gtk_table_new (3, 3, FALSE);
 
652
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
 
653
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
 
654
  gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
 
655
  gtk_widget_show (table);
 
656
 
 
657
  /*  Label, scale, entry for svals.amount  */
 
658
  scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
 
659
                                     _("_Glow radius:"), 100, 5,
 
660
                                     svals.glow_radius, 1.0, 50.0, 1, 5.0, 2,
 
661
                                     TRUE, 0, 0,
 
662
                                     NULL, NULL);
 
663
 
 
664
  g_signal_connect (scale_data, "value_changed",
 
665
                    G_CALLBACK (gimp_double_adjustment_update),
 
666
                    &svals.glow_radius);
 
667
  g_signal_connect_swapped (scale_data, "value_changed",
 
668
                            G_CALLBACK (gimp_preview_invalidate),
 
669
                            preview);
 
670
 
 
671
  /*  Label, scale, entry for svals.amount  */
 
672
  scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
 
673
                                     _("_Brightness:"), 100, 5,
 
674
                                     svals.brightness, 0.0, 1.0, 0.01, 0.1, 2,
 
675
                                     TRUE, 0, 0,
 
676
                                     NULL, NULL);
 
677
 
 
678
  g_signal_connect (scale_data, "value_changed",
 
679
                    G_CALLBACK (gimp_double_adjustment_update),
 
680
                    &svals.brightness);
 
681
  g_signal_connect_swapped (scale_data, "value_changed",
 
682
                            G_CALLBACK (gimp_preview_invalidate),
 
683
                            preview);
 
684
 
 
685
  /*  Label, scale, entry for svals.amount  */
 
686
  scale_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
 
687
                                     _("_Sharpness:"), 100, 5,
 
688
                                     svals.sharpness, 0.0, 1.0, 0.01, 0.1, 2,
 
689
                                     TRUE, 0, 0,
 
690
                                     NULL, NULL);
 
691
 
 
692
  g_signal_connect (scale_data, "value_changed",
 
693
                    G_CALLBACK (gimp_double_adjustment_update),
 
694
                    &svals.sharpness);
 
695
  g_signal_connect_swapped (scale_data, "value_changed",
 
696
                            G_CALLBACK (gimp_preview_invalidate),
 
697
                            preview);
 
698
 
 
699
  gtk_widget_show (dialog);
 
700
 
 
701
  run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
 
702
 
 
703
  gtk_widget_destroy (dialog);
 
704
 
 
705
  return run;
 
706
}