~ubuntu-branches/ubuntu/breezy/gimp/breezy

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2005-10-04 19:04:46 UTC
  • Revision ID: james.westby@ubuntu.com-20051004190446-ukh32kwk56s4sjhu
Tags: upstream-2.2.8
ImportĀ upstreamĀ versionĀ 2.2.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (c) Adam D. Moss : 1998-2000 : adam@gimp.org : adam@foxbox.org
 
3
 *
 
4
 * This is part of the GIMP package and is released under the GNU
 
5
 * Public License.
 
6
 */
 
7
 
 
8
/*
 
9
 * Version 1.06 : 2000-12-12
 
10
 *
 
11
 * 1.06:
 
12
 * "Out of hyding" remix.  Dr Jekyll is still suspiciously
 
13
 * absent from the fine bogey tale until Chapter Three.
 
14
 *
 
15
 * 1.05:
 
16
 * Sub-pixel jitter is now less severe and less coarse.
 
17
 *
 
18
 * 1.04:
 
19
 * Wigglyness and button-click fun.
 
20
 *
 
21
 * 1.03:
 
22
 * Fix for pseudocolor displays w/gdkrgb.
 
23
 *
 
24
 * 1.02:
 
25
 * Massive speedup if you have a very recent version of GTK 1.1.
 
26
 * Removed possible div-by-0 errors, took the plugin out
 
27
 * of hiding (guess we need a new easter-egg for GIMP 1.2!)
 
28
 */
 
29
 
 
30
#include "config.h"
 
31
 
 
32
#include <stdlib.h>
 
33
#include <string.h>
 
34
 
 
35
#include <gtk/gtk.h>
 
36
 
 
37
#include <libgimp/gimp.h>
 
38
#include <libgimp/gimpui.h>
 
39
 
 
40
#include "libgimp/stdplugins-intl.h"
 
41
 
 
42
 
 
43
/* Declare local functions. */
 
44
static void       query (void);
 
45
static void       run   (const gchar      *name,
 
46
                         gint              nparams,
 
47
                         const GimpParam  *param,
 
48
                         gint             *nreturn_vals,
 
49
                         GimpParam       **return_vals);
 
50
 
 
51
static void       do_fun                   (void);
 
52
 
 
53
static void       window_response_callback (GtkWidget      *widget,
 
54
                                            gint            response_id,
 
55
                                            gpointer        data);
 
56
static gboolean   do_iteration             (void);
 
57
static gboolean   toggle_feedbacktype      (GtkWidget      *widget,
 
58
                                            GdkEventButton *bevent);
 
59
 
 
60
static void       render_frame             (void);
 
61
static void       init_preview_misc        (void);
 
62
 
 
63
 
 
64
GimpPlugInInfo PLUG_IN_INFO =
 
65
{
 
66
  NULL,  /* init_proc  */
 
67
  NULL,  /* quit_proc  */
 
68
  query, /* query_proc */
 
69
  run,   /* run_proc   */
 
70
};
 
71
 
 
72
 
 
73
static const guint  width  = 256;
 
74
static const guint  height = 256;
 
75
static GRand       *gr;
 
76
 
 
77
 
 
78
#define LUTSIZE 512
 
79
#define LUTSIZEMASK ((LUTSIZE)-1)
 
80
static gint wigglelut[LUTSIZE];
 
81
 
 
82
#define LOWAMP 2
 
83
#define HIGHAMP 11
 
84
static gint wiggleamp = LOWAMP;
 
85
 
 
86
 
 
87
/* Global widgets'n'stuff */
 
88
static guchar     *seed_data;
 
89
static guchar     *preview_data1;
 
90
static guchar     *preview_data2;
 
91
 
 
92
static GtkWidget  *drawing_area;
 
93
 
 
94
static gint32      image_id;
 
95
static GimpDrawable      *drawable;
 
96
static GimpImageBaseType  imagetype;
 
97
static guchar     *palette;
 
98
static gint        ncolours;
 
99
 
 
100
static guint      idle_tag;
 
101
static gboolean   feedbacktype = FALSE;
 
102
static gboolean   wiggly       = TRUE;
 
103
static gboolean   rgb_mode;
 
104
 
 
105
 
 
106
MAIN ()
 
107
 
 
108
static void
 
109
query (void)
 
