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

« back to all changes in this revision

Viewing changes to plug-ins/common/gee.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
/*
 
2
 * (c) Adam D. Moss : 1998-2000 : adam@gimp.org : adam@foxbox.org
 
3
 *
 
4
 * Enjoy.
 
5
 */
 
6
 
 
7
/*
 
8
 * Version 1.01 : 2000-12-12
 
9
 *
 
10
 */
 
11
#include "config.h"
 
12
 
 
13
#include <string.h>
 
14
 
 
15
#include <gtk/gtk.h>
 
16
 
 
17
#include <libgimp/gimp.h>
 
18
#include <libgimp/gimpui.h>
 
19
 
 
20
#include "libgimp/stdplugins-intl.h"
 
21
 
 
22
 
 
23
/* Declare local functions. */
 
24
static void       query (void);
 
25
static void       run   (const gchar      *name,
 
26
                         gint              nparams,
 
27
                         const GimpParam  *param,
 
28
                         gint             *nreturn_vals,
 
29
                         GimpParam       **return_vals);
 
30
 
 
31
static void       do_fun                   (void);
 
32
 
 
33
static void       window_response_callback (GtkWidget *widget,
 
34
                                            gint       response_id,
 
35
                                            gpointer   data);
 
36
static gboolean   do_iteration             (void);
 
37
 
 
38
static void       render_frame             (void);
 
39
static void       init_preview_misc        (void);
 
40
 
 
41
 
 
42
GimpPlugInInfo PLUG_IN_INFO =
 
43
{
 
44
  NULL,  /* init_proc  */
 
45
  NULL,  /* quit_proc  */
 
46
  query, /* query_proc */
 
47
  run,   /* run_proc   */
 
48
};
 
49
 
 
50
 
 
51
/* These aren't really redefinable, easily. */
 
52
#define IWIDTH  256
 
53
#define IHEIGHT 256
 
54
 
 
55
 
 
56
/* Global widgets'n'stuff */
 
57
static guchar     *disp;      /* RGBX preview data      */
 
58
static guchar     *env;       /* src warping image data */
 
59
static guchar     *bump1base;
 
60
static guchar     *bump1;
 
61
static guchar     *bump2base;
 
62
static guchar     *bump2;
 
63
static guchar     *srcbump;
 
64
static guchar     *destbump;
 
65
 
 
66
static guint       idle_tag;
 
67
static GtkWidget  *drawing_area;
 
68
 
 
69
static gint32      image_id;
 
70
static GimpDrawable      *drawable;
 
71
static GimpImageBaseType  imagetype;
 
72
static guchar     *palette;
 
73
static gint        ncolours;
 
74
 
 
75
 
 
76
MAIN ()
 
77
 
 
78
static void
 
79
query (void)
 
80
{
 
81
  static GimpParamDef args[] =
 
82
  {
 
83
    { GIMP_PDB_INT32,    "run_mode", "Must be interactive (1)" },
 
84
    { GIMP_PDB_IMAGE,    "image",    "Input Image"             },
 
85
    { GIMP_PDB_DRAWABLE, "drawable", "Input Drawable"          }
 
86
  };
 
87
 
 
88
  gimp_install_procedure ("plug_in_the_slimy_egg",
 
89
                          "A big hello from the GIMP team!",
 
90
                          "Beyond help.",
 
91
                          "Adam D. Moss <adam@gimp.org>",
 
92
                          "Adam D. Moss <adam@gimp.org>",
 
93
                          "2000",
 
94
                          N_("Gee-_Slime"),
 
95
                          "RGB*, INDEXED*, GRAY*",
 
96
                          GIMP_PLUGIN,
 
97
                          G_N_ELEMENTS (args), 0,
 
98
                          args, NULL);
 
99
 
 
100
  gimp_plugin_menu_register ("plug_in_the_slimy_egg", "<Image>/Filters/Toys");
 
101
}
 
102
 
 
103
static void
 
104
run (const gchar      *name,
 
105
     gint              n_params,
 
106
     const GimpParam  *param,
 
107
     gint             *nreturn_vals,
 
108
     GimpParam       **return_vals)
 
