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

« back to all changes in this revision

Viewing changes to plug-ins/common/noise-hsv.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2008-10-06 13:30:41 UTC
  • mto: This revision was merged to the branch mainline in revision 35.
  • Revision ID: james.westby@ubuntu.com-20081006133041-3panbkcanaymfsmp
Tags: upstream-2.6.0
ImportĀ upstreamĀ versionĀ 2.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* scatter_hsv.c -- This is a plug-in for GIMP (1.0's API)
 
2
 * Author: Shuji Narazaki <narazaki@InetQ.or.jp>
 
3
 * Time-stamp: <2000-01-08 02:49:39 yasuhiro>
 
4
 * Version: 0.42
 
5
 *
 
6
 * Copyright (C) 1997 Shuji Narazaki <narazaki@InetQ.or.jp>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <stdlib.h>
 
26
 
 
27
#include <libgimp/gimp.h>
 
28
#include <libgimp/gimpui.h>
 
29
 
 
30
#include "libgimp/stdplugins-intl.h"
 
31
 
 
32
 
 
33
#define HSV_NOISE_PROC   "plug-in-hsv-noise"
 
34
#define SCATTER_HSV_PROC "plug-in-scatter-hsv"
 
35
#define PLUG_IN_BINARY   "noise-hsv"
 
36
#define SCALE_WIDTH      100
 
37
#define ENTRY_WIDTH        3
 
38
 
 
39
 
 
40
static void     query               (void);
 
41
static void     run                 (const gchar      *name,
 
42
                                     gint              nparams,
 
43
                                     const GimpParam  *param,
 
44
                                     gint             *nreturn_vals,
 
45
                                     GimpParam       **return_vals);
 
46
 
 
47
static void     scatter_hsv         (GimpDrawable     *drawable);
 
48
static gboolean scatter_hsv_dialog  (GimpDrawable     *drawable);
 
49
static void     scatter_hsv_preview (GimpPreview      *preview);
 
50
 
 
51
static void     scatter_hsv_scatter (guchar           *r,
 
52
                                     guchar           *g,
 
53
                                     guchar           *b);
 
54
 
 
55
static gint     randomize_value     (gint              now,
 
56
                                     gint              min,
 
57
                                     gint              max,
 
58
                                     gboolean          wraps_around,
 
59
                                     gint              rand_max);
 
60
 
 
61
 
 
62
const GimpPlugInInfo PLUG_IN_INFO =
 
63
{
 
64
  NULL,  /* init_proc  */
 
65
  NULL,  /* quit_proc  */
 
66
  query, /* query_proc */
 
67
  run,   /* run_proc   */
 
68
};
 
69
 
 
70
typedef struct
 
71
{
 
72
  gint     holdness;
 
73
  gint     hue_distance;
 
74
  gint     saturation_distance;
 
75
  gint     value_distance;
 
76
} ValueType;
 
77
 
 
78
static ValueType VALS =
 
79
{
 
80
  2,
 
81
  3,
 
82
  10,
 
83
  10
 
84
};
 
85
 
 
86
MAIN ()
 
87
 
 
88
static void
 
89
query (void)
 
90
{
 
91
  static const GimpParamDef args [] =
 
92
  {
 
93
    { GIMP_PDB_INT32,    "run-mode",            "Interactive, non-interactive" },
 
94
    { GIMP_PDB_IMAGE,    "image",               "Input image (not used)" },
 
95
    { GIMP_PDB_DRAWABLE, "drawable",            "Input drawable" },
 
96
    { GIMP_PDB_INT32,    "holdness",            "convolution strength" },
 
97
    { GIMP_PDB_INT32,    "hue-distance",        "scattering of hue angle [0,180]" },
 
98
    { GIMP_PDB_INT32,    "saturation-distance", "distribution distance on saturation axis [0,255]" },
 
99
    { GIMP_PDB_INT32,    "value-distance",      "distribution distance on value axis [0,255]" }
 
100
  };
 
101
 
 
102
  gimp_install_procedure (HSV_NOISE_PROC,
 
103
                          N_("Randomize hue/saturation/value independently"),
 
104
                          "Scattering pixel values in HSV space",
 
105
                          "Shuji Narazaki (narazaki@InetQ.or.jp)",
 
106
                          "Shuji Narazaki",
 
107
                          "1997",
 
108
                          N_("HSV Noise..."),
 
109
                          "RGB*",
 
110
                          GIMP_PLUGIN,
 
111
                          G_N_ELEMENTS (args), 0,
 
112
                          args, NULL);
 
113
 
 
114
  gimp_plugin_menu_register (HSV_NOISE_PROC, "<Image>/Filters/Noise");
 
115
 
 
116
  gimp_install_procedure (SCATTER_HSV_PROC,
 
117
                          "Scattering pixel values in HSV space",
 
118
                          "Scattering pixel values in HSV space",
 
119
                          "Shuji Narazaki (narazaki@InetQ.or.jp)",
 
120
                          "Shuji Narazaki",
 
121
                          "1997",
 
122
                          NULL,
 
123
                          "RGB*",
 
124
                          GIMP_PLUGIN,
 
125
                          G_N_ELEMENTS (args), 0,
 
126
                          args, NULL);
 
127
}
 
128
 
 
129
static void
 
130
run (const gchar      *name,
 
131
     gint              nparams,
 
132
     const GimpParam  *param,
 
133
     gint             *nreturn_vals,
 
134
     GimpParam       **return_vals)
 
135
{
 
136
  static GimpParam   values[1];
 
137
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
 
138
  GimpRunMode        run_mode;
 
139
  GimpDrawable      *drawable;
 
140
 
 
141
  INIT_I18N ();
 
142
 
 
143
  run_mode = param[0].data.d_int32;
 
144
  drawable = gimp_drawable_get (param[2].data.d_int32);
 
145
 
 
146
  *nreturn_vals = 1;
 
147
  *return_vals  = values;
 
148
 
 
149
  values[0].type          = GIMP_PDB_STATUS;
 
150
  values[0].data.d_status = status;
 
151
 
 
152
  switch (run_mode)
 
153
    {
 
154
    case GIMP_RUN_INTERACTIVE:
 
155
      gimp_get_data (HSV_NOISE_PROC, &VALS);
 
156
      if (!gimp_drawable_is_rgb (drawable->drawable_id))
 
157
        {
 
158
          g_message (_("Can only operate on RGB drawables."));
 
159
          return;
 
160
        }
 
161
      if (! scatter_hsv_dialog (drawable))
 
162
        return;
 
163
      break;
 
164
 
 
165
    case GIMP_RUN_NONINTERACTIVE:
 
166
      VALS.holdness            = CLAMP (param[3].data.d_int32, 1, 8);
 
167
      VALS.hue_distance        = CLAMP (param[4].data.d_int32, 0, 180);
 
168
      VALS.saturation_distance = CLAMP (param[5].data.d_int32, 0, 255);
 
169
      VALS.value_distance      = CLAMP (param[6].data.d_int32, 0, 255);
 
170
      break;
 
171
 
 
172
    case GIMP_RUN_WITH_LAST_VALS:
 
173
      gimp_get_data (HSV_NOISE_PROC, &VALS);
 
174
      break;
 
175
    }
 
176
 
 
177
  scatter_hsv (drawable);
 
178
 
 
179
  if (run_mode != GIMP_RUN_NONINTERACTIVE)
 
180
    gimp_displays_flush();
 
181
  if (run_mode == GIMP_RUN_INTERACTIVE && status == GIMP_PDB_SUCCESS )
 
182
    gimp_set_data (HSV_NOISE_PROC, &VALS, sizeof (ValueType));
 
183
 
 
184
  values[0].type = GIMP_PDB_STATUS;
 
185
  values[0].data.d_status = status;
 
186
}
 
187
 
 
188
static void
 
189
scatter_hsv_func (const guchar *src,
 
190
                  guchar       *dest,
 
191
                  gint          bpp,
 
192
                  gpointer      data)
 
193
{
 
194
  guchar h, s, v;
 
195
 
 
196
  h = src[0];
 
197
  s = src[1];
 
198
  v = src[2];
 
199
 
 
200
  scatter_hsv_scatter (&h, &s, &v);
 
201
 
 
202
  dest[0] = h;
 
203
  dest[1] = s;
 
204
  dest[2] = v;
 
205
 
 
206
  if (bpp == 4)
 
207
    dest[3] = src[3];
 
208
}
 
209
 
 
210
static void
 
211
scatter_hsv (GimpDrawable *drawable)
 
212
{
 
213
  gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));
 