110
{
 
111
  static GimpParamDef args[] =
 
112
  {
 
113
    { GIMP_PDB_INT32,    "run_mode", "Must be interactive (1)" },
 
114
    { GIMP_PDB_IMAGE,    "image",    "Input Image"             },
 
115
    { GIMP_PDB_DRAWABLE, "drawable", "Input Drawable"          }
 
116
  };
 
117
 
 
118
  gimp_install_procedure ("plug_in_the_old_egg",
 
119
                          "A big hello from the GIMP team!",
 
120
                          "Hay-ulp",
 
121
                          "Adam D. Moss <adam@gimp.org>",
 
122
                          "Adam D. Moss <adam@gimp.org>",
 
123
                          "1998",
 
124
                          N_("Gee-_Zoom"),
 
125
                          "RGB*, INDEXED*, GRAY*",
 
126
                          GIMP_PLUGIN,
 
127
                          G_N_ELEMENTS (args), 0,
 
128
                          args, NULL);
 
129
 
 
130
  gimp_plugin_menu_register ("plug_in_the_old_egg", "<Image>/Filters/Toys");
 
131
}
 
132
 
 
133
static void
 
134
run (const gchar      *name,
 
135
     gint              n_params,
 
136
     const GimpParam  *param,
 
137
     gint             *nreturn_vals,
 
138
     GimpParam       **return_vals)
 
139
{
 
140
  static GimpParam  values[1];
 
141
  GimpRunMode       run_mode;
 
142
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
 
143
 
 
144
  gr = g_rand_new ();
 
145
 
 
146
  *nreturn_vals = 1;
 
147
  *return_vals = values;
 
148
 
 
149
  run_mode = param[0].data.d_int32;
 
150
 
 
151
  INIT_I18N ();
 
152
 
 
153
  if (run_mode == GIMP_RUN_NONINTERACTIVE ||
 
154
      n_params != 3)
 
155
    {
 
156
      status = GIMP_PDB_CALLING_ERROR;
 
157
    }
 
158
 
 
159
  if (status == GIMP_PDB_SUCCESS)
 
160
    {
 
161
      image_id = param[1].data.d_image;
 
162
      drawable = gimp_drawable_get (param[2].data.d_drawable);
 
163
 
 
164
      if (drawable)
 
165
        do_fun();
 
166
      else
 
167
        status = GIMP_PDB_CALLING_ERROR;
 
168
    }
 
169
 
 
170
  values[0].type = GIMP_PDB_STATUS;
 
171
  values[0].data.d_status = status;
 
172
  g_rand_free (gr);
 
173
}
 
174
 
 
175
 
 
176
static void
 
177
build_dialog (void)
 
178
{
 
179
  GtkWidget *dlg;
 
180
  GtkWidget *button;
 
181
  GtkWidget *frame;
 
182
 
 
183
  gimp_ui_init ("gee_zoom", TRUE);
 
184
 
 
185
  dlg = gimp_dialog_new (_("GEE-ZOOM"), "gee_zoom",
 
186
                         NULL, 0,
 
187
                         gimp_standard_help_func, "plug-in-the-old-egg",
 
188
                         NULL);
 
189
 
 
190
  button = gtk_dialog_add_button (GTK_DIALOG (dlg),
 
191
                                  _("Thank you for choosing GIMP"),
 
192
                                  GTK_RESPONSE_OK);
 
193
 
 
194
  g_signal_connect (dlg, "response",
 
195
                    G_CALLBACK (window_response_callback),
 
196
                    NULL);
 
197
 
 
198
  gimp_help_set_help_data (button,
 
199
                           _("An obsolete creation of Adam D. Moss / "
 
200
                             "adam@gimp.org / adam@foxbox.org / 1998-2000"),
 
201
                           NULL);
 
202
 
 
203
  /* The 'fun' half of the dialog */
 
204
 
 
205
  frame = gtk_frame_new (NULL);
 
206
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
 
207
  gtk_container_set_border_width (GTK_CONTAINER (frame), 12);
 
208
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox),
 
209
                      frame, FALSE, FALSE, 0);
 
210
  gtk_widget_show (frame);
 
211
 
 
212
  drawing_area = gtk_drawing_area_new ();
 
213
  gtk_widget_set_size_request (drawing_area, width, height);
 
214
  gtk_container_add (GTK_CONTAINER (frame), drawing_area);
 
215
  gtk_widget_show (drawing_area);
 