109
{
 
110
  static GimpParam  values[1];
 
111
  GimpRunMode       run_mode;
 
112
  GimpPDBStatusType status = GIMP_PDB_SUCCESS;
 
113
 
 
114
  *nreturn_vals = 1;
 
115
  *return_vals = values;
 
116
 
 
117
  run_mode = param[0].data.d_int32;
 
118
 
 
119
  INIT_I18N ();
 
120
 
 
121
  if (run_mode == GIMP_RUN_NONINTERACTIVE ||
 
122
      n_params != 3)
 
123
    {
 
124
      status = GIMP_PDB_CALLING_ERROR;
 
125
    }
 
126
 
 
127
  if (status == GIMP_PDB_SUCCESS)
 
128
    {
 
129
      image_id = param[1].data.d_image;
 
130
      drawable = gimp_drawable_get (param[2].data.d_drawable);
 
131
 
 
132
      if (drawable)
 
133
        do_fun ();
 
134
      else
 
135
        status = GIMP_PDB_CALLING_ERROR;
 
136
    }
 
137
 
 
138
  values[0].type = GIMP_PDB_STATUS;
 
139
  values[0].data.d_status = status;
 
140
}
 
141
 
 
142
 
 
143
static void
 
144
build_dialog (void)
 
145
{
 
146
  GtkWidget *dlg;
 
147
  GtkWidget *button;
 
148
  GtkWidget *frame;
 
149
 
 
150
  gimp_ui_init ("gee", TRUE);
 
151
 
 
152
  dlg = gimp_dialog_new (_("GEE-SLIME"), "gee",
 
153
                         NULL, 0,
 
154
                         gimp_standard_help_func, "plug-in-the-slimy-egg",
 
155
                         NULL);
 
156
 
 
157
  button = gtk_dialog_add_button (GTK_DIALOG (dlg),
 
158
                                  _("Thank you for choosing GIMP"),
 
159
                                  GTK_RESPONSE_OK);
 
160
 
 
161
  g_signal_connect (dlg, "response",
 
162
                    G_CALLBACK (window_response_callback),
 
163
                    NULL);
 
164
 
 
165
  gimp_help_set_help_data (button,
 
166
                           _("A less-obsolete creation of Adam D. Moss / "
 
167
                             "adam@gimp.org / adam@foxbox.org / 1998-2000"),
 
168
                           NULL);
 
169
 
 
170
  frame = gtk_frame_new (NULL);
 
171
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
 
172
  gtk_container_set_border_width (GTK_CONTAINER (frame), 12);
 
173
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox),
 
174
                      frame, FALSE, FALSE, 0);
 
175
  gtk_widget_show (frame);
 
176
 
 
177
  drawing_area = gtk_drawing_area_new ();
 
178
  gtk_widget_set_size_request (drawing_area, IWIDTH, IHEIGHT);
 
179
  gtk_container_add (GTK_CONTAINER (frame), drawing_area);
 
180
  gtk_widget_show (drawing_area);
 
181
 
 
182
  gtk_widget_show (dlg);
 
183
 
 
184
  idle_tag = g_idle_add_full (G_PRIORITY_LOW,
 
185
                              (GSourceFunc) do_iteration,
 
186
                              NULL,
 
187
                              NULL);
 
188
}
 
189
 
 
190
 
 
191
/* #define LIGHT 0x19
 
192
#define LIGHT 0x1a
 
193
#define LIGHT 0x21 */
 
194
#define LIGHT 0x0d
 
195
static guchar llut[256];
 
196
 
 
197
static void
 
198
gen_llut (void)
 
199
{
 
200
  int i,k;
 
201
 
 
202
  for (i=0; i<256; i++)
 
203
    {
 
204
      /* k = i + RINT (((double)LIGHT) * pow(((double)i / 255.0), 0.5));
 
205
         k = i + ((LIGHT*i)/255); */
 
206
      k = i + ((LIGHT*( /* (255*255)- */ i*i))/(255*255));
 
207
#if 0
 
208
      k = i + ((LIGHT*( /* (255*255*255)- */ i*i*i))/(255*255*255));
 
209
#endif
 
210
      k = k + 8;
 
211
      k = (k>255 ? 255 : k);
 
212
      llut[i] = k;
 
213
    }
 
214
}
 