214
 
 
215
  gimp_progress_init (_("HSV Noise"));
 
216
 
 
217
  gimp_rgn_iterate2 (drawable, 0 /* unused */, scatter_hsv_func, NULL);
 
218
 
 
219
  gimp_drawable_detach (drawable);
 
220
}
 
221
 
 
222
static gint
 
223
randomize_value (gint     now,
 
224
                 gint     min,
 
225
                 gint     max,
 
226
                 gboolean wraps_around,
 
227
                 gint     rand_max)
 
228
{
 
229
  gint    flag, new, steps, index;
 
230
  gdouble rand_val;
 
231
 
 
232
  steps = max - min + 1;
 
233
  rand_val = g_random_double ();
 
234
  for (index = 1; index < VALS.holdness; index++)
 
235
    {
 
236
      double tmp = g_random_double ();
 
237
      if (tmp < rand_val)
 
238
        rand_val = tmp;
 
239
    }
 
240
 
 
241
  if (g_random_double () < 0.5)
 
242
    flag = -1;
 
243
  else
 
244
    flag = 1;
 
245
 
 
246
  new = now + flag * ((int) (rand_max * rand_val) % steps);
 
247
 
 
248
  if (new < min)
 
249
    {
 
250
      if (wraps_around)
 
251
        new += steps;
 
252
      else
 
253
        new = min;
 
254
    }
 
255
  if (max < new)
 
256
    {
 
257
      if (wraps_around)
 
258
        new -= steps;
 
259
      else
 
260
        new = max;
 
261
    }
 
262
  return new;
 
263
}
 