216
 
 
217
  gtk_widget_add_events (drawing_area,
 
218
                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
 
219
 
 
220
  g_signal_connect (drawing_area, "button_release_event",
 
221
                    G_CALLBACK (toggle_feedbacktype),
 
222
                    NULL);
 
223
 
 
224
  gtk_widget_show (dlg);
 
225
 
 
226
  idle_tag = g_idle_add_full (G_PRIORITY_LOW,
 
227
                              (GSourceFunc) do_iteration,
 
228
                              NULL,
 
229
                              NULL);
 
230
}
 
231
 
 
232
 
 
233
static void
 
234
init_lut (void)
 
235
{
 
236
  gint i;
 
237
 
 
238
  for (i=0; i<LUTSIZE; i++)
 
239
    {
 
240
      wigglelut[i] = RINT((double)(wiggleamp<<11))*(sin((double)(i) /
 
241
                                            ((double)LUTSIZEMASK /
 
242
                                             10 * G_PI)));
 
243
    }
 
244
}
 
245
 
 
246
 
 
247
static void
 
248
do_fun (void)
 
249
{
 
250
  imagetype = gimp_image_base_type(image_id);
 
251
 
 
252
  if (imagetype == GIMP_INDEXED)
 
253
    palette = gimp_image_get_colormap (image_id, &ncolours);
 
254
 
 
255
  /* cache hint */
 
256
  gimp_tile_cache_ntiles (1);
 
257
 
 
258
  init_preview_misc ();
 
259
  build_dialog ();
 
260
 
 
261
  init_lut();
 
262
 
 
263
  render_frame();
 
264
 
 
265
  gtk_main ();
 
266
}
 
267
 
 
268
 
 
269
/* Rendering Functions */
 
270
 
 
271
/* Adam's silly algorithm. */
 
272
static void
 
273
domap1 (unsigned char *src, unsigned char *dest,
 
274
        int bx, int by, int cx, int cy)
 
275
{
 
276
  unsigned int dy;
 
277
  signed int bycxmcybx;
 
278
  signed int bx2,by2;
 
279
  signed int cx2,cy2;
 
280
  unsigned int basesx;
 
281
  unsigned int basesy;
 
282
 
 
283
  static unsigned int grrr=0;
 
284
 
 
285
  grrr++;
 
286
 
 
287
  if ((cx+bx) == 0)
 
288
    cx++;
 
289
 
 
290
  if ((cy+by) == 0)
 
291
    by++;
 
292
 
 
293
  bycxmcybx = (by*cx-cy*bx);
 
294
 
 
295
  if (bycxmcybx == 0)
 
296
    bycxmcybx = 1;
 
297
 
 
298
  /* A little sub-pixel jitter to liven things up. */
 
299
  basesx = ((g_rand_int_range (gr, 0, 29<<19)/bycxmcybx)) +
 
300
    ((-128-((128*256)/(cx+bx)))<<11);
 
301
  basesy = ((g_rand_int_range (gr, 0, 29<<19)/bycxmcybx)) +
 
302
    ((-128-((128*256)/(cy+by)))<<11);
 
303
 
 
304
  bx2 = ((bx)<<19)/bycxmcybx;
 
305
  cx2 = ((cx)<<19)/bycxmcybx;
 
306
  by2 = ((by)<<19)/bycxmcybx;
 
307
  cy2 = ((cy)<<19)/bycxmcybx;
 
308
 
 
309
  for (dy=0;dy<256;dy++)
 
310
    {
 
311
      unsigned int sx;
 
312
      unsigned int sy;
 
313
      unsigned int dx;
 
314
 
 
315
      sy = (basesy+=cx2);
 
316
      sx = (basesx-=bx2);
 
317
 
 
318
      if (wiggly)
 
319
        {
 
320
          sx += wigglelut[(((basesy)>>11)+grrr) & LUTSIZEMASK];
 
321
          sy += wigglelut[(((basesx)>>11)+(grrr/3)) & LUTSIZEMASK];
 
322
        }
 
323
 
 
324
      dx = 256;
 
325
      do
 
326
        {
 
327
          *dest++ = (*(src +
 
328
                   (
 
329
                    (
 
330
                     ((255&(
 
331
                            (sx>>11)
 
332
                            )))
 
333
                     |
 
334
                     ((((255&(
 
335
                              (sy>>11)
 
336
                              ))<<8)))
 
337
                     )
 
338
                    )));
 
339
          ;
 
340
          sx += by2;
 
341
          sy -= cy2;
 
342
        }
 
343
      while (--dx);
 
344
    }
 
345
}
 