215
 
 
216
 
 
217
static void
 
218
do_fun (void)
 
219
{
 
220
  imagetype = gimp_image_base_type(image_id);
 
221
 
 
222
  if (imagetype == GIMP_INDEXED)
 
223
    palette = gimp_image_get_colormap (image_id, &ncolours);
 
224
  else
 
225
    if (imagetype == GIMP_GRAY)
 
226
      {
 
227
        int i;
 
228
        palette = g_malloc(256 * 3);
 
229
        for (i=0; i<256; i++)
 
230
          {
 
231
            palette[i*3+0] =
 
232
              palette[i*3+1] =
 
233
              palette[i*3+2] = i;
 
234
          }
 
235
      }
 
236
 
 
237
  /* cache hint */
 
238
  gimp_tile_cache_ntiles (1);
 
239
 
 
240
  init_preview_misc();
 
241
  build_dialog ();
 
242
 
 
243
  gen_llut();
 
244
 
 
245
  render_frame();
 
246
 
 
247
  gtk_main ();
 
248
}
 
249
 
 
250
 
 
251
static void
 
252
show (void)
 
253
{
 
254
  if (GTK_WIDGET_DRAWABLE (drawing_area))
 
255
    gdk_draw_rgb_32_image (drawing_area->window,
 
256
                           drawing_area->style->white_gc,
 
257
                           0, 0, IWIDTH, IHEIGHT,
 
258
                           GDK_RGB_DITHER_NORMAL,
 
259
                           (guchar *) disp, IWIDTH * 4);
 
260
}
 
261
 
 
262
 
 
263
/* Rendering Functions */
 
264
 
 
265
 
 
266
static void
 
267
bumpbob (int x, int y, int size)
 
268
{
 
269
  int o;
 
270
 
 
271
  /*  for (o=0; o<size; o++)
 
272
    {
 
273
      bump[x+(size/2)+(y+o)*IWIDTH] = 255;
 
274
    }
 
275
  memset(&bump[x+(y+(size/2))*IWIDTH], 255, size);
 
276
  */
 
277
 
 
278
  for (o=0; o<size; o++)
 
279
    {
 
280
      int p;
 
281
      for (p=0; p<size; p++)
 
282
        {
 
283
          int k;
 
284
#define BOB_INC 45
 
285
          k = destbump[p+x+(y+o)*IWIDTH] + BOB_INC;
 
286
          if (k&256)
 
287
            destbump[p+x+(y+o)*IWIDTH] = 255;
 
288
          else
 
289
            destbump[p+x+(y+o)*IWIDTH] = k;
 
290
        }
 
291
      /* memset(&destbump[x+(y+o)*IWIDTH], 131, size); */
 
292
    }
 
293
}
 
294
 
 
295
 
 
296
/* Adam's sillier algorithm. */
 
297
static void
 
298
iterate (void)
 