264
 
 
265
static void
 
266
scatter_hsv_scatter (guchar *r,
 
267
                     guchar *g,
 
268
                     guchar *b)
 
269
{
 
270
  gint h, s, v;
 
271
  gint h1, s1, v1;
 
272
  gint h2, s2, v2;
 
273
 
 
274
  h = *r; s = *g; v = *b;
 
275
 
 
276
  gimp_rgb_to_hsv_int (&h, &s, &v);
 
277
 
 
278
  /* there is no need for scattering hue of desaturated pixels here */
 
279
  if ((VALS.hue_distance > 0) && (s > 0))
 
280
    h = randomize_value (h, 0, 359, TRUE,  VALS.hue_distance);
 
281
 
 
282
  /* desaturated pixels get random hue before increasing saturation */
 
283
  if (VALS.saturation_distance > 0) {
 
284
    if (s == 0)
 
285
      h = g_random_int_range (0, 360);
 
286
    s = randomize_value (s, 0, 255, FALSE, VALS.saturation_distance);
 
287
  }
 
288
 
 
289
  if (VALS.value_distance > 0)
 
290
    v = randomize_value (v, 0, 255, FALSE, VALS.value_distance);
 
291
 
 
292
  h1 = h; s1 = s; v1 = v;
 
293
 
 
294
  gimp_hsv_to_rgb_int (&h, &s, &v); /* don't believe ! */
 
295
 
 
296
  h2 = h; s2 = s; v2 = v;
 
297
 
 
298
  gimp_rgb_to_hsv_int (&h2, &s2, &v2); /* h2 should be h1. But... */
 
299
 
 
300
  if ((abs (h1 - h2) <= VALS.hue_distance)        &&
 
301
      (abs (s1 - s2) <= VALS.saturation_distance) &&
 
302
      (abs (v1 - v2) <= VALS.value_distance))
 
303
    {
 
304
      *r = h;
 
305
      *g = s;
 
306
      *b = v;
 
307
    }
 
308
}
 
309
 
 
310
static void
 
311
scatter_hsv_preview (GimpPreview *preview)
 
312
{
 
313
  GimpDrawable *drawable;
 
314
  GimpPixelRgn  src_rgn;
 
315
  guchar       *src, *dst;
 
316
  gint          i;
 
317
  gint          x1, y1;
 
318
  gint          width, height;
 
319
  gint          bpp;
 
320
 
 
321
  drawable =
 
322
    gimp_drawable_preview_get_drawable (GIMP_DRAWABLE_PREVIEW (preview));
 
323
 
 
324
  gimp_preview_get_position (preview, &x1, &y1);
 
325
  gimp_preview_get_size (preview, &width, &height);
 
326
 
 
327
  bpp = drawable->bpp;
 
328
 
 
329
  src = g_new (guchar, width * height * bpp);
 
330
  dst = g_new (guchar, width * height * bpp);
 
331
 
 
332
  gimp_pixel_rgn_init (&src_rgn, drawable,
 
333
                       x1, y1, width, height,
 
334
                       FALSE, FALSE);
 
335
  gimp_pixel_rgn_get_rect (&src_rgn, src, x1, y1, width, height);
 
336
 
 
337
  for (i = 0; i < width * height; i++)
 
338
    scatter_hsv_func (src + i * bpp, dst + i * bpp, bpp, NULL);
 
339
 
 
340
  gimp_preview_draw_buffer (preview, dst, width * bpp);
 
341
 
 
342
  g_free (src);
 
343
  g_free (dst);
 
344
}
 
345
 
 
346
 
 
347
/* dialog stuff */
 