346
 
 
347
/* 3bypp variant */
 
348
static void
 
349
domap3(unsigned char *src, unsigned char *dest,
 
350
       int bx, int by, int cx, int cy)
 
351
{
 
352
  unsigned int dy;
 
353
  signed int bycxmcybx;
 
354
  signed int bx2,by2;
 
355
  signed int cx2,cy2;
 
356
  unsigned int basesx;
 
357
  unsigned int basesy;
 
358
 
 
359
  static unsigned int grrr=0;
 
360
 
 
361
  grrr++;
 
362
 
 
363
  if ((cx+bx) == 0)
 
364
    cx++;
 
365
 
 
366
  if ((cy+by) == 0)
 
367
    by++;
 
368
 
 
369
  bycxmcybx = (by*cx-cy*bx);
 
370
 
 
371
  if (bycxmcybx == 0)
 
372
    bycxmcybx = 1;
 
373
 
 
374
  /* A little sub-pixel jitter to liven things up. */
 
375
  basesx = ((g_rand_int_range (gr, 0, 29<<19)/bycxmcybx)) +
 
376
    ((-128-((128*256)/(cx+bx)))<<11);
 
377
  basesy = ((g_rand_int_range (gr, 0, 29<<19)/bycxmcybx)) +
 
378
    ((-128-((128*256)/(cy+by)))<<11);
 
379
 
 
380
  bx2 = ((bx)<<19)/bycxmcybx;
 
381
  cx2 = ((cx)<<19)/bycxmcybx;
 
382
  by2 = ((by)<<19)/bycxmcybx;
 
383
  cy2 = ((cy)<<19)/bycxmcybx;
 
384
 
 
385
  for (dy=0;dy<256;dy++)
 
386
    {
 
387
      unsigned int sx;
 
388
      unsigned int sy;
 
389
      unsigned int dx;
 
390
 
 
391
      sy = (basesy+=cx2);
 
392
      sx = (basesx-=bx2);
 
393
 
 
394
      if (wiggly)
 
395
        {
 
396
          sx += wigglelut[(((basesy)>>11)+grrr) & LUTSIZEMASK];
 
397
          sy += wigglelut[(((basesx)>>11)+(grrr/3)) & LUTSIZEMASK];
 
398
        }
 
399
 
 
400
      dx = 256;
 
401
 
 
402
      do
 
403
        {
 
404
          unsigned char* addr;
 
405
 
 
406
          addr = src + 3*
 
407
            (
 
408
             (
 
409
              ((255&(
 
410
                     (sx>>11)
 
411
                     )))
 
412
              |
 
413
              ((((255&(
 
414
                       (sy>>11)
 
415
                       ))<<8)))
 
416
              )
 
417
             );
 
418
 
 
419
          *dest++ = *(addr);
 
420
          *dest++ = *(addr+1);
 
421
          *dest++ = *(addr+2);
 
422
 
 
423
          sx += by2;
 
424
          sy -= cy2;
 
425
        }
 
426
      while (--dx);
 
427
    }
 
428
}
 
429
 
 
430
 
 
431
static void
 
432
render_frame (void)
 