299
{
 
300
  static guint frame = 0;
 
301
  gint i,j;
 
302
  gint thisbump;
 
303
  guchar sx,sy;
 
304
  guint32 *dest;
 
305
  guint32 *environment;
 
306
  guchar *basebump;
 
307
  unsigned int basesx;
 
308
  unsigned int basesy;
 
309
  GRand *gr;
 
310
  /*  signed int bycxmcybx;
 
311
  signed int bx2,by2;
 
312
  signed int cx2,cy2;
 
313
  const gint bx = -(123-128);
 
314
  const gint by = (128+123);
 
315
  const gint cx = by;
 
316
  const gint cy = -bx;*/
 
317
#define bx (-(123-128))
 
318
#define by (128+123)
 
319
#define cx (by)
 
320
#define cy (-bx)
 
321
#define bycxmcybx (by*cx-cy*bx)
 
322
#define bx2 (((bx)<<19)/bycxmcybx)
 
323
#define by2 (((by)<<19)/bycxmcybx)
 
324
#define cx2 (((cx)<<19)/bycxmcybx)
 
325
#define cy2 (((cy)<<19)/bycxmcybx)
 
326
 
 
327
  gr = g_rand_new ();
 
328
  frame++;
 
329
 
 
330
  environment = (guint32*) env;
 
331
  dest = (guint32*) disp;
 
332
  srcbump = (frame&1) ? bump1 : bump2;
 
333
  destbump = (frame&1) ? bump2 : bump1;
 
334
 
 
335
  /* WARP DISTORTION MAP (plughole-effect) */
 
336
 
 
337
  /* this setup obsolete, tranformation is constant */
 
338
  /*if ((cx+bx) == 0)
 
339
    cx++;
 
340
 
 
341
    if ((cy+by) == 0)
 
342
    by++;
 
343
 
 
344
  bycxmcybx = (by*cx-cy*bx);
 
345
 
 
346
  if (bycxmcybx == 0)
 
347
    bycxmcybx = 1;
 
348
 
 
349
  bx2 = ((bx)<<19)/bycxmcybx;
 
350
  cx2 = ((cx)<<19)/bycxmcybx;
 
351
  by2 = ((by)<<19)/bycxmcybx;
 
352
  cy2 = ((cy)<<19)/bycxmcybx;
 
353
  */
 
354
 
 
355
  /* A little sub-pixel jitter to liven things up. */
 
356
  basesx = (g_rand_int_range (gr, 0, 29<<19)/bycxmcybx) +
 
357
            ((-128-((128*256)/(cx+bx)))<<11);
 
358
  basesy = (g_rand_int_range (gr, 0, 29<<19)/bycxmcybx) + ((-128-((128*256)/(cy+by)))<<11);
 
359
 
 
360
  basebump = srcbump;
 
361
 
 
362
 
 
363
#if 0
 
364
  /* identity only */
 
365
  j = IHEIGHT;
 
366
  while (j--)
 
367
    {
 
368
      i = IWIDTH;
 
369
      while (i--)
 
370
        {
 
371
          *dest++ = *environment++;
 
372
        }
 
373
    }
 
374
  return;
 
375
#endif
 
376
 
 
377
 
 
378
  /* MELT DISTORTION MAP, APPLY IT */
 
379
  j = IHEIGHT;
 
380
  while (j--)
 
381
    {
 
382
      unsigned int tx;
 
383
      unsigned int ty;
 
384
 
 
385
      ty = (basesy+=cx2);
 
386
      tx = (basesx-=bx2);
 
387
 
 
388
      i = IWIDTH;
 
389
      while (i--)
 
390
        {
 
391
          unsigned char *bptr =
 
392
            (srcbump + (
 
393
                        (
 
394
                         ((255&(
 
395
                                (tx>>11)
 
396
                                )))
 
397
                         |
 
398
                         ((((255&(
 
399
                                  (ty>>11)
 
400
                                  ))<<8)))
 
401
                         )
 
402
                        ));
 
403
 
 
404
          thisbump = (11 * *(basebump) + (
 
405
                                          *(bptr-IWIDTH) +
 
406
                                          *(bptr-1) +
 
407
                                          *(bptr) +
 
408
                                          *(bptr+1) +
 
409
                                          *(bptr+IWIDTH)
 
410
                                          )
 
411
                      );
 
412
          basebump++;
 
413
 
 
414
          tx += by2;
 
415
          ty -= cy2;
 
416
 
 
417
          /* TODO: Can accelerate search for non-zero bumps with
 
418
             casting an aligned long-word search. */
 
419
          if (thisbump == 0)
 
420
            {
 
421
              *(dest++) = *( environment + (i | (j<<8) ) );
 
422
              /* *(dest++) = 111; */
 
423
              *(destbump++) = 0;
 
424
            }
 
425
          else
 
426
            {
 
427
              if (thisbump <= (131<<4) )
 
428
                {
 
429
                  thisbump >>= 4;
 
430
                  *destbump = thisbump;
 
431
                }
 
432
              else
 
433
                *destbump = thisbump = 131;
 
434
 
 
435
              /* sy = j + ( ((thisbump) - *(destbump+IWIDTH))<<1);
 
436
                 sx = i + ( ((thisbump) - *(++destbump))<<1);  + blah; */
 
437
              sy = j + ( ((thisbump) - *(destbump+IWIDTH)));
 
438
              sx = i + ( ((thisbump) - *(++destbump)));
 
439
              *dest++ = *( environment + (sx | (sy<<8) ) );
 
440
              /* sx = ( ((thisbump) - *(destbump+IWIDTH)));
 
441
                 sy = ( ((thisbump) - *(++destbump)));
 
442
                 *dest++ = (sx) | (sy<<8) | (sx<<16); */
 
443
            }
 
444
        }
 
445
    }
 
446
 
 
447
 
 
448
  srcbump = (frame&1) ? bump1 : bump2;
 
449
  destbump = (frame&1) ? bump2 : bump1;
 
450
  dest = (guint32 *) disp;
 
451
  memset(destbump, 0, IWIDTH);
 
452
 
 
453
#if 1
 
454
  /*  CAUSTICS!  */
 
455
  /* The idea here is that we refract IWIDTH*IHEIGHT parallel rays
 
456
     through the surface of the slime and illuminate the points
 
457
     where they hit the backing-image.  There are some unrealistic
 
458
     shortcuts taken, but the result is quite pleasing.
 
459
  */
 
460
  j = IHEIGHT;
 
461
  while (j--)
 
462
    {
 
463
      i = IWIDTH;
 
464
      while (i--)
 
465
        {
 
466
          /* Apply caustics */
 
467
          sx = *(destbump++);
 
468
          if (sx!=0)
 
469
            {
 
470
              guchar* cptr;
 
471
 
 
472
              sy = j + ( ((sx) - *(destbump+IWIDTH-1)));
 
473
              sx = i + ( ((sx) - *(destbump)));
 
474
 
 
475
              /* cptr = (guchar*)((guint32*)(( dest+ (0xffff^(sx | (sy<<8) )) ))); */
 
476
              cptr = (guchar*)( dest + (0xffff^(sx | (sy<<8) )) );
 
477
 
 
478
              *cptr = llut[*cptr]; cptr++;
 
479
              *cptr = llut[*cptr]; cptr++;
 
480
              *cptr = llut[*cptr];
 
481
              /* this second point of light's offset (1 across, 1 down)
 
482
                 isn't really 'right' but it gives a more pleasing,
 
483
                 diffuse look. */
 
484
              cptr+= 2 + IWIDTH*4;
 
485
 
 
486
              *cptr = llut[*cptr]; cptr++;
 
487
              *cptr = llut[*cptr]; cptr++;
 
488
              *cptr = llut[*cptr];
 
489
            }
 
490
        }
 
491
    }
 
492
#endif
 
493
 
 
494
 
 
495
    /* Interactive bumpmap */
 
496
#define BOBSIZE 6
 
497
#define BOBSPREAD 40
 
498
#define BOBS_PER_FRAME 70
 
499
  destbump = (frame&1) ? bump2 : bump1;
 
500
  {
 
501
    gint rxp, ryp, posx, posy;
 
502
    GdkModifierType mask;
 
503
    gint size, i;
 
504
 
 
505
    gdk_window_get_pointer (drawing_area->window, &rxp, &ryp, &mask);
 
506
 
 
507
    for (i = 0; i < BOBS_PER_FRAME; i++)
 
508
      {
 
509
        size = g_rand_int_range (gr, 1, BOBSIZE);
 
510
 
 
511
        posx = rxp + BOBSPREAD/2 -
 
512
          RINT(sqrt(g_rand_double_range (gr, 0, BOBSPREAD)) *
 
513
               g_rand_int_range (gr, 0, BOBSPREAD));
 
514
        posy = ryp + BOBSPREAD/2 -
 
515
          RINT(sqrt(g_rand_double_range (gr, 0, BOBSPREAD)) *
 
516
               g_rand_int_range (gr, 0, BOBSPREAD));
 
517
 
 
518
        if (! ((posx>IWIDTH-size) ||
 
519
               (posy>IHEIGHT-size) ||
 
520
               (posx<1) ||
 
521
               (posy<1) ))
 
522
          bumpbob(posx, posy, size);
 
523
      }
 
524
  }
 
525
}
 