348
 
 
349
static gboolean
 
350
scatter_hsv_dialog (GimpDrawable *drawable)
 
351
{
 
352
  GtkWidget *dialog;
 
353
  GtkWidget *main_vbox;
 
354
  GtkWidget *preview;
 
355
  GtkWidget *table;
 
356
  GtkObject *adj;
 
357
  gboolean   run;
 
358
 
 
359
  gimp_ui_init (PLUG_IN_BINARY, TRUE);
 
360
 
 
361
  dialog = gimp_dialog_new (_("HSV Noise"), PLUG_IN_BINARY,
 
362
                            NULL, 0,
 
363
                            gimp_standard_help_func, HSV_NOISE_PROC,
 
364
 
 
365
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
366
                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
 
367
 
 
368
                            NULL);
 
369
 
 
370
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
 
371
                                           GTK_RESPONSE_OK,
 
372
                                           GTK_RESPONSE_CANCEL,
 
373
                                           -1);
 
374
 
 
375
  gimp_window_set_transient (GTK_WINDOW (dialog));
 
376
 
 
377
  main_vbox = gtk_vbox_new (FALSE, 12);
 
378
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
 
379
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
 
380
  gtk_widget_show (main_vbox);
 
381
 
 
382
  preview = gimp_drawable_preview_new (drawable, NULL);
 
383
  gtk_box_pack_start (GTK_BOX (main_vbox), preview, TRUE, TRUE, 0);
 
384
  gtk_widget_show (preview);
 
385
 
 
386
  g_signal_connect (preview, "invalidated",
 
387
                    G_CALLBACK (scatter_hsv_preview),
 
388
                    NULL);
 
389
 
 
390
  table = gtk_table_new (4, 3, FALSE);
 
391
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
 
392
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
 
393
  gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
 
394
  gtk_widget_show (table);
 
395
 
 
396
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
 
397
                              _("_Holdness:"), SCALE_WIDTH, ENTRY_WIDTH,
 
398
                              VALS.holdness, 1, 8, 1, 2, 0,
 
399
                              TRUE, 0, 0,
 
400
                              NULL, NULL);
 
401
  g_signal_connect (adj, "value-changed",
 
402
                    G_CALLBACK (gimp_int_adjustment_update),
 
403
                    &VALS.holdness);
 
404
  g_signal_connect_swapped (adj, "value-changed",
 
405
                            G_CALLBACK (gimp_preview_invalidate),
 
406
                            preview);
 
407
 
 
408
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
 
409
                              _("H_ue:"), SCALE_WIDTH, ENTRY_WIDTH,
 
410
                              VALS.hue_distance, 0, 180, 1, 6, 0,
 
411
                              TRUE, 0, 0,
 
412
                              NULL, NULL);
 
413
  g_signal_connect (adj, "value-changed",
 
414
                    G_CALLBACK (gimp_int_adjustment_update),
 
415
                    &VALS.hue_distance);
 
416
  g_signal_connect_swapped (adj, "value-changed",
 
417
                            G_CALLBACK (gimp_preview_invalidate),
 
418
                            preview);
 
419
 
 
420
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
 
421
                              _("_Saturation:"), SCALE_WIDTH, ENTRY_WIDTH,
 
422
                              VALS.saturation_distance, 0, 255, 1, 8, 0,
 
423
                              TRUE, 0, 0,
 
424
                              NULL, NULL);
 
425
  g_signal_connect (adj, "value-changed",
 
426
                    G_CALLBACK (gimp_int_adjustment_update),
 
427
                    &VALS.saturation_distance);
 
428
  g_signal_connect_swapped (adj, "value-changed",
 
429
                            G_CALLBACK (gimp_preview_invalidate),
 
430
                            preview);
 
431
 
 
432
  adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 3,
 
433
                              _("_Value:"), SCALE_WIDTH, ENTRY_WIDTH,
 
434
                              VALS.value_distance, 0, 255, 1, 8, 0,
 
435
                              TRUE, 0, 0,
 
436
                              NULL, NULL);
 
437
  g_signal_connect (adj, "value-changed",
 
438
                    G_CALLBACK (gimp_int_adjustment_update),
 
439
                    &VALS.value_distance);
 
440
  g_signal_connect_swapped (adj, "value-changed",
 
441
                            G_CALLBACK (gimp_preview_invalidate),
 
442
                            preview);
 
443
 
 
444
  gtk_widget_show (dialog);
 
445
 
 
446
  run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
 
447
 
 
448
  gtk_widget_destroy (dialog);
 
449
 
 
450
  return run;
 
451
}