433
{
 
434
  int i;
 
435
  static int frame = 0;
 
436
  unsigned char* tmp;
 
437
  static gint xp=128, yp=128;
 
438
  gint rxp, ryp;
 
439
  GdkModifierType mask;
 
440
  gint pixels;
 
441
 
 
442
  if (! GTK_WIDGET_DRAWABLE (drawing_area))
 
443
    return;
 
444
 
 
445
  pixels = width*height*(rgb_mode?3:1);
 
446
 
 
447
  tmp = preview_data2;
 
448
  preview_data2 = preview_data1;
 
449
  preview_data1 = tmp;
 
450
 
 
451
  if (frame==0)
 
452
    {
 
453
      for (i=0;i<pixels;i++)
 
454
        {
 
455
          preview_data2[i] =
 
456
            preview_data1[i] =
 
457
            seed_data[i];
 
458
        }
 
459
    }
 
460
 
 
461
  gdk_window_get_pointer (drawing_area->window, &rxp, &ryp, &mask);
 
462
 
 
463
  if ((abs(rxp)>60)||(abs(ryp)>60))
 
464
    {
 
465
      xp = rxp;
 
466
      yp = ryp;
 
467
    }
 
468
 
 
469
  if (rgb_mode)
 
470
    {
 
471
      domap3(preview_data2, preview_data1,
 
472
             -(yp-xp)/2, xp+yp
 
473
             ,
 
474
             xp+yp, (yp-xp)/2
 
475
             );
 
476
 
 
477
      gdk_draw_rgb_image (drawing_area->window,
 
478
                          drawing_area->style->white_gc,
 
479
                          0, 0, width, height,
 
480
                          GDK_RGB_DITHER_NORMAL,
 
481
                          preview_data1, width * 3);
 
482
 
 
483
      /*      memcpy(preview_data1, seed_data, 256*256*3); */
 
484
 
 
485
      if (frame != 0)
 
486
        {
 
487
          if (feedbacktype)
 
488
            {
 
489
              for (i=0;i<pixels;i++)
 
490
                {
 
491
                  gint t;
 
492
                  t = preview_data1[i] + seed_data[i] - 128;
 
493
                  preview_data1[i] = /*CLAMP(t,0,255);*/
 
494
                    (t&256)? (~(t>>10)) : t; /* Quick specialized clamp */
 
495
                }
 
496
            }
 
497
          else/* if (0) */
 
498
            {
 
499
              gint pixwords = pixels/sizeof(gint32);
 
500
              gint32* seedwords = (gint32*) seed_data;
 
501
              gint32* prevwords = (gint32*) preview_data1;
 
502
 
 
503
              for (i=0;i<pixwords;i++)
 
504
                {
 
505
                  /*preview_data1[i] = (preview_data1[i]*2 +
 
506
                    seed_data[i]) /3;*/
 
507
 
 
508
                  /* mod'd version of the below for a 'deeper' mix */
 
509
                  prevwords[i] =
 
510
                    ((prevwords[i] >> 1) & 0x7f7f7f7f) +
 
511
                    ((prevwords[i] >> 2) & 0x3f3f3f3f) +
 
512
                    ((seedwords[i] >> 2) & 0x3f3f3f3f);
 
513
                  /* This is from Raph L... it should be a fast 50%/50%
 
514
                     blend, though I don't know if 50%/50% is as nice as
 
515
                     the old ratio. */
 
516
                  /*
 
517
                    prevwords[i] =
 
518
                    ((prevwords[i] >> 1) & 0x7f7f7f7f) +
 
519
                    ((seedwords[i] >> 1) & 0x7f7f7f7f) +
 
520
                    (prevwords[i] & seedwords[i] & 0x01010101); */
 
521
                }
 
522
            }
 
523
        }
 
524
    }
 
525
  else /* GRAYSCALE */
 
526
    {
 
527
      domap1(preview_data2, preview_data1,
 
528
             -(yp-xp)/2, xp+yp
 
529
             ,
 
530
             xp+yp, (yp-xp)/2
 
531
             );
 
532
 
 
533
      gdk_draw_gray_image (drawing_area->window,
 
534
                           drawing_area->style->white_gc,
 
535
                           0, 0, width, height,
 
536
                           GDK_RGB_DITHER_NORMAL,
 
537
                           preview_data1, width);
 
538
      if (frame != 0)
 
539
        {
 
540
          if (feedbacktype)
 
541
            {
 
542
              for (i=0;i<pixels;i++)
 
543
                {
 
544
                  int t;
 
545
                  t = preview_data1[i] + seed_data[i] - 128;
 
546
                  preview_data1[i] = /*CLAMP(t,0,255);*/
 
547
                    (t&256)? (~(t>>10)) : t; /* Quick specialized clamp */
 
548
                }
 
549
            }
 
550
          else
 
551
            {
 
552
              gint pixwords = pixels/sizeof(gint32);
 
553
              gint32* seedwords = (gint32*) seed_data;
 
554
              gint32* prevwords = (gint32*) preview_data1;
 
555
 
 
556
              for (i=0;i<pixwords;i++)
 
557
                {
 
558
 
 
559
                  /* mod'd version of the below for a 'deeper' mix */
 
560
                  prevwords[i] =
 
561
                    ((prevwords[i] >> 1) & 0x7f7f7f7f) +
 
562
                    ((prevwords[i] >> 2) & 0x3f3f3f3f) +
 
563
                    ((seedwords[i] >> 2) & 0x3f3f3f3f);
 
564
                  /* This is from Raph L... it should be a fast 50%/50%
 
565
                     blend, though I don't know if 50%/50% is as nice as
 
566
                     the old ratio. */
 
567
                  /*
 
568
                    prevwords[i] =
 
569
                    ((prevwords[i] >> 1) & 0x7f7f7f7f) +
 
570
                    ((seedwords[i] >> 1) & 0x7f7f7f7f) +
 
571
                    (prevwords[i] & seedwords[i] & 0x01010101); */
 
572
                }
 
573
            }
 
574
        }
 
575
    }
 
576
 
 
577
  frame++;
 
578
}
 