526
 
 
527
 
 
528
static void
 
529
render_frame (void)
 
530
{
 
531
  static int frame = 0;
 
532
 
 
533
#if 0
 
534
  if (frame==0)
 
535
    {
 
536
      gint i, bytes;
 
537
 
 
538
      bytes = IWIDTH*IHEIGHT*4;
 
539
 
 
540
      for (i=0;i<bytes;i++)
 
541
        {
 
542
          disp[i] = env[i];
 
543
        }
 
544
    }
 
545
#endif
 
546
 
 
547
  iterate ();
 
548
  show ();
 
549
 
 
550
  frame++;
 
551
}
 
552
 
 
553
 
 
554
static void
 
555
init_preview_misc (void)
 
556
{
 
557
  GimpPixelRgn pixel_rgn;
 
558
  gint         i;
 
559
  gboolean     has_alpha;
 
560
 
 
561
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
 
562
 
 
563
  env = g_malloc (4 * IWIDTH * IHEIGHT * 2);
 
564
  disp = g_malloc ((IWIDTH + 2 + IWIDTH * IHEIGHT) * 4);
 
565
  bump1base = g_malloc (IWIDTH * IHEIGHT + IWIDTH+IWIDTH);
 
566
  bump2base = g_malloc (IWIDTH * IHEIGHT + IWIDTH+IWIDTH);
 
567
 
 
568
  bump1 = &bump1base[IWIDTH];
 
569
  bump2 = &bump2base[IWIDTH];
 
570
 
 
571
  if ((drawable->width<256) || (drawable->height<256))
 
572
    {
 
573
      for (i=0;i<256;i++)
 
574
        {
 
575
          if (i < drawable->height)
 
576
            {
 
577
              gimp_pixel_rgn_init (&pixel_rgn,
 
578
                                   drawable,
 
579
                                   drawable->width>256?
 
580
                                   (drawable->width/2-128):0,
 
581
                                   (drawable->height>256?
 
582
                                   (drawable->height/2-128):0)+i,
 
583
                                   MIN(256,drawable->width),
 
584
                                   1,
 
585
                                   FALSE,
 
586
                                   FALSE);
 
587
              gimp_pixel_rgn_get_rect (&pixel_rgn,
 
588
                                       &env[(256*i +
 
589
                                             (
 
590
                                              (
 
591
                                               drawable->width<256 ?
 
592
                                               (256-drawable->width)/2 :
 
593
                                               0
 
594
                                               )
 
595
                                              +
 
596
                                              (
 
597
                                               drawable->height<256 ?
 
598
                                               (256-drawable->height)/2 :
 
599
                                               0
 
600
                                               ) * 256
 
601
                                              )) *
 
602
                                           gimp_drawable_bpp
 
603
                                           (drawable->drawable_id)
 
604
                                       ],
 
605
                                       drawable->width>256?
 
606
                                       (drawable->width/2-128):0,
 
607
                                       (drawable->height>256?
 
608
                                       (drawable->height/2-128):0)+i,
 
609
                                       MIN(256,drawable->width),
 
610
                                       1);
 
611
            }
 
612
        }
 
613
    }
 
614
  else
 
615
    {
 
616
      gimp_pixel_rgn_init (&pixel_rgn,
 
617
                           drawable,
 
618
                           drawable->width>256?(drawable->width/2-128):0,
 
619
                           drawable->height>256?(drawable->height/2-128):0,
 
620
                           MIN(256,drawable->width),
 
621
                           MIN(256,drawable->height),
 
622
                           FALSE,
 
623
                           FALSE);
 
624
      gimp_pixel_rgn_get_rect (&pixel_rgn,
 
625
                               env,
 
626
                               drawable->width>256?(drawable->width/2-128):0,
 
627
                               drawable->height>256?(drawable->height/2-128):0,
 
628
                               MIN(256,drawable->width),
 
629
                               MIN(256,drawable->height));
 
630
    }
 
631
 
 
632
  gimp_drawable_detach(drawable);
 
633
 
 
634
 
 
635
  /* convert the image data of varying types into flat grey or rgb. */
 
636
  switch (imagetype)
 
637
    {
 
638
    case GIMP_GRAY:
 
639
    case GIMP_INDEXED:
 
640
      if (has_alpha)
 
641
        {
 
642
          for (i=IWIDTH*IHEIGHT;i>0;i--)
 
643
            {
 
644
              env[4*(i-1)+2] =
 
645
                ((palette[3*(env[(i-1)*2])+2]*env[(i-1)*2+1])/255)
 
646
                + ((255-env[(i-1)*2+1])*((i&255) ^ (i>>8)))/255;
 
647
              env[4*(i-1)+1] =
 
648
                ((palette[3*(env[(i-1)*2])+1]*env[(i-1)*2+1])/255)
 
649
                + ((255-env[(i-1)*2+1])*((i&255) ^ (i>>8)))/255;
 
650
              env[4*(i-1)+0] =
 
651
                ((palette[3*(env[(i-1)*2])+0]*env[(i-1)*2+1])/255)
 
652
                + ((255-env[(i-1)*2+1])*((i&255) ^ (i>>8)))/255;
 
653
            }
 
654
        }
 
655
      else
 
656
        {
 
657
          for (i=IWIDTH*IHEIGHT;i>0;i--)
 
658
            {
 
659
              env[4*(i-1)+2] = palette[3*(env[i-1])+2];
 
660
              env[4*(i-1)+1] = palette[3*(env[i-1])+1];
 
661
              env[4*(i-1)+0] = palette[3*(env[i-1])+0];
 
662
            }
 
663
        }
 
664
      break;
 
665
 
 
666
    case GIMP_RGB:
 
667
      if (has_alpha)
 
668
        {
 
669
          for (i=0;i<IWIDTH*IHEIGHT;i++)
 
670
            {
 
671
              env[i*4+2] =
 
672
                (env[i*4+2]*env[i*4+3])/255
 
673
                + ((255-env[i*4+3])*((i&255) ^ (i>>8)))/255;
 
674
              env[i*4+1] =
 
675
                (env[i*4+1]*env[i*4+3])/255
 
676
                + ((255-env[i*4+3])*((i&255) ^ (i>>8)))/255;
 
677
              env[i*4+0] =
 
678
                (env[i*4+0]*env[i*4+3])/255
 
679
                + ((255-env[i*4+3])*((i&255) ^ (i>>8)))/255;
 
680
            }
 
681
        }
 
682
      else
 
683
        {
 
684
          for (i=IWIDTH*IHEIGHT;i>0;i--)
 
685
            {
 
686
              env[4*(i-1)+2] = env[(i-1)*3+2];
 
687
              env[4*(i-1)+1] = env[(i-1)*3+1];
 
688
              env[4*(i-1)+0] = env[(i-1)*3+0];
 
689
            }
 
690
        }
 
691
      break;
 
692
 
 
693
    default:
 
694
      break;
 
695
    }
 
696
 
 
697
  /* Finally, 180-degree flip the environmental image! */
 
698
  for (i = 0; i < IWIDTH*IHEIGHT/2; i++)
 
699
    {
 
700
      guchar t;
 
701
      t = env[4*(i)+0];
 
702
      env[4*(i)+0] = env[4*(IWIDTH*IHEIGHT-(i+1))+0];
 
703
      env[4*(IWIDTH*IHEIGHT-(i+1))+0] = t;
 
704
      t = env[4*(i)+1];
 
705
      env[4*(i)+1] = env[4*(IWIDTH*IHEIGHT-(i+1))+1];
 
706
      env[4*(IWIDTH*IHEIGHT-(i+1))+1] = t;
 
707
      t = env[4*(i)+2];
 
708
      env[4*(i)+2] = env[4*(IWIDTH*IHEIGHT-(i+1))+2];
 
709
      env[4*(IWIDTH*IHEIGHT-(i+1))+2] = t;
 
710
    }
 
711
}
 
712
 
 
713
static gboolean
 
714
do_iteration (void)
 
715
{
 
716
  render_frame ();
 
717
  show ();
 
718
 
 
719
  return TRUE;
 
720
}
 
721
 
 
722
static void
 
723
window_response_callback (GtkWidget *widget,
 
724
                          gint       response_id,
 
725
                          gpointer   data)
 
726
{
 
727
  g_source_remove (idle_tag);
 
728
  idle_tag = 0;
 
729
 
 
730
  gtk_widget_destroy (widget);
 
731
}