579
 
 
580
static void
 
581
init_preview_misc (void)
 
582
{
 
583
  GimpPixelRgn pixel_rgn;
 
584
  gint i;
 
585
  gboolean has_alpha;
 
586
 
 
587
  if ((imagetype == GIMP_RGB) || (imagetype == GIMP_INDEXED))
 
588
    rgb_mode = TRUE;
 
589
  else
 
590
    rgb_mode = FALSE;
 
591
 
 
592
  has_alpha = gimp_drawable_has_alpha(drawable->drawable_id);
 
593
 
 
594
  seed_data = g_malloc(width*height*4);
 
595
  preview_data1 = g_malloc(width*height*(rgb_mode?3:1));
 
596
  preview_data2 = g_malloc(width*height*(rgb_mode?3:1));
 
597
 
 
598
  if ((drawable->width<256) || (drawable->height<256))
 
599
    {
 
600
      for (i=0;i<256;i++)
 
601
        {
 
602
          if (i < drawable->height)
 
603
            {
 
604
              gimp_pixel_rgn_init (&pixel_rgn,
 
605
                                   drawable,
 
606
                                   drawable->width>256?
 
607
                                   (drawable->width/2-128):0,
 
608
                                   (drawable->height>256?
 
609
                                   (drawable->height/2-128):0)+i,
 
610
                                   MIN(256,drawable->width),
 
611
                                   1,
 
612
                                   FALSE,
 
613
                                   FALSE);
 
614
              gimp_pixel_rgn_get_rect (&pixel_rgn,
 
615
                                       &seed_data[(256*i +
 
616
                                                 (
 
617
                                                  (
 
618
                                                   drawable->width<256 ?
 
619
                                                   (256-drawable->width)/2 :
 
620
                                                   0
 
621
                                                   )
 
622
                                                  +
 
623
                                                  (
 
624
                                                   drawable->height<256 ?
 
625
                                                   (256-drawable->height)/2 :
 
626
                                                   0
 
627
                                                   ) * 256
 
628
                                                  )) *
 
629
                                                 gimp_drawable_bpp
 
630
                                                 (drawable->drawable_id)
 
631
                                       ],
 
632
                                       drawable->width>256?
 
633
                                       (drawable->width/2-128):0,
 
634
                                       (drawable->height>256?
 
635
                                       (drawable->height/2-128):0)+i,
 
636
                                       MIN(256,drawable->width),
 
637
                                       1);
 
638
            }
 
639
        }
 
640
    }
 
641
  else
 
642
    {
 
643
      gimp_pixel_rgn_init (&pixel_rgn,
 
644
                           drawable,
 
645
                           drawable->width>256?(drawable->width/2-128):0,
 
646
                           drawable->height>256?(drawable->height/2-128):0,
 
647
                           MIN(256,drawable->width),
 
648
                           MIN(256,drawable->height),
 
649
                           FALSE,
 
650
                           FALSE);
 
651
      gimp_pixel_rgn_get_rect (&pixel_rgn,
 
652
                               seed_data,
 
653
                               drawable->width>256?(drawable->width/2-128):0,
 
654
                               drawable->height>256?(drawable->height/2-128):0,
 
655
                               MIN(256,drawable->width),
 
656
                               MIN(256,drawable->height));
 
657
    }
 
658
 
 
659
  gimp_drawable_detach(drawable);
 
660
 
 
661
 
 
662
  /* convert the image data of varying types into flat grey or rgb. */
 
663
  switch (imagetype)
 
664
    {
 
665
    case GIMP_INDEXED:
 
666
      if (has_alpha)
 
667
        {
 
668
          for (i=width*height;i>0;i--)
 
669
            {
 
670
              seed_data[3*(i-1)+2] =
 
671
                ((palette[3*(seed_data[(i-1)*2])+2]*seed_data[(i-1)*2+1])/255)
 
672
                + ((255-seed_data[(i-1)*2+1]) * g_rand_int_range (gr, 0, 256))/255;
 
673
              seed_data[3*(i-1)+1] =
 
674
                ((palette[3*(seed_data[(i-1)*2])+1]*seed_data[(i-1)*2+1])/255)
 
675
                + ((255-seed_data[(i-1)*2+1]) * g_rand_int_range (gr, 0, 256))/255;
 
676
              seed_data[3*(i-1)+0] =
 
677
                ((palette[3*(seed_data[(i-1)*2])+0]*seed_data[(i-1)*2+1])/255)
 
678
                + ((255-seed_data[(i-1)*2+1]) * g_rand_int_range (gr, 0, 256))/255;
 
679
            }
 
680
        }
 
681
      else
 
682
        {
 
683
          for (i=width*height;i>0;i--)
 
684
            {
 
685
              seed_data[3*(i-1)+2] = palette[3*(seed_data[i-1])+2];
 
686
              seed_data[3*(i-1)+1] = palette[3*(seed_data[i-1])+1];
 
687
              seed_data[3*(i-1)+0] = palette[3*(seed_data[i-1])+0];
 
688
            }
 
689
        }
 
690
      break;
 
691
 
 
692
    case GIMP_GRAY:
 
693
      if (has_alpha)
 
694
        {
 
695
          for (i=0;i<width*height;i++)
 
696
            {
 
697
              seed_data[i] =
 
698
                (seed_data[i*2]*seed_data[i*2+1])/255
 
699
                + ((255-seed_data[i*2+1]) * g_rand_int_range (gr, 0, 256))/255;
 
700
            }
 
701
        }
 
702
      break;
 
703
 
 
704
    case GIMP_RGB:
 
705
      if (has_alpha)
 
706
        {
 
707
          for (i=0;i<width*height;i++)
 
708
            {
 
709
              seed_data[i*3+2] =
 
710
                (seed_data[i*4+2]*seed_data[i*4+3])/255
 
711
                + ((255-seed_data[i*4+3]) * g_rand_int_range (gr, 0, 256))/255;
 
712
              seed_data[i*3+1] =
 
713
                (seed_data[i*4+1]*seed_data[i*4+3])/255
 
714
                + ((255-seed_data[i*4+3]) * g_rand_int_range (gr, 0, 256))/255;
 
715
              seed_data[i*3+0] =
 
716
                (seed_data[i*4+0]*seed_data[i*4+3])/255
 
717
                + ((255-seed_data[i*4+3]) * g_rand_int_range (gr, 0, 256))/255;
 
718
            }
 
719
        }
 
720
      break;
 
721
 
 
722
    default:
 
723
      break;
 
724
    }
 
725
}
 
726
 
 
727
 
 
728
 
 
729
/* Util. */
 
730
 
 
731
static gboolean
 
732
do_iteration (void)
 
733
{
 
734
  render_frame ();
 
735
 
 
736
  return TRUE;
 
737
}
 
738
 
 
739
 
 
740
 
 
741
/*  Callbacks  */
 
742
 
 
743
static void
 
744
window_response_callback (GtkWidget *widget,
 
745
                          gint       response_id,
 
746
                          gpointer   data)
 
747
{
 
748
  g_source_remove (idle_tag);
 
749
  idle_tag = 0;
 
750
 
 
751
  gtk_widget_destroy (widget);
 
752
}
 
753
 
 
754
static gboolean
 
755
toggle_feedbacktype (GtkWidget      *widget,
 
756
                     GdkEventButton *bevent)
 
757
{
 
758
  if (bevent->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK))
 
759
    {
 
760
      wiggleamp = bevent->x/5;
 
761
 
 
762
      wiggly = TRUE;
 
763
      init_lut();
 
764
 
 
765
      return TRUE;
 
766
    }
 
767
 
 
768
  if (bevent->state & GDK_BUTTON1_MASK)
 
769
    feedbacktype = !feedbacktype;
 
770
 
 
771
  if (bevent->state & GDK_BUTTON2_MASK)
 
772
    wiggly = !wiggly;
 
773
 
 
774
  if (bevent->state & GDK_BUTTON3_MASK)
 
775
    {
 
776
      if (wiggleamp == LOWAMP)
 
777
        wiggleamp = HIGHAMP;
 
778
      else
 
779
        wiggleamp = LOWAMP;
 
780
 
 
781
      wiggly = TRUE;
 
782
      init_lut ();
 
783
    }
 
784
 
 
785
  return TRUE;
 
786
}