~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* sample_colorize.c
 
2
 *      A GIMP Plug-In by Wolfgang Hofer
 
3
 */
 
4
 
 
5
/* The GIMP -- an image manipulation program
 
6
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
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., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
 
 
29
#include <gtk/gtk.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
#define RESPONSE_RESET      1
 
39
#define RESPONSE_GET_COLORS 2
 
40
 
 
41
#define PLUG_IN_NAME        "plug_in_sample_colorize"
 
42
#define NUMBER_IN_ARGS      13
 
43
#define HELP_ID             "plug-in-sample-colorize"
 
44
 
 
45
#define TILE_CACHE_SIZE      32
 
46
#define LUMINOSITY_0(X)      ((X[0] * 30 + X[1] * 59 + X[2] * 11))
 
47
#define LUMINOSITY_1(X)      ((X[0] * 30 + X[1] * 59 + X[2] * 11) / 100)
 
48
#define MIX_CHANNEL(a, b, m) (((a * m) + (b * (255 - m))) / 255)
 
49
 
 
50
#define SMP_GRADIENT         -444
 
51
#define SMP_INV_GRADIENT     -445
 
52
 
 
53
 
 
54
#define PREVIEW_BPP 3
 
55
#define PREVIEW_SIZE_X  256
 
56
#define PREVIEW_SIZE_Y  256
 
57
#define DA_WIDTH         256
 
58
#define DA_HEIGHT        25
 
59
#define GRADIENT_HEIGHT  15
 
60
#define CONTROL_HEIGHT   DA_HEIGHT - GRADIENT_HEIGHT
 
61
#define LEVELS_DA_MASK  (GDK_EXPOSURE_MASK       | \
 
62
                         GDK_ENTER_NOTIFY_MASK   | \
 
63
                         GDK_BUTTON_PRESS_MASK   | \
 
64
                         GDK_BUTTON_RELEASE_MASK | \
 
65
                         GDK_BUTTON1_MOTION_MASK | \
 
66
                         GDK_POINTER_MOTION_HINT_MASK)
 
67
 
 
68
#define LOW_INPUT          0x1
 
69
#define GAMMA              0x2
 
70
#define HIGH_INPUT         0x4
 
71
#define LOW_OUTPUT         0x8
 
72
#define HIGH_OUTPUT        0x10
 
73
#define INPUT_LEVELS       0x20
 
74
#define OUTPUT_LEVELS      0x40
 
75
#define INPUT_SLIDERS      0x80
 
76
#define OUTPUT_SLIDERS     0x100
 
77
#define DRAW               0x200
 
78
#define REFRESH_DST        0x400
 
79
#define ALL                0xFFF
 
80
 
 
81
#define MC_GET_SAMPLE_COLORS 1
 
82
#define MC_DST_REMAP         2
 
83
#define MC_ALL               (MC_GET_SAMPLE_COLORS | MC_DST_REMAP)
 
84
 
 
85
typedef struct
 
86
{
 
87
  gint32  dst_id;
 
88
  gint32  sample_id;
 
89
 
 
90
  gint32 hold_inten;       /* TRUE or FALSE */
 
91
  gint32 orig_inten;       /* TRUE or FALSE */
 
92
  gint32 rnd_subcolors;    /* TRUE or FALSE */
 
93
  gint32 guess_missing;    /* TRUE or FALSE */
 
94
  gint32 lvl_in_min;       /* 0 upto 254 */
 
95
  gint32 lvl_in_max;       /* 1 upto 255 */
 
96
  float  lvl_in_gamma;     /* 0.1 upto 10.0  (1.0 == linear) */
 
97
  gint32 lvl_out_min;       /* 0 upto 254 */
 
98
  gint32 lvl_out_max;       /* 1 upto 255 */
 
99
 
 
100
  float  tol_col_err;      /* 0.0% upto 100.0%
 
101
                            * this is uesd to findout colors of the same
 
102
                            * colortone, while analyzing sample colors,
 
103
                            * It does not make much sense for the user to adjust this
 
104
                            * value. (I used a param file to findout a suitable value)
 
105
                            */
 
106
} t_values;
 
107
 
 
108
typedef struct
 
109
{
 
110
  GtkWidget     *dialog;
 
111
  GtkWidget     *sample_preview;
 
112
  GtkWidget     *dst_preview;
 
113
  GtkWidget     *sample_colortab_preview;
 
114
  GtkWidget     *sample_drawarea;
 
115
  GtkWidget     *in_lvl_gray_preview;
 
116
  GtkWidget     *in_lvl_drawarea;
 
117
  GtkAdjustment *adj_lvl_in_min;
 
118
  GtkAdjustment *adj_lvl_in_max;
 
119
  GtkAdjustment *adj_lvl_in_gamma;
 
120
  GtkAdjustment *adj_lvl_out_min;
 
121
  GtkAdjustment *adj_lvl_out_max;
 
122
  GtkWidget     *orig_inten_button;
 
123
  gint           active_slider;
 
124
  gint           slider_pos[5];  /*  positions for the five sliders  */
 
125
 
 
126
  gint32         enable_preview_update;
 
127
  gint32         sample_show_selection;
 
128
  gint32         dst_show_selection;
 
129
  gint32         sample_show_color;
 
130
  gint32         dst_show_color;
 
131
}   t_samp_interface;
 
132
 
 
133
 
 
134
 
 
135
typedef struct
 
136
{
 
137
  guchar     color[4];  /* R,G,B,A */
 
138
  gint32     sum_color;         /* nr. of sourcepixels with (nearly the same) color */
 
139
  void      *next;
 
140
} t_samp_color_elem;
 
141
 
 
142
 
 
143
 
 
144
typedef struct
 
145
{
 
146
  gint32              all_samples;  /* number of all source pixels with this luminosity */
 
147
  gint                from_sample;  /* TRUE: color found in sample, FALSE: interpolated color added */
 
148
  t_samp_color_elem  *col_ptr;       /* List of sample colors at same luminosity */
 
149
} t_samp_table_elem;
 
150
 
 
151
 
 
152
typedef struct
 
153
{
 
154
   GimpDrawable *drawable;
 
155
   void         *sel_gdrw;
 
156
   GimpPixelRgn  pr;
 
157
   gint          x1;
 
158
   gint          y1;
 
159
   gint          x2;
 
160
   gint          y2;
 
161
   gint          index_alpha;   /* 0 == no alpha, 1 == GREYA, 3 == RGBA */
 
162
   gint          bpp;
 
163
   GimpTile     *tile;
 
164
   gint          tile_row;
 
165
   gint          tile_col;
 
166
   gint          tile_width;
 
167
   gint          tile_height;
 
168
   gint          tile_dirty;
 
169
   gint          shadow;
 
170
   gint32        seldeltax;
 
171
   gint32        seldeltay;
 
172
   gint32        tile_swapcount;
 
173
} t_GDRW;
 
174
 
 
175
/*
 
176
 * Some globals
 
177
 */
 
178
 
 
179
static t_samp_interface  g_di;  /* global dialog interface varables */
 
180
static t_values          g_values = { -1, -1, 1, 1, 0, 1, 0, 255, 1.0, 0, 255, 5.5 };
 
181
static t_samp_table_elem g_lum_tab[256];
 
182
static guchar            g_lvl_trans_tab[256];
 
183
static guchar            g_out_trans_tab[256];
 
184
static guchar            g_sample_color_tab[256 * 3];
 
185
static guchar            g_dst_preview_buffer[PREVIEW_SIZE_X * PREVIEW_SIZE_Y * 4 ];  /* color copy with mask of dst in previewsize */
 
186
 
 
187
static gint32  g_tol_col_err;
 
188
static gint32  g_max_col_err;
 
189
static gint    g_Sdebug = FALSE;
 
190
static gint    g_show_progress = FALSE;
 
191
 
 
192
/* Declare a local function.
 
193
 */
 
194
static void      query  (void);
 
195
static void      run    (const gchar      *name,
 
196
                         gint              nparams,
 
197
                         const GimpParam  *param,
 
198
                         gint            *nreturn_vals,
 
199
                         GimpParam       **return_vals);
 
200
 
 
201
static gint      p_main_colorize(gint);
 
202
static void      p_get_filevalues (void);
 
203
static void      p_smp_dialog (void);
 
204
static void      p_refresh_dst_preview(GtkWidget *preview, guchar *src_buffer);
 
205
static void      p_update_preview (gint32 *id_ptr);
 
206
static void      p_clear_tables(void);
 
207
static void      p_free_colors(void);
 
208
static void      p_levels_update (gint update);
 
209
static gint      p_level_in_events (GtkWidget *widget, GdkEvent *event, gpointer data);
 
210
static gint      p_level_out_events (GtkWidget *widget, GdkEvent *event, gpointer data);
 
211
static void      p_calculate_level_transfers (void);
 
212
static void      p_get_pixel(t_GDRW *gdrw, gint32 x, gint32 y, guchar *pixel);
 
213
static void      p_init_gdrw(t_GDRW *gdrw, GimpDrawable *drawable, gint dirty, gint shadow);
 
214
static void      p_end_gdrw(t_GDRW *gdrw);
 
215
static gint32    p_is_layer_alive(gint32 drawable_id);
 
216
static void      p_remap_pixel (guchar       *pixel,
 
217
                                const guchar *original,
 
218
                                gint          bpp2);
 
219
static void      p_guess_missing_colors(void);
 
220
static void      p_fill_missing_colors(void);
 
221
static void      p_smp_get_colors(GtkWidget *dialog);
 
222
static void      p_get_gradient (gint mode);
 
223
static void      p_clear_preview(GtkWidget *preview);
 
224
 
 
225
GimpPlugInInfo PLUG_IN_INFO =
 
226
{
 
227
  NULL,  /* init_proc  */
 
228
  NULL,  /* quit_proc  */
 
229
  query, /* query_proc */
 
230
  run    /* run_proc   */
 
231
};
 
232
 
 
233
MAIN ()
 
234
 
 
235
static void
 
236
query (void)
 
237
{
 
238
  static GimpParamDef args[]=
 
239
  {
 
240
    { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
 
241
    { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
 
242
    { GIMP_PDB_DRAWABLE, "dst_drawable", "The drawable to be colorized (Type GRAY* or RGB*)" },
 
243
    { GIMP_PDB_DRAWABLE, "sample_drawable", "Sample drawable (should be of Type RGB or RGBA)" },
 
244
    { GIMP_PDB_INT32, "hold_inten", "hold brightness intensity levels (TRUE, FALSE)" },
 
245
    { GIMP_PDB_INT32, "orig_inten", "TRUE: hold brightness of original intensity levels. FALSE: Hold Intensity of input levels" },
 
246
    { GIMP_PDB_INT32, "rnd_subcolors", "TRUE: Use all subcolors of same intensity, FALSE: use only one color per intensity" },
 
247
    { GIMP_PDB_INT32, "guess_missing", "TRUE: guess samplecolors for the missing intensity values FALSE: use only colors found in the sample" },
 
248
    { GIMP_PDB_INT32, "in_low",   "intensity of lowest input (0 <= in_low <= 254)" },
 
249
    { GIMP_PDB_INT32, "in_high",  "intensity of highest input (1 <= in_high <= 255)" },
 
250
    { GIMP_PDB_FLOAT, "gamma",  "gamma correction factor (0.1 <= gamma <= 10) where 1.0 is linear" },
 
251
    { GIMP_PDB_INT32, "out_low",   "lowest sample color intensity (0 <= out_low <= 254)" },
 
252
    { GIMP_PDB_INT32, "out_high",  "highest sample color intensity (1 <= out_high <= 255)" }
 
253
  };
 
254
 
 
255
  static gchar *help_string =
 
256
    "This plug-in colorizes the contents of the specified (gray) layer"
 
257
    " with the help of a  sample (color) layer."
 
258
    " It analyzes all colors in the sample layer."
 
259
    " The sample colors are sorted by brightness (== intentisty) and amount"
 
260
    " and stored in a sample colortable (where brightness is the index)"
 
261
    " The pixels of the destination layer are remapped with the help of the"
 
262
    " sample colortable. If use_subcolors is TRUE, the remapping process uses"
 
263
    " all sample colors of the corresponding brightness-intensity and"
 
264
    " distributes the subcolors according to their amount in the sample"
 
265
    " (If the sample has 5 green, 3 yellow, and 1 red pixel of the "
 
266
    " intensity value 105, the destination pixels at intensity value 105"
 
267
    " are randomly painted in green, yellow and red in a relation of 5:3:1"
 
268
    " If use_subcolors is FALSE only one sample color per intensity is used."
 
269
    " (green will be used in this example)"
 
270
    " The brightness intensity value is transformed at the remapping process"
 
271
    " according to the levels: out_lo, out_hi, in_lo, in_high and gamma"
 
272
    " The in_low / in_high levels specify an initial mapping of the intensity."
 
273
    " The gamma value determines how intensities are interpolated between"
 
274
    " the in_lo and in_high levels. A gamma value of 1.0 results in linear"
 
275
    " interpolation. Higher gamma values results in more high-level intensities"
 
276
    " Lower gamma values results in more low-level intensities"
 
277
    " The out_low/out_high levels constrain the resulting intensity index"
 
278
    " The intensity index is used to pick the corresponding color"
 
279
    " in the sample colortable. If hold_inten is FALSE the picked color"
 
280
    " is used 1:1 as resulting remap_color."
 
281
    " If hold_inten is TRUE The brightness of the picked color is adjusted"
 
282
    " back to the origial intensity value (only hue and saturation are"
 
283
    " taken from the picked sample color)"
 
284
    " (or to the input level, if orig_inten is set FALSE)"
 
285
    " Works on both Grayscale and RGB image with/without alpha channel."
 
286
    " (the image with the dst_drawable is converted to RGB if necessary)"
 
287
    " The sample_drawable should be of type RGB or RGBA";
 
288
 
 
289
  gimp_install_procedure (PLUG_IN_NAME,
 
290
                          "Colorize the contents of the specified drawable "
 
291
                          "similar to sample drawable",
 
292
                          help_string,
 
293
                          "Wolfgang Hofer",
 
294
                          "hof@hotbot.com",
 
295
                          "02/2000",
 
296
                          N_("_Sample Colorize..."),
 
297
                          "RGB*, GRAY*",
 
298
                          GIMP_PLUGIN,
 
299
                          G_N_ELEMENTS (args), 0,
 
300
                          args, NULL);
 
301
 
 
302
  gimp_plugin_menu_register (PLUG_IN_NAME,
 
303
                             "<Image>/Filters/Colors/Map");
 
304
}
 
305
 
 
306
static void
 
307
run (const gchar      *name,
 
308
     gint              nparams,
 
309
     const GimpParam  *param,
 
310
     gint             *nreturn_vals,
 
311
     GimpParam       **return_vals)
 
312
{
 
313
  static GimpParam   values[1];
 
314
  GimpDrawable      *dst_drawable;
 
315
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
 
316
  const gchar       *l_env;
 
317
  GimpRunMode        run_mode;
 
318
 
 
319
  INIT_I18N ();
 
320
 
 
321
  l_env = g_getenv ("SAMPLE_COLORIZE_DEBUG");
 
322
  if (l_env != NULL)
 
323
    {
 
324
      if((*l_env != 'n') && (*l_env != 'N')) g_Sdebug = TRUE;
 
325
    }
 
326
 
 
327
  if(g_Sdebug) printf("sample colorize run\n");
 
328
  g_show_progress = FALSE;
 
329
 
 
330
  run_mode = param[0].data.d_int32;
 
331
 
 
332
  *nreturn_vals = 1;
 
333
  *return_vals = values;
 
334
 
 
335
  values[0].type = GIMP_PDB_STATUS;
 
336
  values[0].data.d_status = status;
 
337
 
 
338
  g_values.lvl_out_min = 0;
 
339
  g_values.lvl_out_max = 255;
 
340
  g_values.lvl_in_min = 0;
 
341
  g_values.lvl_in_max = 255;
 
342
  g_values.lvl_in_gamma = 1.0;
 
343
 
 
344
  /* Possibly retrieve data from a previous run */
 
345
  gimp_get_data (PLUG_IN_NAME, &g_values);
 
346
 
 
347
  /* fix value */
 
348
  g_values.tol_col_err = 5.5;
 
349
 
 
350
  /*  Get the specified dst_drawable  */
 
351
  g_values.dst_id = param[2].data.d_drawable;
 
352
  dst_drawable = gimp_drawable_get (g_values.dst_id );
 
353
 
 
354
  p_clear_tables();
 
355
 
 
356
  /*  Make sure that the dst_drawable is gray or RGB color        */
 
357
  if (gimp_drawable_is_rgb (dst_drawable->drawable_id) ||
 
358
      gimp_drawable_is_gray (dst_drawable->drawable_id))
 
359
    {
 
360
      gimp_tile_cache_ntiles (TILE_CACHE_SIZE);
 
361
 
 
362
      switch (run_mode)
 
363
        {
 
364
        case GIMP_RUN_INTERACTIVE:
 
365
          p_smp_dialog ();
 
366
          p_free_colors ();
 
367
          gimp_set_data (PLUG_IN_NAME, &g_values, sizeof (t_values));
 
368
          gimp_displays_flush ();
 
369
          break;
 
370
 
 
371
        case GIMP_RUN_NONINTERACTIVE:
 
372
          if (nparams == NUMBER_IN_ARGS)
 
373
            {
 
374
              g_values.sample_id     = param[3].data.d_drawable;
 
375
              g_values.hold_inten    = param[4].data.d_int32;
 
376
              g_values.orig_inten    = param[5].data.d_int32;
 
377
              g_values.rnd_subcolors = param[6].data.d_int32;
 
378
              g_values.guess_missing = param[7].data.d_int32;
 
379
              g_values.lvl_in_min    = param[8].data.d_int32;
 
380
              g_values.lvl_in_max    = param[9].data.d_int32;
 
381
              g_values.lvl_in_gamma  = param[10].data.d_float;
 
382
              g_values.lvl_out_min   = param[11].data.d_int32;
 
383
              g_values.lvl_out_max   = param[12].data.d_int32;
 
384
            }
 
385
          else
 
386
            {
 
387
              status = GIMP_PDB_CALLING_ERROR;
 
388
            }
 
389
          break;
 
390
 
 
391
        case GIMP_RUN_WITH_LAST_VALS:
 
392
          break;
 
393
        }
 
394
    }
 
395
  else
 
396
    {
 
397
      status = GIMP_PDB_EXECUTION_ERROR;
 
398
    }
 
399
 
 
400
  values[0].data.d_status = status;
 
401
 
 
402
  gimp_drawable_detach (dst_drawable);
 
403
}
 
404
 
 
405
/* ============================================================================
 
406
 * callback and constraint procedures for the dialog
 
407
 * ============================================================================
 
408
 */
 
409
 
 
410
static void
 
411
p_smp_response_callback (GtkWidget *widget,
 
412
                         gint       response_id,
 
413
                         gpointer   data)
 
414
{
 
415
  switch (response_id)
 
416
    {
 
417
    case RESPONSE_RESET:
 
418
      g_values.lvl_in_min    = 0;
 
419
      g_values.lvl_in_max    = 255;
 
420
      g_values.lvl_in_gamma  = 1.0;
 
421
      g_values.lvl_out_min   = 0;
 
422
      g_values.lvl_out_max   = 255;
 
423
 
 
424
      p_levels_update (ALL);
 
425
      break;
 
426
 
 
427
    case RESPONSE_GET_COLORS:
 
428
      p_smp_get_colors (widget);
 
429
      break;
 
430
 
 
431
    case GTK_RESPONSE_APPLY:
 
432
      g_show_progress = TRUE;
 
433
      if (p_main_colorize (MC_DST_REMAP) == 0)
 
434
        {
 
435
          gimp_displays_flush ();
 
436
          g_show_progress = FALSE;
 
437
          return;
 
438
        }
 
439
      gtk_dialog_set_response_sensitive (GTK_DIALOG (widget),
 
440
                                         GTK_RESPONSE_APPLY, FALSE);
 
441
      break;
 
442
 
 
443
    default:
 
444
      gtk_widget_destroy (widget);
 
445
      gtk_main_quit ();
 
446
      break;
 
447
    }
 
448
}
 
449
 
 
450
static void
 
451
p_smp_toggle_callback (GtkWidget *widget,
 
452
                       gpointer   data)
 
453
{
 
454
  gint32 *toggle_val = (gint32 *) data;
 
455
 
 
456
  if (GTK_TOGGLE_BUTTON (widget)->active) { *toggle_val = TRUE;  }
 
457
  else                                    { *toggle_val = FALSE; }
 
458
 
 
459
  if((data == &g_di.sample_show_selection) || (data == &g_di.sample_show_color))
 
460
  {
 
461
     p_update_preview (&g_values.sample_id);
 
462
     return;
 
463
  }
 
464
 
 
465
  if((data == &g_di.dst_show_selection) || (data == &g_di.dst_show_color))
 
466
  {
 
467
     p_update_preview (&g_values.dst_id);
 
468
     return;
 
469
  }
 
470
 
 
471
  if((data == &g_values.hold_inten) || (data == &g_values.orig_inten)
 
472
  || (data == &g_values.rnd_subcolors))
 
473
  {
 
474
     if(g_di.orig_inten_button)
 
475
     {
 
476
       gtk_widget_set_sensitive (g_di.orig_inten_button,g_values.hold_inten);
 
477
     }
 
478
     p_refresh_dst_preview (g_di.dst_preview,  &g_dst_preview_buffer[0]);
 
479
  }
 
480
 
 
481
  if(data == &g_values.guess_missing)
 
482
  {
 
483
     if(g_values.guess_missing) { p_guess_missing_colors(); }
 
484
     else                       { p_fill_missing_colors(); }
 
485
     p_smp_get_colors (NULL);
 
486
  }
 
487
 
 
488
}
 
489
 
 
490
static void
 
491
p_smp_sample_combo_callback (GtkWidget *widget,
 
492
                             gpointer   data)
 
493
{
 
494
  gint value;
 
495
 
 
496
  gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
 
497
 
 
498
  g_values.sample_id = value;
 
499
 
 
500
  if (value == SMP_GRADIENT || value == SMP_INV_GRADIENT)
 
501
    {
 
502
      p_get_gradient (value);
 
503
      p_smp_get_colors (NULL);
 
504
 
 
505
      if (g_di.sample_preview)
 
506
        p_clear_preview (g_di.sample_preview);
 
507
 
 
508
      gtk_dialog_set_response_sensitive (GTK_DIALOG (g_di.dialog),
 
509
                                         GTK_RESPONSE_APPLY, TRUE);
 
510
      gtk_dialog_set_response_sensitive (GTK_DIALOG (g_di.dialog),
 
511
                                         RESPONSE_GET_COLORS, FALSE);
 
512
    }
 
513
  else
 
514
    {
 
515
      p_update_preview (&g_values.sample_id);
 
516
 
 
517
      gtk_dialog_set_response_sensitive (GTK_DIALOG (g_di.dialog),
 
518
                                         RESPONSE_GET_COLORS, TRUE);
 
519
    }
 
520
}
 
521
 
 
522
static void
 
523
p_smp_dest_combo_callback (GtkWidget *widget,
 
524
                           gpointer   data)
 
525
{
 
526
  gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget),
 
527
                                 &g_values.dst_id);
 
528
 
 
529
  p_update_preview (&g_values.dst_id);
 
530
 
 
531
  gtk_dialog_set_response_sensitive (GTK_DIALOG (g_di.dialog),
 
532
                                     RESPONSE_GET_COLORS, TRUE);
 
533
}
 
534
 
 
535
static gint
 
536
p_smp_constrain (gint32    image_id,
 
537
                 gint32    drawable_id,
 
538
                 gpointer  data)
 
539
{
 
540
  if (image_id < 0)
 
541
    return FALSE;
 
542
 
 
543
  /* dont accept layers from indexed images */
 
544
  if (gimp_drawable_is_indexed (drawable_id))
 
545
    return FALSE;
 
546
 
 
547
  return TRUE;
 
548
}
 
549
 
 
550
 
 
551
static void
 
552
p_smp_adj_lvl_in_max_upd_callback (GtkAdjustment *adjustment,
 
553
                                   gpointer       data)
 
554
{
 
555
  gint32 value;
 
556
  gint   upd_flags;
 
557
 
 
558
  value = CLAMP ((adjustment->value), 1, 255);
 
559
 
 
560
  if (value != g_values.lvl_in_max)
 
561
  {
 
562
    g_values.lvl_in_max = value;
 
563
    upd_flags = INPUT_SLIDERS | INPUT_LEVELS | DRAW | REFRESH_DST;
 
564
    if(g_values.lvl_in_max < g_values.lvl_in_min)
 
565
    {
 
566
      g_values.lvl_in_min = g_values.lvl_in_max;
 
567
      upd_flags |= LOW_INPUT;
 
568
    }
 
569
    p_levels_update (upd_flags);
 
570
  }
 
571
}
 
572
 
 
573
static void
 
574
p_smp_adj_lvl_in_min_upd_callback(GtkAdjustment *adjustment,
 
575
                              gpointer   data)
 
576
{
 
577
  double value;
 
578
  gint   upd_flags;
 
579
 
 
580
  value = CLAMP ((adjustment->value), 0, 254);
 
581
 
 
582
  if (value != g_values.lvl_in_min)
 
583
  {
 
584
    g_values.lvl_in_min = value;
 
585
    upd_flags = INPUT_SLIDERS | INPUT_LEVELS | DRAW | REFRESH_DST;
 
586
    if(g_values.lvl_in_min > g_values.lvl_in_max)
 
587
    {
 
588
      g_values.lvl_in_max = g_values.lvl_in_min;
 
589
      upd_flags |= HIGH_INPUT;
 
590
    }
 
591
    p_levels_update (upd_flags);
 
592
  }
 
593
}
 
594
 
 
595
static void
 
596
p_smp_text_gamma_upd_callback (GtkAdjustment *adjustment,
 
597
                               gpointer       data)
 
598
{
 
599
  double value;
 
600
 
 
601
  value = CLAMP ((adjustment->value), 0.1, 10.0);
 
602
 
 
603
  if (value != g_values.lvl_in_gamma)
 
604
  {
 
605
    g_values.lvl_in_gamma = value;
 
606
    p_levels_update (INPUT_SLIDERS | INPUT_LEVELS | DRAW | REFRESH_DST);
 
607
  }
 
608
}
 
609
 
 
610
static void
 
611
p_smp_adj_lvl_out_max_upd_callback (GtkAdjustment *adjustment,
 
612
                                    gpointer       data)
 
613
{
 
614
  gint32 value;
 
615
  gint   upd_flags;
 
616
 
 
617
  value = CLAMP ((adjustment->value), 1, 255);
 
618
 
 
619
  if (value != g_values.lvl_out_max)
 
620
  {
 
621
    g_values.lvl_out_max = value;
 
622
    upd_flags = OUTPUT_SLIDERS | OUTPUT_LEVELS | DRAW | REFRESH_DST;
 
623
    if(g_values.lvl_out_max < g_values.lvl_out_min)
 
624
    {
 
625
      g_values.lvl_out_min = g_values.lvl_out_max;
 
626
      upd_flags |= LOW_OUTPUT;
 
627
    }
 
628
    p_levels_update (upd_flags);
 
629
  }
 
630
}
 
631
 
 
632
static void
 
633
p_smp_adj_lvl_out_min_upd_callback (GtkAdjustment *adjustment,
 
634
                                    gpointer       data)
 
635
{
 
636
  double value;
 
637
  gint   upd_flags;
 
638
 
 
639
  value = CLAMP ((adjustment->value), 0, 254);
 
640
 
 
641
  if (value != g_values.lvl_out_min)
 
642
  {
 
643
    g_values.lvl_out_min = value;
 
644
    upd_flags = OUTPUT_SLIDERS | OUTPUT_LEVELS | DRAW  | REFRESH_DST;
 
645
    if(g_values.lvl_out_min > g_values.lvl_out_max)
 
646
    {
 
647
      g_values.lvl_out_max = g_values.lvl_out_min;
 
648
      upd_flags |= HIGH_OUTPUT;
 
649
    }
 
650
    p_levels_update (upd_flags);
 
651
  }
 
652
}
 
653
 
 
654
/* ============================================================================
 
655
 * DIALOG helper procedures
 
656
 *    (workers for the updates on the preview widgets)
 
657
 * ============================================================================
 
658
 */
 
659
 
 
660
static void
 
661
p_refresh_dst_preview (GtkWidget *preview,
 
662
                       guchar    *src_buffer)
 
663
{
 
664
  guchar  l_allrowsbuf[3 * PREVIEW_SIZE_X * PREVIEW_SIZE_Y];
 
665
  guchar *l_ptr;
 
666
  guchar *l_src_ptr;
 
667
  guchar  l_lum;
 
668
  guchar  l_maskbyte;
 
669
  gint    l_x, l_y;
 
670
  gint    l_preview_bpp;
 
671
  gint    l_src_bpp;
 
672
 
 
673
  l_preview_bpp = PREVIEW_BPP;
 
674
  l_src_bpp = PREVIEW_BPP +1;   /* 3 colors + 1 maskbyte */
 
675
  l_src_ptr = src_buffer;
 
676
 
 
677
  l_ptr = l_allrowsbuf;
 
678
  for(l_y = 0; l_y < PREVIEW_SIZE_Y; l_y++)
 
679
    {
 
680
      for(l_x = 0; l_x < PREVIEW_SIZE_X; l_x++)
 
681
        {
 
682
          if((l_maskbyte = l_src_ptr[3]) == 0)
 
683
            {
 
684
              l_ptr[0] = l_src_ptr[0];
 
685
              l_ptr[1] = l_src_ptr[1];
 
686
              l_ptr[2] = l_src_ptr[2];
 
687
            }
 
688
          else
 
689
            {
 
690
              if(g_di.dst_show_color)
 
691
                {
 
692
                  p_remap_pixel(l_ptr, l_src_ptr, 3);
 
693
                }
 
694
              else
 
695
                {
 
696
                  /* l_lum = g_out_trans_tab[g_lvl_trans_tab[LUMINOSITY_1(l_src_ptr)]]; */
 
697
                  /* get brightness from (uncolorized) original */
 
698
 
 
699
                  l_lum = g_lvl_trans_tab[LUMINOSITY_1(l_src_ptr)];
 
700
                  /* get brightness from (uncolorized) original */
 
701
 
 
702
                  l_ptr[0] = l_lum;
 
703
                  l_ptr[1] = l_lum;
 
704
                  l_ptr[2] = l_lum;
 
705
                }
 
706
 
 
707
              if (l_maskbyte < 255)
 
708
                {
 
709
                  l_ptr[0] = MIX_CHANNEL(l_ptr[0], l_src_ptr[0], l_maskbyte);
 
710
                  l_ptr[1] = MIX_CHANNEL(l_ptr[1], l_src_ptr[1], l_maskbyte);
 
711
                  l_ptr[2] = MIX_CHANNEL(l_ptr[2], l_src_ptr[2], l_maskbyte);
 
712
                }
 
713
            }
 
714
          l_ptr += l_preview_bpp;
 
715
          l_src_ptr += l_src_bpp;
 
716
        }
 
717
    }
 
718
  gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
 
719
                          0, 0, PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
 
720
                          GIMP_RGB_IMAGE,
 
721
                          l_allrowsbuf,
 
722
                          PREVIEW_SIZE_X * 3);
 
723
}        /* end p_refresh_dst_preview */
 
724
 
 
725
static void
 
726
p_clear_preview (GtkWidget *preview)
 
727
{
 
728
  gimp_preview_area_fill (GIMP_PREVIEW_AREA (preview),
 
729
                          0, 0, PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
 
730
                          170, 170, 170);
 
731
}        /* end p_clear_preview */
 
732
 
 
733
static void
 
734
p_update_pv (GtkWidget *preview,
 
735
             gint32     show_selection,
 
736
             t_GDRW    *gdrw,
 
737
             guchar    *dst_buffer,
 
738
             gint       is_color)
 
739
{
 
740
  guchar  l_allrowsbuf[4 * PREVIEW_SIZE_X * PREVIEW_SIZE_Y];
 
741
  guchar  l_pixel[4];
 
742
  guchar *l_ptr;
 
743
  gint    l_x, l_y;
 
744
  gint    l_x2, l_y2;
 
745
  gint    l_ofx, l_ofy;
 
746
  gint    l_sel_width, l_sel_height;
 
747
  double  l_scale_x, l_scale_y;
 
748
  guchar *l_buf_ptr;
 
749
  guchar  l_dummy[4];
 
750
  guchar  l_maskbytes[4];
 
751
  gint    l_dstep;
 
752
  guchar  l_alpha;
 
753
 
 
754
 
 
755
  if (!preview)
 
756
    return;
 
757
 
 
758
  /* init gray pixel (if we are called without a sourceimage (gdwr == NULL) */
 
759
  l_pixel[0] = l_pixel[1] =l_pixel[2] = l_pixel[3] = 127;
 
760
 
 
761
  /* calculate scale factors and offsets */
 
762
  if(show_selection)
 
763
    {
 
764
      l_sel_width  = gdrw->x2 - gdrw->x1;
 
765
      l_sel_height = gdrw->y2 - gdrw->y1;
 
766
 
 
767
      if(l_sel_height > l_sel_width)
 
768
        {
 
769
          l_scale_y = (gfloat) l_sel_height / PREVIEW_SIZE_Y;
 
770
          l_scale_x = l_scale_y;
 
771
          l_ofx = (gdrw->x1 +
 
772
                   ((l_sel_width - (PREVIEW_SIZE_X * l_scale_x)) / 2));
 
773
          l_ofy = gdrw->y1;
 
774
        }
 
775
      else
 
776
        {
 
777
          l_scale_x = (gfloat) l_sel_width / PREVIEW_SIZE_X;
 
778
          l_scale_y = l_scale_x;
 
779
          l_ofx = gdrw->x1;
 
780
          l_ofy = (gdrw->y1 +
 
781
                   ((l_sel_height - (PREVIEW_SIZE_Y * l_scale_y)) / 2));
 
782
        }
 
783
    }
 
784
  else
 
785
    {
 
786
      if (gdrw->drawable->height > gdrw->drawable->width)
 
787
        {
 
788
          l_scale_y = (gfloat) gdrw->drawable->height / PREVIEW_SIZE_Y;
 
789
          l_scale_x = l_scale_y;
 
790
          l_ofx = (gdrw->drawable->width - (PREVIEW_SIZE_X * l_scale_x)) / 2;
 
791
          l_ofy = 0;
 
792
        }
 
793
      else
 
794
        {
 
795
          l_scale_x = (gfloat) gdrw->drawable->width / PREVIEW_SIZE_X;
 
796
          l_scale_y = l_scale_x;
 
797
          l_ofx = 0;
 
798
          l_ofy = (gdrw->drawable->height - (PREVIEW_SIZE_Y * l_scale_y)) / 2;
 
799
        }
 
800
    }
 
801
 
 
802
  /* check if output goes to previw widget or to dst_buffer */
 
803
  if (dst_buffer) { l_buf_ptr = dst_buffer; l_dstep = PREVIEW_BPP +1; }
 
804
  else            { l_buf_ptr = &l_dummy[0]; l_dstep = 0; }
 
805
 
 
806
 
 
807
  /* render preview */
 
808
  l_ptr = l_allrowsbuf;
 
809
  for (l_y = 0; l_y < PREVIEW_SIZE_Y; l_y++)
 
810
    {
 
811
      for(l_x = 0; l_x < PREVIEW_SIZE_X; l_x++)
 
812
        {
 
813
          if (gdrw->drawable)
 
814
            {
 
815
              l_x2 = l_ofx + (l_x * l_scale_x);
 
816
              l_y2 = l_ofy + (l_y * l_scale_y);
 
817
              p_get_pixel(gdrw, l_x2, l_y2, &l_pixel[0]);
 
818
              if (gdrw->sel_gdrw)
 
819
                {
 
820
                  p_get_pixel (gdrw->sel_gdrw,
 
821
                               l_x2 + gdrw->seldeltax,
 
822
                               l_y2 + gdrw->seldeltay,
 
823
                               &l_maskbytes[0]);
 
824
                }
 
825
              else
 
826
                {
 
827
                  l_maskbytes[0] = 255;
 
828
                }
 
829
            }
 
830
 
 
831
          l_alpha = l_pixel[gdrw->index_alpha];
 
832
          if (is_color && (gdrw->bpp > 2))
 
833
            {
 
834
              l_buf_ptr[0] = l_ptr[0] = l_pixel[0];
 
835
              l_buf_ptr[1] = l_ptr[1] = l_pixel[1];
 
836
              l_buf_ptr[2] = l_ptr[2] = l_pixel[2];
 
837
            }
 
838
          else
 
839
            {
 
840
              if(gdrw->bpp > 2)  *l_ptr = LUMINOSITY_1(l_pixel);
 
841
              else               *l_ptr = l_pixel[0];
 
842
 
 
843
              *l_buf_ptr   = *l_ptr;
 
844
              l_buf_ptr[1] = l_ptr[1] = *l_ptr;
 
845
              l_buf_ptr[2] = l_ptr[2] = *l_ptr;
 
846
            }
 
847
          if (gdrw->index_alpha == 0)             /* has no alpha channel */
 
848
            l_buf_ptr[3] = l_ptr[3] = 255;
 
849
          else          
 
850
            l_buf_ptr[3] = l_ptr[3] = MIN(l_maskbytes[0], l_alpha);
 
851
          l_buf_ptr += l_dstep;   /* advance (or stay at dummy byte) */
 
852
          l_ptr += 4;
 
853
        }
 
854
 
 
855
    }
 
856
 
 
857
  if (dst_buffer == NULL)
 
858
    {
 
859
      gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
 
860
                              0, 0, PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
 
861
                              GIMP_RGBA_IMAGE,
 
862
                              l_allrowsbuf,
 
863
                              PREVIEW_SIZE_X * 4);
 
864
      gtk_widget_queue_draw (preview);
 
865
    }
 
866
}        /* end p_update_pv */
 
867
 
 
868
static void
 
869
p_update_preview (gint32 *id_ptr)
 
870
{
 
871
  GimpDrawable *drawable;
 
872
  t_GDRW     l_gdrw;
 
873
 
 
874
  if(g_Sdebug)  printf("UPD PREVIEWS   ID:%d ENABLE_UPD:%d\n", (int)*id_ptr, (int)g_di.enable_preview_update);
 
875
 
 
876
  if(id_ptr == NULL)                 { return; }
 
877
  if(!g_di.enable_preview_update)    { return; }
 
878
  if(p_is_layer_alive(*id_ptr) < 0)
 
879
    {
 
880
      /* clear preview on invalid drawable id
 
881
       * (SMP_GRADIENT and SMP_INV_GRADIENT)
 
882
       */
 
883
      if(id_ptr == &g_values.sample_id)
 
884
        {
 
885
          p_clear_preview(g_di.sample_preview);
 
886
        }
 
887
      if(id_ptr == &g_values.dst_id)
 
888
        {
 
889
          p_clear_preview(g_di.dst_preview);
 
890
        }
 
891
      return;
 
892
    }
 
893
 
 
894
  drawable = gimp_drawable_get (*id_ptr);
 
895
 
 
896
  if(id_ptr == &g_values.sample_id)
 
897
    {
 
898
      p_init_gdrw(&l_gdrw, drawable, FALSE, FALSE);
 
899
      p_update_pv(g_di.sample_preview, g_di.sample_show_selection, &l_gdrw, NULL, g_di.sample_show_color);
 
900
    }
 
901
  else if (id_ptr == &g_values.dst_id)
 
902
    {
 
903
      p_init_gdrw(&l_gdrw, drawable, FALSE, FALSE);
 
904
      p_update_pv(g_di.dst_preview, g_di.dst_show_selection, &l_gdrw, &g_dst_preview_buffer[0], g_di.dst_show_color);
 
905
      p_refresh_dst_preview(g_di.dst_preview,  &g_dst_preview_buffer[0]);
 
906
    }
 
907
 
 
908
  if (drawable)
 
909
    p_end_gdrw (&l_gdrw);
 
910
}        /* end p_update_preview */
 
911
 
 
912
static void
 
913
p_levels_draw_slider (GdkWindow *window,
 
914
                      GdkGC     *border_gc,
 
915
                      GdkGC     *fill_gc,
 
916
                      gint       xpos)
 
917
{
 
918
  gint y;
 
919
 
 
920
  for (y = 0; y < CONTROL_HEIGHT; y++)
 
921
    gdk_draw_line(window, fill_gc, xpos - y / 2, y,
 
922
                  xpos + y / 2, y);
 
923
 
 
924
  gdk_draw_line(window, border_gc, xpos, 0,
 
925
                xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
 
926
 
 
927
  gdk_draw_line(window, border_gc, xpos, 0,
 
928
                xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
 
929
 
 
930
  gdk_draw_line(window, border_gc,
 
931
                xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1,
 
932
                xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
 
933
}        /* end p_levels_draw_slider */
 
934
 
 
935
static void
 
936
p_levels_erase_slider (GdkWindow *window,
 
937
                       gint       xpos)
 
938
{
 
939
  gdk_window_clear_area (window, xpos - (CONTROL_HEIGHT - 1) / 2, 0,
 
940
                         CONTROL_HEIGHT - 1, CONTROL_HEIGHT);
 
941
}        /* end p_levels_erase_slider */
 
942
 
 
943
static void
 
944
p_smp_get_colors (GtkWidget *dialog)
 
945
{
 
946
  gint   i;
 
947
  guchar buffer[3 * DA_WIDTH * GRADIENT_HEIGHT];
 
948
 
 
949
  p_update_preview (&g_values.sample_id);
 
950
 
 
951
  if (dialog)
 
952
    {
 
953
      if (p_main_colorize (MC_GET_SAMPLE_COLORS) >= 0)  /* do not colorize, just analyze sample colors */
 
954
        {
 
955
          gtk_dialog_set_response_sensitive (GTK_DIALOG (g_di.dialog),
 
956
                                             GTK_RESPONSE_APPLY, TRUE);
 
957
        }
 
958
    }
 
959
  for (i = 0; i < GRADIENT_HEIGHT; i++)
 
960
    {
 
961
      memcpy (buffer+i*3*DA_WIDTH, g_sample_color_tab, 3*DA_WIDTH);
 
962
    }
 
963
  p_update_preview (&g_values.dst_id);
 
964
 
 
965
  gimp_preview_area_draw (GIMP_PREVIEW_AREA (g_di.sample_colortab_preview),
 
966
                          0, 0, DA_WIDTH, GRADIENT_HEIGHT,
 
967
                          GIMP_RGB_IMAGE,
 
968
                          buffer,
 
969
                          DA_WIDTH * 3);
 
970
}
 
971
 
 
972
 
 
973
static void
 
974
p_levels_update (gint update)
 
975
{
 
976
  gint i;
 
977
 
 
978
  if(g_Sdebug)  printf("p_levels_update: update reques %x\n", update);
 
979
 
 
980
  /*  Recalculate the transfer array  */
 
981
  p_calculate_level_transfers();
 
982
  if (update & REFRESH_DST)
 
983
    {
 
984
      p_refresh_dst_preview(g_di.dst_preview,  &g_dst_preview_buffer[0]);
 
985
    }
 
986
 
 
987
  /* update the spinbutton entry widgets */
 
988
  if (update & LOW_INPUT)
 
989
    {
 
990
      gtk_adjustment_set_value (g_di.adj_lvl_in_min,
 
991
                                g_values.lvl_in_min);
 
992
    }
 
993
  if (update & GAMMA)
 
994
    {
 
995
      gtk_adjustment_set_value (g_di.adj_lvl_in_gamma,
 
996
                                g_values.lvl_in_gamma);
 
997
    }
 
998
  if (update & HIGH_INPUT)
 
999
    {
 
1000
      gtk_adjustment_set_value (g_di.adj_lvl_in_max,
 
1001
                                g_values.lvl_in_max);
 
1002
    }
 
1003
  if (update & LOW_OUTPUT)
 
1004
    {
 
1005
      gtk_adjustment_set_value (g_di.adj_lvl_out_min,
 
1006
                                g_values.lvl_out_min);
 
1007
    }
 
1008
  if (update & HIGH_OUTPUT)
 
1009
    {
 
1010
      gtk_adjustment_set_value (g_di.adj_lvl_out_max,
 
1011
                                g_values.lvl_out_max);
 
1012
    }
 
1013
  if (update & INPUT_LEVELS)
 
1014
    {
 
1015
      guchar buffer[DA_WIDTH * GRADIENT_HEIGHT];
 
1016
      for (i = 0; i < GRADIENT_HEIGHT; i++)
 
1017
        {
 
1018
          memcpy (buffer+DA_WIDTH*i, g_lvl_trans_tab, DA_WIDTH);
 
1019
        }
 
1020
      gimp_preview_area_draw (GIMP_PREVIEW_AREA (g_di.in_lvl_gray_preview),
 
1021
                              0, 0, DA_WIDTH, GRADIENT_HEIGHT,
 
1022
                              GIMP_GRAY_IMAGE,
 
1023
                              buffer,
 
1024
                              DA_WIDTH);
 
1025
    }
 
1026
 
 
1027
  if (update & INPUT_SLIDERS)
 
1028
    {
 
1029
      gdouble width, mid, tmp;
 
1030
 
 
1031
      p_levels_erase_slider (g_di.in_lvl_drawarea->window, g_di.slider_pos[0]);
 
1032
      p_levels_erase_slider (g_di.in_lvl_drawarea->window, g_di.slider_pos[1]);
 
1033
      p_levels_erase_slider (g_di.in_lvl_drawarea->window, g_di.slider_pos[2]);
 
1034
 
 
1035
      g_di.slider_pos[0] = DA_WIDTH * ((double) g_values.lvl_in_min / 255.0);
 
1036
      g_di.slider_pos[2] = DA_WIDTH * ((double) g_values.lvl_in_max / 255.0);
 
1037
 
 
1038
      width = (double) (g_di.slider_pos[2] - g_di.slider_pos[0]) / 2.0;
 
1039
      mid = g_di.slider_pos[0] + width;
 
1040
      tmp = log10 (1.0 / g_values.lvl_in_gamma);
 
1041
      g_di.slider_pos[1] = (int) (mid + width * tmp + 0.5);
 
1042
 
 
1043
      p_levels_draw_slider (g_di.in_lvl_drawarea->window,
 
1044
                            g_di.in_lvl_drawarea->style->black_gc,
 
1045
                            g_di.in_lvl_drawarea->style->dark_gc[GTK_STATE_NORMAL],
 
1046
                            g_di.slider_pos[1]);
 
1047
      p_levels_draw_slider (g_di.in_lvl_drawarea->window,
 
1048
                            g_di.in_lvl_drawarea->style->black_gc,
 
1049
                            g_di.in_lvl_drawarea->style->black_gc,
 
1050
                            g_di.slider_pos[0]);
 
1051
      p_levels_draw_slider (g_di.in_lvl_drawarea->window,
 
1052
                            g_di.in_lvl_drawarea->style->black_gc,
 
1053
                            g_di.in_lvl_drawarea->style->white_gc,
 
1054
                            g_di.slider_pos[2]);
 
1055
    }
 
1056
 
 
1057
  if (update & OUTPUT_SLIDERS)
 
1058
    {
 
1059
      p_levels_erase_slider (g_di.sample_drawarea->window, g_di.slider_pos[3]);
 
1060
      p_levels_erase_slider (g_di.sample_drawarea->window, g_di.slider_pos[4]);
 
1061
 
 
1062
      g_di.slider_pos[3] = DA_WIDTH * ((double) g_values.lvl_out_min / 255.0);
 
1063
      g_di.slider_pos[4] = DA_WIDTH * ((double) g_values.lvl_out_max / 255.0);
 
1064
 
 
1065
      p_levels_draw_slider (g_di.sample_drawarea->window,
 
1066
                            g_di.sample_drawarea->style->black_gc,
 
1067
                            g_di.sample_drawarea->style->black_gc,
 
1068
                            g_di.slider_pos[3]);
 
1069
      p_levels_draw_slider (g_di.sample_drawarea->window,
 
1070
                            g_di.sample_drawarea->style->black_gc,
 
1071
                            g_di.sample_drawarea->style->black_gc,
 
1072
                            g_di.slider_pos[4]);
 
1073
    }
 
1074
}        /* end p_levels_update */
 
1075
 
 
1076
static gboolean
 
1077
p_level_in_events (GtkWidget *widget,
 
1078
                   GdkEvent  *event,
 
1079
                   gpointer   data)
 
1080
{
 
1081
  GdkEventButton *bevent;
 
1082
  GdkEventMotion *mevent;
 
1083
  gchar text[20];
 
1084
  double width, mid, tmp;
 
1085
  gint x, distance;
 
1086
  gint i;
 
1087
  gint update = FALSE;
 
1088
 
 
1089
 
 
1090
  switch (event->type)
 
1091
    {
 
1092
    case GDK_EXPOSE:
 
1093
      if(g_Sdebug) printf("EVENT: GDK_EXPOSE\n");
 
1094
      if (widget == g_di.in_lvl_drawarea)
 
1095
        p_levels_update (INPUT_SLIDERS);
 
1096
      break;
 
1097
 
 
1098
    case GDK_BUTTON_PRESS:
 
1099
      if(g_Sdebug) printf("EVENT: GDK_BUTTON_PRESS\n");
 
1100
      gtk_grab_add (widget);
 
1101
      bevent = (GdkEventButton *) event;
 
1102
 
 
1103
      distance = G_MAXINT;
 
1104
      for (i = 0; i < 3; i++)
 
1105
        {
 
1106
          if (fabs (bevent->x - g_di.slider_pos[i]) < distance)
 
1107
            {
 
1108
              g_di.active_slider = i;
 
1109
              distance = fabs (bevent->x - g_di.slider_pos[i]);
 
1110
            }
 
1111
        }
 
1112
 
 
1113
      x = bevent->x;
 
1114
      update = TRUE;
 
1115
      break;
 
1116
 
 
1117
    case GDK_BUTTON_RELEASE:
 
1118
      if(g_Sdebug) printf("EVENT: GDK_BUTTON_RELEASE\n");
 
1119
      gtk_grab_remove (widget);
 
1120
      switch (g_di.active_slider)
 
1121
        {
 
1122
        case 0:  /*  low input  */
 
1123
          p_levels_update (LOW_INPUT | GAMMA | DRAW);
 
1124
          break;
 
1125
        case 1:  /*  gamma  */
 
1126
          p_levels_update (GAMMA);
 
1127
          break;
 
1128
        case 2:  /*  high input  */
 
1129
          p_levels_update (HIGH_INPUT | GAMMA | DRAW);
 
1130
          break;
 
1131
        }
 
1132
 
 
1133
      p_refresh_dst_preview(g_di.dst_preview,  &g_dst_preview_buffer[0]);
 
1134
      break;
 
1135
 
 
1136
    case GDK_MOTION_NOTIFY:
 
1137
      if(g_Sdebug) printf("EVENT: GDK_MOTION_NOTIFY\n");
 
1138
      mevent = (GdkEventMotion *) event;
 
1139
      gdk_window_get_pointer (widget->window, &x, NULL, NULL);
 
1140
      update = TRUE;
 
1141
      break;
 
1142
 
 
1143
    default:
 
1144
      if(g_Sdebug)  printf("EVENT: default\n");
 
1145
      break;
 
1146
    }
 
1147
 
 
1148
  if (update)
 
1149
    {
 
1150
      if(g_Sdebug)  printf("EVENT: ** update **\n");
 
1151
      switch (g_di.active_slider)
 
1152
        {
 
1153
        case 0:  /*  low input  */
 
1154
          g_values.lvl_in_min = ((double) x / (double) DA_WIDTH) * 255.0;
 
1155
          g_values.lvl_in_min = CLAMP (g_values.lvl_in_min,
 
1156
                                       0, g_values.lvl_in_max);
 
1157
          break;
 
1158
 
 
1159
        case 1:  /*  gamma  */
 
1160
          width = (double) (g_di.slider_pos[2] - g_di.slider_pos[0]) / 2.0;
 
1161
          mid = g_di.slider_pos[0] + width;
 
1162
 
 
1163
          x = CLAMP (x, g_di.slider_pos[0], g_di.slider_pos[2]);
 
1164
          tmp = (double) (x - mid) / width;
 
1165
          g_values.lvl_in_gamma = 1.0 / pow (10, tmp);
 
1166
 
 
1167
          /*  round the gamma value to the nearest 1/100th  */
 
1168
          sprintf (text, "%2.2f", g_values.lvl_in_gamma);
 
1169
          g_values.lvl_in_gamma = atof (text);
 
1170
          break;
 
1171
 
 
1172
        case 2:  /*  high input  */
 
1173
          g_values.lvl_in_max = ((double) x / (double) DA_WIDTH) * 255.0;
 
1174
          g_values.lvl_in_max = CLAMP (g_values.lvl_in_max,
 
1175
                                       g_values.lvl_in_min, 255);
 
1176
          break;
 
1177
        }
 
1178
 
 
1179
      p_levels_update (INPUT_SLIDERS | INPUT_LEVELS | DRAW);
 
1180
    }
 
1181
 
 
1182
  return FALSE;
 
1183
}        /* end p_level_in_events */
 
1184
 
 
1185
static gboolean
 
1186
p_level_out_events (GtkWidget *widget,
 
1187
                    GdkEvent  *event,
 
1188
                    gpointer   data)
 
1189
{
 
1190
  GdkEventButton *bevent;
 
1191
  GdkEventMotion *mevent;
 
1192
  gint x, distance;
 
1193
  gint i;
 
1194
  gint update = FALSE;
 
1195
 
 
1196
  switch (event->type)
 
1197
    {
 
1198
    case GDK_EXPOSE:
 
1199
      if(g_Sdebug) printf("OUT_EVENT: GDK_EXPOSE\n");
 
1200
      if (widget == g_di.sample_drawarea)
 
1201
        p_levels_update (OUTPUT_SLIDERS);
 
1202
      break;
 
1203
 
 
1204
    case GDK_BUTTON_PRESS:
 
1205
      if(g_Sdebug) printf("OUT_EVENT: GDK_BUTTON_PRESS\n");
 
1206
      bevent = (GdkEventButton *) event;
 
1207
 
 
1208
      distance = G_MAXINT;
 
1209
      for (i = 3; i < 5; i++)
 
1210
        {
 
1211
          if (fabs (bevent->x - g_di.slider_pos[i]) < distance)
 
1212
            {
 
1213
              g_di.active_slider = i;
 
1214
              distance = fabs (bevent->x - g_di.slider_pos[i]);
 
1215
            }
 
1216
        }
 
1217
 
 
1218
      x = bevent->x;
 
1219
      update = TRUE;
 
1220
      break;
 
1221
 
 
1222
    case GDK_BUTTON_RELEASE:
 
1223
      if(g_Sdebug) printf("OUT_EVENT: GDK_BUTTON_RELEASE\n");
 
1224
      switch (g_di.active_slider)
 
1225
        {
 
1226
        case 3:  /*  low output  */
 
1227
          p_levels_update (LOW_OUTPUT | DRAW);
 
1228
          break;
 
1229
        case 4:  /*  high output  */
 
1230
          p_levels_update (HIGH_OUTPUT | DRAW);
 
1231
          break;
 
1232
        }
 
1233
 
 
1234
      p_refresh_dst_preview(g_di.dst_preview,  &g_dst_preview_buffer[0]);
 
1235
      break;
 
1236
 
 
1237
    case GDK_MOTION_NOTIFY:
 
1238
      if(g_Sdebug) printf("OUT_EVENT: GDK_MOTION_NOTIFY\n");
 
1239
      mevent = (GdkEventMotion *) event;
 
1240
      gdk_window_get_pointer (widget->window, &x, NULL, NULL);
 
1241
      update = TRUE;
 
1242
      break;
 
1243
 
 
1244
    default:
 
1245
      if(g_Sdebug)  printf("OUT_EVENT: default\n");
 
1246
     break;
 
1247
    }
 
1248
 
 
1249
  if (update)
 
1250
    {
 
1251
      if(g_Sdebug)  printf("OUT_EVENT: ** update **\n");
 
1252
      switch (g_di.active_slider)
 
1253
        {
 
1254
        case 3:  /*  low output  */
 
1255
          g_values.lvl_out_min = ((double) x / (double) DA_WIDTH) * 255.0;
 
1256
          g_values.lvl_out_min = CLAMP (g_values.lvl_out_min,
 
1257
                                       0, g_values.lvl_out_max);
 
1258
          break;
 
1259
 
 
1260
        case 4:  /*  high output  */
 
1261
          g_values.lvl_out_max = ((double) x / (double) DA_WIDTH) * 255.0;
 
1262
          g_values.lvl_out_max = CLAMP (g_values.lvl_out_max,
 
1263
                                       g_values.lvl_out_min, 255);
 
1264
          break;
 
1265
        }
 
1266
 
 
1267
      p_levels_update (OUTPUT_SLIDERS | OUTPUT_LEVELS | DRAW);
 
1268
    }
 
1269
 
 
1270
  return FALSE;
 
1271
}        /* end p_level_out_events */
 
1272
 
 
1273
 
 
1274
/* ============================================================================
 
1275
 * p_smp_dialog
 
1276
 *        The Interactive Dialog
 
1277
 * ============================================================================
 
1278
 */
 
1279
static void
 
1280
p_smp_dialog (void)
 
1281
{
 
1282
  GtkWidget *dialog;
 
1283
  GtkWidget *hbox;
 
1284
  GtkWidget *vbox2;
 
1285
  GtkWidget *frame;
 
1286
  GtkWidget *table;
 
1287
  GtkWidget *check_button;
 
1288
  GtkWidget *label;
 
1289
  GtkWidget *combo;
 
1290
  GtkWidget *spinbutton;
 
1291
  GtkObject *data;
 
1292
  gint       l_ty;
 
1293
 
 
1294
  /* set flags for check buttons from mode value bits */
 
1295
  if (g_Sdebug) g_print ("p_smp_dialog START\n");
 
1296
 
 
1297
  /* init some dialog variables */
 
1298
  g_di.enable_preview_update = FALSE;
 
1299
  g_di.sample_show_selection = TRUE;
 
1300
  g_di.dst_show_selection    = TRUE;
 
1301
  g_di.dst_show_color        = TRUE;
 
1302
  g_di.sample_show_color     = TRUE;
 
1303
  g_di.orig_inten_button     = NULL;
 
1304
 
 
1305
  /* Init GTK  */
 
1306
  gimp_ui_init ("sample_colorize", TRUE);
 
1307
 
 
1308
  /* Main Dialog */
 
1309
  g_di.dialog = dialog =
 
1310
    gimp_dialog_new (_("Sample Colorize"), "sample_colorize",
 
1311
                     NULL, 0,
 
1312
                     gimp_standard_help_func, HELP_ID,
 
1313
 
 
1314
                     GIMP_STOCK_RESET,       RESPONSE_RESET,
 
1315
                     _("Get sample colors"), RESPONSE_GET_COLORS,
 
1316
                     GTK_STOCK_CLOSE,        GTK_RESPONSE_CLOSE,
 
1317
                     _("Apply"),             GTK_RESPONSE_APPLY,
 
1318
 
 
1319
                     NULL);
 
1320
 
 
1321
  g_signal_connect (dialog, "response",
 
1322
                    G_CALLBACK (p_smp_response_callback),
 
1323
                    dialog);
 
1324
 
 
1325
  /* table for values */
 
1326
  table = gtk_table_new (7, 5, FALSE);
 
1327
  gtk_table_set_row_spacings (GTK_TABLE (table), 12);
 
1328
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
 
1329
  gtk_container_set_border_width (GTK_CONTAINER (table), 12);
 
1330
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
 
1331
                      table, TRUE, TRUE, 0);
 
1332
 
 
1333
  l_ty = 0;
 
1334
  /* layer combo_box (Dst) */
 
1335
  label = gtk_label_new (_("Destination:"));
 
1336
  gtk_misc_set_alignment (GTK_MISC(label), 1.0, 0.5);
 
1337
  gtk_table_attach (GTK_TABLE (table), label, 0, 1, l_ty, l_ty + 1,
 
1338
                    GTK_FILL, GTK_FILL, 4, 0);
 
1339
  gtk_widget_show (label);
 
1340
 
 
1341
  combo = gimp_layer_combo_box_new (p_smp_constrain, NULL);
 
1342
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), g_values.dst_id,
 
1343
                              G_CALLBACK (p_smp_dest_combo_callback),
 
1344
                              NULL);
 
1345
 
 
1346
  gtk_table_attach (GTK_TABLE (table), combo, 1, 2, l_ty, l_ty + 1,
 
1347
                    GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
 
1348
  gtk_widget_show (combo);
 
1349
 
 
1350
  /* layer combo_box (Sample) */
 
1351
  label = gtk_label_new (_("Sample:"));
 
1352
  gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
 
1353
  gtk_table_attach (GTK_TABLE (table), label, 3, 4, l_ty, l_ty + 1,
 
1354
                    GTK_FILL, GTK_FILL, 4, 0);
 
1355
  gtk_widget_show (label);
 
1356
 
 
1357
  combo = gimp_layer_combo_box_new (p_smp_constrain, NULL);
 
1358
 
 
1359
  gimp_int_combo_box_prepend (GIMP_INT_COMBO_BOX (combo),
 
1360
                              GIMP_INT_STORE_VALUE,    SMP_INV_GRADIENT,
 
1361
                              GIMP_INT_STORE_LABEL,    _("From reverse gradient"),
 
1362
                              GIMP_INT_STORE_STOCK_ID, GIMP_STOCK_GRADIENT,
 
1363
                              -1);
 
1364
  gimp_int_combo_box_prepend (GIMP_INT_COMBO_BOX (combo),
 
1365
                              GIMP_INT_STORE_VALUE,    SMP_GRADIENT,
 
1366
                              GIMP_INT_STORE_LABEL,    _("From gradient"),
 
1367
                              GIMP_INT_STORE_STOCK_ID, GIMP_STOCK_GRADIENT,
 
1368
                              -1);
 
1369
 
 
1370
  gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), g_values.sample_id,
 
1371
                              G_CALLBACK (p_smp_sample_combo_callback),
 
1372
                              NULL);
 
1373
 
 
1374
  gtk_table_attach (GTK_TABLE (table), combo, 4, 5, l_ty, l_ty + 1,
 
1375
                    GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
 
1376
  gtk_widget_show (combo);
 
1377
 
 
1378
  l_ty++;
 
1379
 
 
1380
 
 
1381
  hbox = gtk_hbox_new (FALSE, 6);
 
1382
  gtk_table_attach (GTK_TABLE (table), hbox, 0, 2, l_ty, l_ty + 1,
 
1383
                    GTK_FILL, 0, 0, 0);
 
1384
  gtk_widget_show (hbox);
 
1385
 
 
1386
  /* check button */
 
1387
  check_button = gtk_check_button_new_with_label (_("Show selection"));
 
1388
  gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
 
1389
  gtk_widget_show (check_button);
 
1390
 
 
1391
  g_signal_connect (check_button, "toggled",
 
1392
                    G_CALLBACK (p_smp_toggle_callback),
 
1393
                    &g_di.dst_show_selection);
 
1394
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
 
1395
                                g_di.dst_show_selection);
 
1396
 
 
1397
  /* check button */
 
1398
  check_button = gtk_check_button_new_with_label (_("Show color"));
 
1399
  gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
 
1400
  gtk_widget_show (check_button);
 
1401
 
 
1402
  g_signal_connect (check_button, "toggled",
 
1403
                    G_CALLBACK (p_smp_toggle_callback),
 
1404
                    &g_di.dst_show_color);
 
1405
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
 
1406
                                g_di.dst_show_color);
 
1407
 
 
1408
  hbox = gtk_hbox_new (FALSE, 6);
 
1409
  gtk_table_attach (GTK_TABLE (table), hbox, 3, 5, l_ty, l_ty + 1,
 
1410
                    GTK_FILL, 0, 0, 0);
 
1411
  gtk_widget_show (hbox);
 
1412
 
 
1413
  /* check button */
 
1414
  check_button = gtk_check_button_new_with_label (_("Show selection"));
 
1415
  gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
 
1416
  gtk_widget_show (check_button);
 
1417
 
 
1418
  g_signal_connect (check_button, "toggled",
 
1419
                    (GtkSignalFunc)p_smp_toggle_callback ,
 
1420
                    &g_di.sample_show_selection);
 
1421
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
 
1422
                                g_di.sample_show_selection);
 
1423
 
 
1424
  /* check button */
 
1425
  check_button = gtk_check_button_new_with_label (_("Show color"));
 
1426
  gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
 
1427
  gtk_widget_show (check_button);
 
1428
 
 
1429
  g_signal_connect (check_button, "toggled",
 
1430
                    (GtkSignalFunc)p_smp_toggle_callback ,
 
1431
                    &g_di.sample_show_color);
 
1432
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
 
1433
                                g_di.sample_show_color);
 
1434
 
 
1435
  l_ty++;
 
1436
 
 
1437
  /* Preview (Dst) */
 
1438
 
 
1439
  frame = gtk_frame_new (NULL);
 
1440
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
 
1441
  gtk_table_attach (GTK_TABLE (table),
 
1442
                    frame, 0, 2, l_ty, l_ty + 1, 0, 0, 0, 0);
 
1443
  gtk_widget_show (frame);
 
1444
 
 
1445
  g_di.dst_preview = gimp_preview_area_new ();
 
1446
  gtk_widget_set_size_request (g_di.dst_preview,
 
1447
                               PREVIEW_SIZE_X, PREVIEW_SIZE_Y);
 
1448
  gtk_container_add (GTK_CONTAINER (frame), g_di.dst_preview);
 
1449
  gtk_widget_show (g_di.dst_preview);
 
1450
 
 
1451
  /* Preview (Sample)*/
 
1452
 
 
1453
  frame = gtk_frame_new (NULL);
 
1454
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
 
1455
  gtk_table_attach (GTK_TABLE (table),
 
1456
                    frame, 3, 5, l_ty, l_ty + 1, 0, 0, 0, 0);
 
1457
  gtk_widget_show (frame);
 
1458
 
 
1459
  g_di.sample_preview = gimp_preview_area_new ();
 
1460
  gtk_widget_set_size_request (g_di.sample_preview,
 
1461
                               PREVIEW_SIZE_X, PREVIEW_SIZE_Y);
 
1462
  gtk_container_add (GTK_CONTAINER (frame), g_di.sample_preview);
 
1463
  gtk_widget_show (g_di.sample_preview);
 
1464
 
 
1465
  l_ty++;
 
1466
 
 
1467
  /*  The levels graylevel prevev  */
 
1468
  frame = gtk_frame_new (NULL);
 
1469
 
 
1470
  vbox2 = gtk_vbox_new (FALSE, 2);
 
1471
  gtk_container_add (GTK_CONTAINER (frame), vbox2);
 
1472
  gtk_table_attach (GTK_TABLE (table),
 
1473
                    frame, 0, 2, l_ty, l_ty + 1, 0, 0, 0, 0);
 
1474
 
 
1475
  g_di.in_lvl_gray_preview = gimp_preview_area_new ();
 
1476
  gtk_widget_set_size_request (g_di.in_lvl_gray_preview,
 
1477
                               DA_WIDTH, GRADIENT_HEIGHT);
 
1478
  gtk_widget_set_events (g_di.in_lvl_gray_preview, LEVELS_DA_MASK);
 
1479
  gtk_box_pack_start (GTK_BOX (vbox2), g_di.in_lvl_gray_preview, FALSE, TRUE, 0);
 
1480
  gtk_widget_show (g_di.in_lvl_gray_preview);
 
1481
 
 
1482
  g_signal_connect (g_di.in_lvl_gray_preview, "event",
 
1483
                    G_CALLBACK (p_level_in_events),
 
1484
                    &g_di);
 
1485
 
 
1486
  /*  The levels drawing area  */
 
1487
  g_di.in_lvl_drawarea = gtk_drawing_area_new ();
 
1488
  gtk_widget_set_size_request (g_di.in_lvl_drawarea,
 
1489
                               DA_WIDTH, CONTROL_HEIGHT);
 
1490
  gtk_widget_set_events (g_di.in_lvl_drawarea, LEVELS_DA_MASK);
 
1491
  gtk_box_pack_start (GTK_BOX (vbox2), g_di.in_lvl_drawarea, FALSE, TRUE, 0);
 
1492
  gtk_widget_show (g_di.in_lvl_drawarea);
 
1493
 
 
1494
  g_signal_connect (g_di.in_lvl_drawarea, "event",
 
1495
                    G_CALLBACK (p_level_in_events),
 
1496
                    &g_di);
 
1497
 
 
1498
  gtk_widget_show(vbox2);
 
1499
  gtk_widget_show(frame);
 
1500
 
 
1501
  /*  The sample_colortable prevev  */
 
1502
  frame = gtk_frame_new (NULL);
 
1503
 
 
1504
  vbox2 = gtk_vbox_new (FALSE, 2);
 
1505
  gtk_container_add (GTK_CONTAINER (frame), vbox2);
 
1506
  gtk_table_attach (GTK_TABLE (table),
 
1507
                    frame, 3, 5, l_ty, l_ty + 1, 0, 0, 0, 0);
 
1508
 
 
1509
  g_di.sample_colortab_preview = gimp_preview_area_new ();
 
1510
  gtk_widget_set_size_request (g_di.sample_colortab_preview,
 
1511
                               DA_WIDTH, GRADIENT_HEIGHT);
 
1512
  gtk_box_pack_start (GTK_BOX (vbox2), g_di.sample_colortab_preview, FALSE, TRUE, 0);
 
1513
  gtk_widget_show (g_di.sample_colortab_preview);
 
1514
 
 
1515
  /*  The levels drawing area  */
 
1516
  g_di.sample_drawarea = gtk_drawing_area_new ();
 
1517
  gtk_widget_set_size_request (g_di.sample_drawarea,
 
1518
                               DA_WIDTH, CONTROL_HEIGHT);
 
1519
  gtk_widget_set_events (g_di.sample_drawarea, LEVELS_DA_MASK);
 
1520
  gtk_box_pack_start (GTK_BOX (vbox2), g_di.sample_drawarea, FALSE, TRUE, 0);
 
1521
  gtk_widget_show (g_di.sample_drawarea);
 
1522
 
 
1523
  g_signal_connect (g_di.sample_drawarea, "event",
 
1524
                    G_CALLBACK (p_level_out_events),
 
1525
                    &g_di);
 
1526
 
 
1527
  gtk_widget_show(vbox2);
 
1528
  gtk_widget_show(frame);
 
1529
 
 
1530
 
 
1531
  l_ty++;
 
1532
 
 
1533
  /*  Horizontal box for INPUT levels text widget  */
 
1534
  hbox = gtk_hbox_new (TRUE, 6);
 
1535
  gtk_table_attach (GTK_TABLE (table), hbox, 0, 2, l_ty, l_ty+1,
 
1536
                    GTK_FILL, 0, 0, 0);
 
1537
 
 
1538
  label = gtk_label_new (_("Input levels:"));
 
1539
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
1540
  gtk_widget_show (label);
 
1541
 
 
1542
  /* min input spinbutton */
 
1543
  data = gtk_adjustment_new ((gfloat)g_values.lvl_in_min, 0.0, 254.0, 1, 10, 10);
 
1544
  g_di.adj_lvl_in_min = GTK_ADJUSTMENT (data);
 
1545
 
 
1546
  spinbutton = gtk_spin_button_new (g_di.adj_lvl_in_min, 0.5, 0);
 
1547
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
 
1548
  gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
 
1549
  gtk_widget_show (spinbutton);
 
1550
 
 
1551
  g_signal_connect (g_di.adj_lvl_in_min, "value_changed",
 
1552
                    G_CALLBACK (p_smp_adj_lvl_in_min_upd_callback),
 
1553
                    &g_di);
 
1554
 
 
1555
  /* input gamma spinbutton */
 
1556
  data = gtk_adjustment_new ((gfloat)g_values.lvl_in_gamma, 0.1, 10.0, 0.02, 0.2, 0.2);
 
1557
  g_di.adj_lvl_in_gamma = GTK_ADJUSTMENT (data);
 
1558
 
 
1559
  spinbutton = gtk_spin_button_new (g_di.adj_lvl_in_gamma, 0.5, 2);
 
1560
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
 
1561
  gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
 
1562
  gtk_widget_show (spinbutton);
 
1563
 
 
1564
  g_signal_connect (g_di.adj_lvl_in_gamma, "value_changed",
 
1565
                    G_CALLBACK (p_smp_text_gamma_upd_callback),
 
1566
                    &g_di);
 
1567
 
 
1568
  /* high input spinbutton */
 
1569
  data = gtk_adjustment_new ((gfloat)g_values.lvl_in_max, 1.0, 255.0, 1, 10, 10);
 
1570
  g_di.adj_lvl_in_max = GTK_ADJUSTMENT (data);
 
1571
 
 
1572
  spinbutton = gtk_spin_button_new (g_di.adj_lvl_in_max, 0.5, 0);
 
1573
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
 
1574
  gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
 
1575
  gtk_widget_show (spinbutton);
 
1576
 
 
1577
  g_signal_connect (g_di.adj_lvl_in_max, "value_changed",
 
1578
                    G_CALLBACK (p_smp_adj_lvl_in_max_upd_callback),
 
1579
                    &g_di);
 
1580
 
 
1581
  gtk_widget_show (hbox);
 
1582
 
 
1583
  /*  Horizontal box for OUTPUT levels text widget  */
 
1584
  hbox = gtk_hbox_new (TRUE, 4);
 
1585
  gtk_table_attach (GTK_TABLE (table), hbox, 3, 5, l_ty, l_ty+1,
 
1586
                    GTK_FILL, 0, 0, 0);
 
1587
 
 
1588
  label = gtk_label_new (_("Output Levels:"));
 
1589
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
1590
  gtk_widget_show (label);
 
1591
 
 
1592
  /*  min output spinbutton */
 
1593
  data = gtk_adjustment_new ((gfloat)g_values.lvl_out_min, 0.0, 254.0, 1, 10, 10);
 
1594
  g_di.adj_lvl_out_min = GTK_ADJUSTMENT (data);
 
1595
 
 
1596
  spinbutton = gtk_spin_button_new (g_di.adj_lvl_out_min, 0.5, 0);
 
1597
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
 
1598
  gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
 
1599
  gtk_widget_show (spinbutton);
 
1600
 
 
1601
  g_signal_connect (g_di.adj_lvl_out_min, "value_changed",
 
1602
                    G_CALLBACK (p_smp_adj_lvl_out_min_upd_callback),
 
1603
                    &g_di);
 
1604
 
 
1605
  /* high output spinbutton */
 
1606
  data = gtk_adjustment_new ((gfloat)g_values.lvl_out_max, 0.0, 255.0, 1, 10, 10);
 
1607
  g_di.adj_lvl_out_max = GTK_ADJUSTMENT (data);
 
1608
 
 
1609
  spinbutton = gtk_spin_button_new (g_di.adj_lvl_out_max, 0.5, 0);
 
1610
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
 
1611
  gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
 
1612
  gtk_widget_show (spinbutton);
 
1613
 
 
1614
  g_signal_connect (g_di.adj_lvl_out_max, "value_changed",
 
1615
                    G_CALLBACK (p_smp_adj_lvl_out_max_upd_callback),
 
1616
                    &g_di);
 
1617
 
 
1618
  gtk_widget_show (hbox);
 
1619
 
 
1620
  l_ty++;
 
1621
 
 
1622
  hbox = gtk_hbox_new (FALSE, 6);
 
1623
  gtk_table_attach (GTK_TABLE (table), hbox, 0, 2, l_ty, l_ty+1,
 
1624
                    GTK_FILL, 0, 0, 0);
 
1625
  gtk_widget_show (hbox);
 
1626
 
 
1627
  /* check button */
 
1628
  check_button = gtk_check_button_new_with_label (_("Hold intensity"));
 
1629
  gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
 
1630
  gtk_widget_show (check_button);
 
1631
 
 
1632
  g_signal_connect (check_button, "toggled",
 
1633
                    G_CALLBACK (p_smp_toggle_callback),
 
1634
                    &g_values.hold_inten);
 
1635
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
 
1636
                                g_values.hold_inten);
 
1637
 
 
1638
  /* check button */
 
1639
  check_button = gtk_check_button_new_with_label (_("Original intensity"));
 
1640
  g_di.orig_inten_button = check_button;
 
1641
  gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
 
1642
  gtk_widget_set_sensitive (g_di.orig_inten_button, g_values.hold_inten);
 
1643
  gtk_widget_show (check_button);
 
1644
 
 
1645
  g_signal_connect (check_button, "toggled",
 
1646
                    G_CALLBACK (p_smp_toggle_callback),
 
1647
                    &g_values.orig_inten);
 
1648
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
 
1649
                                g_values.orig_inten);
 
1650
 
 
1651
  hbox = gtk_hbox_new (FALSE, 4);
 
1652
  gtk_table_attach (GTK_TABLE (table), hbox, 3, 5, l_ty, l_ty+1,
 
1653
                    GTK_FILL, 0, 0, 0);
 
1654
  gtk_widget_show (hbox);
 
1655
 
 
1656
  /* check button */
 
1657
  check_button = gtk_check_button_new_with_label (_("Use subcolors"));
 
1658
  gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
 
1659
  gtk_widget_show (check_button);
 
1660
 
 
1661
  g_signal_connect (check_button, "toggled",
 
1662
                    G_CALLBACK (p_smp_toggle_callback),
 
1663
                    &g_values.rnd_subcolors);
 
1664
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
 
1665
                                g_values.rnd_subcolors);
 
1666
 
 
1667
  /* check button */
 
1668
  check_button = gtk_check_button_new_with_label (_("Smooth samples"));
 
1669
  gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
 
1670
  gtk_widget_show (check_button);
 
1671
 
 
1672
  g_signal_connect (check_button, "toggled",
 
1673
                    G_CALLBACK (p_smp_toggle_callback),
 
1674
                    &g_values.guess_missing);
 
1675
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
 
1676
                                g_values.guess_missing);
 
1677
 
 
1678
  l_ty++;
 
1679
 
 
1680
  gtk_widget_show (table);
 
1681
  gtk_widget_show (frame);
 
1682
 
 
1683
  gtk_widget_show (dialog);
 
1684
 
 
1685
  /* set old_id's different (to force updates of the previews) */
 
1686
  g_di.enable_preview_update = TRUE;
 
1687
  p_smp_get_colors (NULL);
 
1688
  p_update_preview (&g_values.dst_id);
 
1689
  p_levels_update (INPUT_SLIDERS | INPUT_LEVELS | DRAW);
 
1690
 
 
1691
  gtk_main ();
 
1692
}        /* end p_smp_dialog */
 
1693
 
 
1694
/* -----------------------------
 
1695
 * DEBUG print procedures START
 
1696
 * -----------------------------
 
1697
 */
 
1698
 
 
1699
static void
 
1700
p_print_ppm (const gchar *ppm_name)
 
1701
{
 
1702
  FILE *fp;
 
1703
  gint l_idx;
 
1704
  gint l_cnt;
 
1705
  gint l_r, l_g, l_b;
 
1706
  t_samp_color_elem *col_ptr;
 
1707
 
 
1708
  if (ppm_name == NULL)
 
1709
    return;
 
1710
 
 
1711
  fp = fopen (ppm_name, "w");
 
1712
  if(fp)
 
1713
    {
 
1714
      fprintf(fp, "P3\n# CREATOR: Gimp sample coloros\n256 256\n255\n");
 
1715
      for(l_idx = 0; l_idx < 256; l_idx++)
 
1716
        {
 
1717
          col_ptr = g_lum_tab[l_idx].col_ptr;
 
1718
 
 
1719
          for(l_cnt = 0; l_cnt < 256; l_cnt++)
 
1720
            {
 
1721
              l_r = l_g = l_b = 0;
 
1722
              if(col_ptr)
 
1723
                {
 
1724
                  if((col_ptr->sum_color > 0) && (l_cnt != 20))
 
1725
                    {
 
1726
                      l_r = (gint) col_ptr->color[0];
 
1727
                      l_g = (gint) col_ptr->color[1];
 
1728
                      l_b = (gint) col_ptr->color[2];
 
1729
                    }
 
1730
 
 
1731
                  if (l_cnt > 20) col_ptr = col_ptr->next;
 
1732
                }
 
1733
              fprintf(fp, "%d %d %d\n", l_r, l_g, l_b);
 
1734
            }
 
1735
        }
 
1736
      fclose(fp);
 
1737
    }
 
1738
}
 
1739
 
 
1740
static void
 
1741
p_print_color_list (FILE *fp, t_samp_color_elem *col_ptr)
 
1742
{
 
1743
  if (fp == NULL)
 
1744
    return;
 
1745
 
 
1746
  while(col_ptr)
 
1747
    {
 
1748
      fprintf (fp, "  RGBA: %03d %03d %03d %03d  sum: [%d]\n",
 
1749
               (gint)col_ptr->color[0],
 
1750
               (gint)col_ptr->color[1],
 
1751
               (gint)col_ptr->color[2],
 
1752
               (gint)col_ptr->color[3],
 
1753
               (gint)col_ptr->sum_color);
 
1754
 
 
1755
      col_ptr = col_ptr->next;
 
1756
    }
 
1757
}
 
1758
 
 
1759
static void
 
1760
p_print_table (FILE *fp)
 
1761
{
 
1762
  gint l_idx;
 
1763
 
 
1764
  if(fp == NULL) return;
 
1765
 
 
1766
  fprintf(fp, "---------------------------\n");
 
1767
  fprintf(fp, "p_print_table\n");
 
1768
  fprintf(fp, "---------------------------\n");
 
1769
 
 
1770
  for(l_idx = 0; l_idx < 256; l_idx++)
 
1771
  {
 
1772
    fprintf(fp, "LUM [%03d]  pixcount:%d\n", l_idx, (int)g_lum_tab[l_idx].all_samples);
 
1773
    p_print_color_list(fp, g_lum_tab[l_idx].col_ptr);
 
1774
  }
 
1775
}
 
1776
 
 
1777
static void
 
1778
p_print_transtable (FILE *fp)
 
1779
{
 
1780
  gint l_idx;
 
1781
 
 
1782
  if (fp == NULL)
 
1783
    return;
 
1784
 
 
1785
  fprintf(fp, "---------------------------\n");
 
1786
  fprintf(fp, "p_print_transtable\n");
 
1787
  fprintf(fp, "---------------------------\n");
 
1788
 
 
1789
  for(l_idx = 0; l_idx < 256; l_idx++)
 
1790
    {
 
1791
      fprintf(fp, "LVL_TRANS [%03d]  in_lvl: %3d  out_lvl: %3d\n",
 
1792
              l_idx, (int)g_lvl_trans_tab[l_idx], (int)g_out_trans_tab[l_idx]);
 
1793
    }
 
1794
}
 
1795
 
 
1796
static void
 
1797
p_print_values (FILE *fp)
 
1798
{
 
1799
  if (fp == NULL)
 
1800
    return;
 
1801
 
 
1802
  fprintf(fp, "sample_colorize: params\n");
 
1803
  fprintf(fp, "g_values.hold_inten     :%d\n", (int)g_values.hold_inten);
 
1804
  fprintf(fp, "g_values.orig_inten     :%d\n", (int)g_values.orig_inten);
 
1805
  fprintf(fp, "g_values.rnd_subcolors  :%d\n", (int)g_values.rnd_subcolors);
 
1806
  fprintf(fp, "g_values.guess_missing  :%d\n", (int)g_values.guess_missing);
 
1807
  fprintf(fp, "g_values.lvl_in_min     :%d\n", (int)g_values.lvl_in_min);
 
1808
  fprintf(fp, "g_values.lvl_in_max     :%d\n", (int)g_values.lvl_in_max);
 
1809
  fprintf(fp, "g_values.lvl_in_gamma   :%f\n", g_values.lvl_in_gamma);
 
1810
  fprintf(fp, "g_values.lvl_out_min    :%d\n", (int)g_values.lvl_out_min);
 
1811
  fprintf(fp, "g_values.lvl_out_max    :%d\n", (int)g_values.lvl_out_max);
 
1812
 
 
1813
  fprintf(fp, "g_values.tol_col_err    :%f\n", g_values.tol_col_err);
 
1814
}
 
1815
 
 
1816
/* -----------------------------
 
1817
 * DEBUG print procedures END
 
1818
 * -----------------------------
 
1819
 */
 
1820
 
 
1821
/* DEBUG: read values from file */
 
1822
static void
 
1823
p_get_filevalues (void)
 
1824
{
 
1825
  FILE *l_fp;
 
1826
  gchar  l_buf[1000];
 
1827
 
 
1828
/*
 
1829
  g_values.lvl_out_min = 0;
 
1830
  g_values.lvl_out_max = 255;
 
1831
  g_values.lvl_in_min = 0;
 
1832
  g_values.lvl_in_max = 255;
 
1833
  g_values.lvl_in_gamma = 1.0;
 
1834
*/
 
1835
  g_values.tol_col_err = 5.5;
 
1836
 
 
1837
  l_fp = fopen("sample_colorize.values", "r");
 
1838
  if (l_fp != NULL)
 
1839
    {
 
1840
      fgets(&l_buf[0], 999, l_fp);
 
1841
      sscanf (&l_buf[0], "%f", &g_values.tol_col_err);
 
1842
      fclose(l_fp);
 
1843
    }
 
1844
 
 
1845
  printf("g_values.tol_col_err    :%f\n", g_values.tol_col_err);
 
1846
}        /* end p_get_filevalues */
 
1847
 
 
1848
static gint32
 
1849
p_color_error (guchar ref_red, guchar ref_green, guchar ref_blue,
 
1850
               guchar cmp_red, guchar cmp_green, guchar cmp_blue)
 
1851
{
 
1852
  glong   l_ff;
 
1853
  glong   l_fs;
 
1854
  glong   cmp_h, ref_h;
 
1855
 
 
1856
  /* 1. Brightness differences */
 
1857
  cmp_h = (3 * cmp_red + 6 * cmp_green + cmp_blue) / 10;
 
1858
  ref_h = (3 * ref_red + 6 * ref_green + ref_blue) / 10;
 
1859
 
 
1860
  l_fs = abs(ref_h - cmp_h);
 
1861
  l_ff = l_fs * l_fs;
 
1862
 
 
1863
  /* 2. add Red Color differences */
 
1864
  l_fs = abs(ref_red - cmp_red);
 
1865
  l_ff += (l_fs * l_fs);
 
1866
 
 
1867
  /* 3. add  Green Color differences */
 
1868
  l_fs = abs(ref_green - cmp_green);
 
1869
  l_ff += (l_fs * l_fs);
 
1870
 
 
1871
  /* 4. add  Blue Color differences */
 
1872
  l_fs = abs(ref_blue - cmp_blue);
 
1873
  l_ff += (l_fs * l_fs);
 
1874
 
 
1875
  return((gint32)(l_ff));
 
1876
}        /* end p_color_error */
 
1877
 
 
1878
static void
 
1879
p_provide_tile (t_GDRW *gdrw,
 
1880
                gint    col,
 
1881
                gint    row,
 
1882
                gint    shadow)
 
1883
{
 
1884
  guchar  *ptr;
 
1885
  gint i;
 
1886
 
 
1887
  if ( col != gdrw->tile_col || row != gdrw->tile_row || !gdrw->tile )
 
1888
    {
 
1889
      if (gdrw->tile)
 
1890
        {
 
1891
          gimp_tile_unref (gdrw->tile, gdrw->tile_dirty);
 
1892
        }
 
1893
 
 
1894
      gdrw->tile_col = col;
 
1895
      gdrw->tile_row = row;
 
1896
      gdrw->tile = gimp_drawable_get_tile (gdrw->drawable, shadow,
 
1897
                                           gdrw->tile_row, gdrw->tile_col);
 
1898
      gdrw->tile_dirty = FALSE;
 
1899
      gimp_tile_ref (gdrw->tile);
 
1900
 
 
1901
      gdrw->tile_swapcount++;
 
1902
 
 
1903
      return;
 
1904
 
 
1905
      /* debug start */
 
1906
 
 
1907
      printf("\np_provide_tile: row: %d col: %d data:", (int)row, (int)col);
 
1908
 
 
1909
      ptr = gdrw->tile->data;
 
1910
      for (i = 0; i < 16; i++)
 
1911
        {
 
1912
          printf(" %d", (int)(*ptr));
 
1913
          ptr++;
 
1914
        }
 
1915
      printf("\n\n");
 
1916
 
 
1917
      /* debug stop */
 
1918
    }
 
1919
}        /* end p_provide_tile */
 
1920
 
 
1921
/* get pixel value
 
1922
 *   return light gray transparent pixel if out of bounds
 
1923
 *   (should occur in the previews only)
 
1924
 */
 
1925
static void
 
1926
p_get_pixel (t_GDRW *gdrw,
 
1927
             gint32  x,
 
1928
             gint32  y,
 
1929
             guchar *pixel)
 
1930
{
 
1931
  gint   row, col;
 
1932
  gint   offx, offy;
 
1933
  guchar  *ptr;
 
1934
 
 
1935
  if((x < 0)
 
1936
     || (x > gdrw->drawable->width   -1)
 
1937
     || (y < 0)
 
1938
     || (y > gdrw->drawable->height - 1))
 
1939
    {
 
1940
      pixel[0] = pixel[1] = pixel[2] = 200;
 
1941
      pixel[3] = 0;
 
1942
      return;
 
1943
    }
 
1944
 
 
1945
  col = x / gdrw->tile_width;
 
1946
  row = y / gdrw->tile_height;
 
1947
  offx = x % gdrw->tile_width;
 
1948
  offy = y % gdrw->tile_height;
 
1949
 
 
1950
  p_provide_tile (gdrw, col, row, gdrw->shadow);
 
1951
 
 
1952
  pixel[1] = pixel[3] = 0;  /* simulate full transparent alpha channel */
 
1953
  ptr = (gdrw->tile->data +
 
1954
         (((offy * gdrw->tile->ewidth) + offx) * gdrw->bpp));
 
1955
  memcpy (pixel, ptr, gdrw->bpp);
 
1956
 
 
1957
  return;
 
1958
 
 
1959
  printf("p_get_pixel: x: %d  y: %d bpp:%d RGBA:%d %d %d %d\n", (int)x, (int)y, (int)gdrw->bpp, (int)pixel[0], (int)pixel[1], (int)pixel[2], (int)pixel[3]);
 
1960
}
 
1961
 
 
1962
/* clear table */
 
1963
static void
 
1964
p_clear_tables (void)
 
1965
{
 
1966
  gint l_idx;
 
1967
 
 
1968
  for (l_idx = 0; l_idx < 256; l_idx++)
 
1969
    {
 
1970
      g_lum_tab[l_idx].col_ptr = NULL;
 
1971
      g_lum_tab[l_idx].all_samples = 0;
 
1972
      g_lvl_trans_tab[l_idx] = l_idx;
 
1973
      g_out_trans_tab[l_idx] = l_idx;
 
1974
      g_sample_color_tab[3 * l_idx + 0] = l_idx;
 
1975
      g_sample_color_tab[3 * l_idx + 1] = l_idx;
 
1976
      g_sample_color_tab[3 * l_idx + 2] = l_idx;
 
1977
    }
 
1978
}
 
1979
 
 
1980
/* free all allocated sample colors in table g_lum_tab */
 
1981
static void
 
1982
p_free_colors (void)
 
1983
{
 
1984
  gint l_lum;
 
1985
 
 
1986
  t_samp_color_elem *l_col_ptr;
 
1987
  t_samp_color_elem *l_next_ptr;
 
1988
 
 
1989
  for (l_lum = 0; l_lum < 256; l_lum++)
 
1990
    {
 
1991
      for (l_col_ptr = g_lum_tab[l_lum].col_ptr;
 
1992
           l_col_ptr != NULL;
 
1993
           l_col_ptr = l_next_ptr)
 
1994
        {
 
1995
          l_next_ptr = (t_samp_color_elem *)l_col_ptr->next;
 
1996
          g_free (l_col_ptr);
 
1997
        }
 
1998
 
 
1999
      g_lum_tab[l_lum].col_ptr = NULL;
 
2000
      g_lum_tab[l_lum].all_samples = 0;
 
2001
    }
 
2002
}        /* end p_free_colors */
 
2003
 
 
2004
/* setup lum transformer table according to input_levels, gamma and output levels
 
2005
 * (uses sam algorithm as GIMP Level Tool)
 
2006
 */
 
2007
static void
 
2008
p_calculate_level_transfers (void)
 
2009
{
 
2010
  double inten;
 
2011
  gint i;
 
2012
  gint l_in_min, l_in_max;
 
2013
  gint l_out_min, l_out_max;
 
2014
 
 
2015
  if(g_values.lvl_in_max >= g_values.lvl_in_min)
 
2016
    {
 
2017
      l_in_max = g_values.lvl_in_max;
 
2018
      l_in_min = g_values.lvl_in_min;
 
2019
    }
 
2020
  else
 
2021
    {
 
2022
      l_in_max = g_values.lvl_in_min;
 
2023
      l_in_min = g_values.lvl_in_max;
 
2024
    }
 
2025
  if(g_values.lvl_out_max >= g_values.lvl_out_min)
 
2026
    {
 
2027
      l_out_max = g_values.lvl_out_max;
 
2028
      l_out_min = g_values.lvl_out_min;
 
2029
    }
 
2030
  else
 
2031
    {
 
2032
      l_out_max = g_values.lvl_out_min;
 
2033
      l_out_min = g_values.lvl_out_max;
 
2034
    }
 
2035
 
 
2036
  /*  Recalculate the levels arrays  */
 
2037
  for (i = 0; i < 256; i++)
 
2038
    {
 
2039
      /*  determine input intensity  */
 
2040
      inten = (double) i / 255.0;
 
2041
      if (g_values.lvl_in_gamma != 0.0)
 
2042
        {
 
2043
          inten = pow (inten, (1.0 / g_values.lvl_in_gamma));
 
2044
        }
 
2045
      inten = (double) (inten * (l_in_max - l_in_min) + l_in_min);
 
2046
      inten = CLAMP (inten, 0.0, 255.0);
 
2047
      g_lvl_trans_tab[i] = (guchar) (inten + 0.5);
 
2048
 
 
2049
      /*  determine the output intensity  */
 
2050
      inten = (double) i / 255.0;
 
2051
      inten = (double) (inten * (l_out_max - l_out_min) + l_out_min);
 
2052
      inten = CLAMP (inten, 0.0, 255.0);
 
2053
      g_out_trans_tab[i] = (guchar) (inten + 0.5);
 
2054
    }
 
2055
}        /* end p_calculate_level_transfers */
 
2056
 
 
2057
 
 
2058
 
 
2059
/* alloc and init new col Element */
 
2060
static t_samp_color_elem *
 
2061
p_new_samp_color (const guchar *color)
 
2062
{
 
2063
  t_samp_color_elem *l_col_ptr;
 
2064
 
 
2065
  l_col_ptr = g_new0 (t_samp_color_elem, 1);
 
2066
  if(l_col_ptr == NULL)
 
2067
    {
 
2068
      printf("Error: cant get Memory\n");
 
2069
      return(NULL);
 
2070
    }
 
2071
 
 
2072
  memcpy (&l_col_ptr->color[0], color, 4);
 
2073
 
 
2074
  l_col_ptr->sum_color = 1;
 
2075
  l_col_ptr->next = NULL;
 
2076
 
 
2077
  return l_col_ptr;
 
2078
}        /* end p_new_samp_color */
 
2079
 
 
2080
 
 
2081
/* store color in g_lum_tab  */
 
2082
static void
 
2083
p_add_color (const guchar *color)
 
2084
{
 
2085
  gint32             l_lum;
 
2086
  t_samp_color_elem *l_col_ptr;
 
2087
 
 
2088
  l_lum = LUMINOSITY_1(color);
 
2089
 
 
2090
  g_lum_tab[l_lum].all_samples++;
 
2091
  g_lum_tab[l_lum].from_sample = TRUE;
 
2092
 
 
2093
  /* check if exactly the same color is already in the list */
 
2094
  for(l_col_ptr = g_lum_tab[l_lum].col_ptr;
 
2095
      l_col_ptr != NULL;
 
2096
      l_col_ptr = (t_samp_color_elem *)l_col_ptr->next)
 
2097
    {
 
2098
      if((color[0] == l_col_ptr->color[0])
 
2099
         && (color[1] == l_col_ptr->color[1])
 
2100
         && (color[2] == l_col_ptr->color[2]))
 
2101
        {
 
2102
          l_col_ptr->sum_color++;
 
2103
          return;
 
2104
        }
 
2105
    }
 
2106
 
 
2107
  /* alloc and init element for the new color  */
 
2108
  l_col_ptr = p_new_samp_color(color);
 
2109
 
 
2110
  if(l_col_ptr != NULL)
 
2111
    {
 
2112
     /* add new color element as 1.st of the list */
 
2113
     l_col_ptr->next = g_lum_tab[l_lum].col_ptr;
 
2114
     g_lum_tab[l_lum].col_ptr = l_col_ptr;
 
2115
    }
 
2116
}        /* end p_add_color */
 
2117
 
 
2118
/* sort Sublists (color) by descending sum_color in g_lum_tab
 
2119
 */
 
2120
static void
 
2121
p_sort_color (gint32 lum)
 
2122
{
 
2123
  t_samp_color_elem *l_col_ptr;
 
2124
  t_samp_color_elem *l_next_ptr;
 
2125
  t_samp_color_elem *l_prev_ptr;
 
2126
  t_samp_color_elem *l_sorted_col_ptr;
 
2127
  gint32             l_min;
 
2128
  gint32             l_min_next;
 
2129
 
 
2130
  l_sorted_col_ptr = NULL;
 
2131
  l_min_next           = 0;
 
2132
 
 
2133
  while (g_lum_tab[lum].col_ptr != NULL)
 
2134
    {
 
2135
      l_min = l_min_next;
 
2136
      l_next_ptr = NULL;
 
2137
      l_prev_ptr = NULL;
 
2138
 
 
2139
      for (l_col_ptr = g_lum_tab[lum].col_ptr;
 
2140
           l_col_ptr != NULL;
 
2141
           l_col_ptr = l_next_ptr)
 
2142
        {
 
2143
          l_next_ptr = l_col_ptr->next;
 
2144
          if (l_col_ptr->sum_color > l_min)
 
2145
            {
 
2146
              /* check min value for next loop */
 
2147
              if((l_col_ptr->sum_color < l_min_next) || (l_min == l_min_next))
 
2148
                {
 
2149
                  l_min_next = l_col_ptr->sum_color;
 
2150
                }
 
2151
              l_prev_ptr = l_col_ptr;
 
2152
            }
 
2153
          else
 
2154
            {
 
2155
              /* add element at head of sorted list */
 
2156
              l_col_ptr->next = l_sorted_col_ptr;
 
2157
              l_sorted_col_ptr = l_col_ptr;
 
2158
 
 
2159
              /* remove element from list */
 
2160
              if(l_prev_ptr == NULL)
 
2161
                {
 
2162
                  g_lum_tab[lum].col_ptr = l_next_ptr;  /* remove 1.st element */
 
2163
                }
 
2164
              else
 
2165
                {
 
2166
                  l_prev_ptr->next = l_next_ptr;
 
2167
                }
 
2168
 
 
2169
            }
 
2170
        }
 
2171
    }
 
2172
 
 
2173
  g_lum_tab[lum].col_ptr = l_sorted_col_ptr;
 
2174
}        /* end p_sort_color */
 
2175
 
 
2176
static void
 
2177
p_cnt_same_sample_colortones (t_samp_color_elem *ref_ptr,
 
2178
                              guchar            *prev_color,
 
2179
                              guchar            *color_tone,
 
2180
                              gint              *csum)
 
2181
{
 
2182
  gint32             l_col_error, l_ref_error;
 
2183
  t_samp_color_elem *l_col_ptr;
 
2184
 
 
2185
  l_ref_error = 0;
 
2186
  if (prev_color != NULL)
 
2187
    {
 
2188
      l_ref_error = p_color_error (ref_ptr->color[0], ref_ptr->color[1], ref_ptr->color[2],
 
2189
                                  prev_color[0],      prev_color[1],     prev_color[2]);
 
2190
    }
 
2191
 
 
2192
  /* collect colors that are (nearly) the same */
 
2193
  for(l_col_ptr = ref_ptr->next;
 
2194
      l_col_ptr != NULL;
 
2195
      l_col_ptr = (t_samp_color_elem *)l_col_ptr->next)
 
2196
    {
 
2197
      if(l_col_ptr->sum_color < 1)
 
2198
        {
 
2199
          continue;
 
2200
        }
 
2201
      l_col_error = p_color_error(ref_ptr->color[0],   ref_ptr->color[1],   ref_ptr->color[2],
 
2202
                                  l_col_ptr->color[0], l_col_ptr->color[1], l_col_ptr->color[2]);
 
2203
 
 
2204
     if (l_col_error <= g_tol_col_err )
 
2205
       {
 
2206
         /* cout color of the same colortone */
 
2207
         *csum += l_col_ptr->sum_color;
 
2208
         /* mark the already checked color with negative sum_color value */
 
2209
         l_col_ptr->sum_color = 0 - l_col_ptr->sum_color;
 
2210
 
 
2211
         if(prev_color != NULL)
 
2212
           {
 
2213
             l_col_error = p_color_error(l_col_ptr->color[0], l_col_ptr->color[1], l_col_ptr->color[2],
 
2214
                                         prev_color[0],       prev_color[1],       prev_color[2]);
 
2215
             if(l_col_error < l_ref_error)
 
2216
               {
 
2217
                 /* use the color that is closest to prev_color */
 
2218
                 memcpy(color_tone, &l_col_ptr->color[0], 3);
 
2219
                 l_ref_error = l_col_error;
 
2220
               }
 
2221
           }
 
2222
       }
 
2223
    }
 
2224
}        /* end p_cnt_same_sample_colortones */
 
2225
 
 
2226
/* find the dominant colortones (out of all sample colors)
 
2227
 * for each available brightness intensity value.
 
2228
 * and store them in g_sample_color_tab
 
2229
 */
 
2230
static void
 
2231
p_ideal_samples (void)
 
2232
{
 
2233
  gint32             l_lum;
 
2234
  t_samp_color_elem *l_col_ptr;
 
2235
  guchar            *l_color;
 
2236
 
 
2237
  guchar             l_color_tone[4];
 
2238
  guchar             l_color_ideal[4];
 
2239
  gint               l_csum, l_maxsum;
 
2240
 
 
2241
  l_color = NULL;
 
2242
  for(l_lum = 0; l_lum < 256; l_lum++)
 
2243
  {
 
2244
    if(g_lum_tab[l_lum].col_ptr == NULL) { continue; }
 
2245
 
 
2246
    p_sort_color(l_lum);
 
2247
    l_col_ptr = g_lum_tab[l_lum].col_ptr;
 
2248
    memcpy(&l_color_ideal[0], &l_col_ptr->color[0], 3);
 
2249
 
 
2250
    l_maxsum = 0;
 
2251
 
 
2252
    /* collect colors that are (nearly) the same */
 
2253
    for(;
 
2254
        l_col_ptr != NULL;
 
2255
        l_col_ptr = (t_samp_color_elem *)l_col_ptr->next)
 
2256
      {
 
2257
        l_csum = 0;
 
2258
        if(l_col_ptr->sum_color > 0)
 
2259
          {
 
2260
            memcpy(&l_color_tone[0], &l_col_ptr->color[0], 3);
 
2261
            p_cnt_same_sample_colortones(l_col_ptr, l_color, &l_color_tone[0], &l_csum);
 
2262
            if(l_csum > l_maxsum)
 
2263
              {
 
2264
                l_maxsum = l_csum;
 
2265
                memcpy(&l_color_ideal[0], &l_color_tone[0], 3);
 
2266
              }
 
2267
          }
 
2268
        else
 
2269
          {
 
2270
            l_col_ptr->sum_color = abs(l_col_ptr->sum_color);
 
2271
          }
 
2272
      }
 
2273
 
 
2274
    /* store ideal color and keep track of the color */
 
2275
    l_color = &g_sample_color_tab[3 * l_lum];
 
2276
    memcpy (l_color, &l_color_ideal[0], 3);
 
2277
  }
 
2278
}        /* end p_ideal_samples */
 
2279
 
 
2280
static void
 
2281
p_guess_missing_colors (void)
 
2282
{
 
2283
  gint32  l_lum;
 
2284
  gint32  l_idx;
 
2285
  gfloat  l_div;
 
2286
 
 
2287
  guchar  l_lo_color[4];
 
2288
  guchar  l_hi_color[4];
 
2289
  guchar  l_new_color[4];
 
2290
 
 
2291
  l_lo_color[0] = 0;
 
2292
  l_lo_color[1] = 0;
 
2293
  l_lo_color[2] = 0;
 
2294
  l_lo_color[3] = 255;
 
2295
  l_hi_color[0] = 255;
 
2296
  l_hi_color[1] = 255;
 
2297
  l_hi_color[2] = 255;
 
2298
  l_hi_color[3] = 255;
 
2299
  l_new_color[0] = 0;
 
2300
  l_new_color[1] = 0;
 
2301
  l_new_color[2] = 0;
 
2302
  l_new_color[3] = 255;
 
2303
 
 
2304
  for(l_lum = 0; l_lum < 256; l_lum++)
 
2305
    {
 
2306
      if((g_lum_tab[l_lum].col_ptr == NULL) || (g_lum_tab[l_lum].from_sample == FALSE))
 
2307
        {
 
2308
          if(l_lum > 0)
 
2309
            {
 
2310
              for(l_idx = l_lum; l_idx < 256; l_idx++)
 
2311
                {
 
2312
                  if((g_lum_tab[l_idx].col_ptr != NULL) && (g_lum_tab[l_idx].from_sample))
 
2313
                    {
 
2314
                      memcpy(&l_hi_color[0], &g_sample_color_tab[l_idx + l_idx + l_idx], 3);
 
2315
                      break;
 
2316
                    }
 
2317
                  if(l_idx == 255)
 
2318
                    {
 
2319
                      l_hi_color[0] = 255;
 
2320
                      l_hi_color[1] = 255;
 
2321
                      l_hi_color[2] = 255;
 
2322
                      break;
 
2323
                    }
 
2324
                }
 
2325
 
 
2326
              l_div = l_idx - (l_lum -1);
 
2327
              l_new_color[0] = l_lo_color[0] + ((float)(l_hi_color[0] - l_lo_color[0]) / l_div);
 
2328
              l_new_color[1] = l_lo_color[1] + ((float)(l_hi_color[1] - l_lo_color[1]) / l_div);
 
2329
              l_new_color[2] = l_lo_color[2] + ((float)(l_hi_color[2] - l_lo_color[2]) / l_div);
 
2330
 
 
2331
/*
 
2332
 *          printf("LO: %03d %03d %03d HI: %03d %03d %03d   NEW: %03d %03d %03d\n",
 
2333
 *                (int)l_lo_color[0],  (int)l_lo_color[1],  (int)l_lo_color[2],
 
2334
 *                (int)l_hi_color[0],  (int)l_hi_color[1],  (int)l_hi_color[2],
 
2335
 *                (int)l_new_color[0], (int)l_new_color[1], (int)l_new_color[2]);
 
2336
 */
 
2337
 
 
2338
            }
 
2339
          g_lum_tab[l_lum].col_ptr = p_new_samp_color(&l_new_color[0]);
 
2340
          g_lum_tab[l_lum].from_sample = FALSE;
 
2341
          memcpy(&g_sample_color_tab [3 * l_lum], &l_new_color[0], 3);
 
2342
        }
 
2343
 
 
2344
    memcpy (&l_lo_color[0], &g_sample_color_tab [3 * l_lum], 3);
 
2345
  }
 
2346
}        /* end p_guess_missing_colors */
 
2347
 
 
2348
static void
 
2349
p_fill_missing_colors (void)
 
2350
{
 
2351
  gint32             l_lum;
 
2352
  gint32             l_idx;
 
2353
  gint32             l_lo_idx;
 
2354
 
 
2355
  guchar             l_lo_color[4];
 
2356
  guchar             l_hi_color[4];
 
2357
  guchar             l_new_color[4];
 
2358
 
 
2359
  l_lo_color[0] = 0;
 
2360
  l_lo_color[1] = 0;
 
2361
  l_lo_color[2] = 0;
 
2362
  l_lo_color[3] = 255;
 
2363
  l_hi_color[0] = 255;
 
2364
  l_hi_color[1] = 255;
 
2365
  l_hi_color[2] = 255;
 
2366
  l_hi_color[3] = 255;
 
2367
  l_new_color[0] = 0;
 
2368
  l_new_color[1] = 0;
 
2369
  l_new_color[2] = 0;
 
2370
  l_new_color[3] = 255;
 
2371
 
 
2372
  l_lo_idx = 0;
 
2373
  for(l_lum = 0; l_lum < 256; l_lum++)
 
2374
    {
 
2375
      if((g_lum_tab[l_lum].col_ptr == NULL) || (g_lum_tab[l_lum].from_sample == FALSE))
 
2376
        {
 
2377
          if(l_lum > 0)
 
2378
            {
 
2379
              for(l_idx = l_lum; l_idx < 256; l_idx++)
 
2380
                {
 
2381
                  if((g_lum_tab[l_idx].col_ptr != NULL) && (g_lum_tab[l_idx].from_sample))
 
2382
                    {
 
2383
                      memcpy (&l_hi_color[0],
 
2384
                              &g_sample_color_tab[l_idx + l_idx + l_idx], 3);
 
2385
                      break;
 
2386
                    }
 
2387
 
 
2388
                  if(l_idx == 255)
 
2389
                    {
 
2390
/*
 
2391
 *               l_hi_color[0] = 255;
 
2392
 *               l_hi_color[1] = 255;
 
2393
 *               l_hi_color[2] = 255;
 
2394
 */
 
2395
                      memcpy(&l_hi_color[0], &l_lo_color[0], 3);
 
2396
                      break;
 
2397
                    }
 
2398
                }
 
2399
 
 
2400
              if((l_lum > (l_lo_idx + ((l_idx - l_lo_idx ) / 2)))
 
2401
                 || (l_lo_idx == 0))
 
2402
                {
 
2403
                  l_new_color[0] = l_hi_color[0];
 
2404
                  l_new_color[1] = l_hi_color[1];
 
2405
                  l_new_color[2] = l_hi_color[2];
 
2406
                }
 
2407
              else
 
2408
                {
 
2409
                  l_new_color[0] = l_lo_color[0];
 
2410
                  l_new_color[1] = l_lo_color[1];
 
2411
                  l_new_color[2] = l_lo_color[2];
 
2412
                }
 
2413
            }
 
2414
 
 
2415
          g_lum_tab[l_lum].col_ptr = p_new_samp_color(&l_new_color[0]);
 
2416
          g_lum_tab[l_lum].from_sample = FALSE;
 
2417
          memcpy(&g_sample_color_tab[3 * l_lum], &l_new_color[0], 3);
 
2418
        }
 
2419
      else
 
2420
        {
 
2421
          l_lo_idx = l_lum;
 
2422
          memcpy(&l_lo_color[0], &g_sample_color_tab[3 * l_lum], 3);
 
2423
        }
 
2424
    }
 
2425
}        /* end p_fill_missing_colors */
 
2426
 
 
2427
/* get 256 samples of active gradient (optional in invers order) */
 
2428
static void
 
2429
p_get_gradient (gint mode)
 
2430
{
 
2431
  gchar   *name;
 
2432
  gint     n_f_samples;
 
2433
  gdouble *f_samples;
 
2434
  gdouble *f_samp;        /* float samples */
 
2435
  gint     l_lum;
 
2436
 
 
2437
  p_free_colors ();
 
2438
 
 
2439
  name = gimp_context_get_gradient ();
 
2440
 
 
2441
  gimp_gradient_get_uniform_samples (name, 256 /* n_samples */,
 
2442
                                     mode == SMP_INV_GRADIENT,
 
2443
                                     &n_f_samples, &f_samples);
 
2444
 
 
2445
  g_free (name);
 
2446
 
 
2447
  for (l_lum = 0; l_lum < 256; l_lum++)
 
2448
    {
 
2449
      f_samp = &f_samples[l_lum * 4];
 
2450
 
 
2451
      g_sample_color_tab[3 * l_lum + 0] = f_samp[0] * 255;
 
2452
      g_sample_color_tab[3 * l_lum + 1] = f_samp[1] * 255;
 
2453
      g_sample_color_tab[3 * l_lum + 2] = f_samp[2] * 255;
 
2454
 
 
2455
      g_lum_tab[l_lum].col_ptr =
 
2456
        p_new_samp_color (&g_sample_color_tab[3 * l_lum]);
 
2457
      g_lum_tab[l_lum].from_sample = TRUE;
 
2458
      g_lum_tab[l_lum].all_samples = 1;
 
2459
    }
 
2460
 
 
2461
  g_free (f_samples);
 
2462
}        /* end p_get_gradient */
 
2463
 
 
2464
static gint32
 
2465
p_is_layer_alive(gint32 drawable_id)
 
2466
{
 
2467
  /* return -1 if layer has become invalid */
 
2468
 
 
2469
  if (drawable_id < 0)
 
2470
    {
 
2471
      return -1;
 
2472
    }
 
2473
 
 
2474
  if (gimp_drawable_get_image (drawable_id) < 0)
 
2475
    {
 
2476
      printf ("sample colorize: unknown layer_id %d (Image closed?)\n",
 
2477
              (int)drawable_id);
 
2478
      return -1;
 
2479
    }
 
2480
 
 
2481
  return drawable_id;
 
2482
}
 
2483
 
 
2484
static void
 
2485
p_end_gdrw(t_GDRW *gdrw)
 
2486
{
 
2487
  t_GDRW  *sel_gdrw;
 
2488
 
 
2489
  if (gdrw->tile)
 
2490
    {
 
2491
      gimp_tile_unref (gdrw->tile, gdrw->tile_dirty);
 
2492
      gdrw->tile = NULL;
 
2493
    }
 
2494
 
 
2495
  sel_gdrw = (t_GDRW*)(gdrw->sel_gdrw);
 
2496
  if (sel_gdrw)
 
2497
    {
 
2498
      if(sel_gdrw->tile)
 
2499
        {
 
2500
          gimp_tile_unref (sel_gdrw->tile, sel_gdrw->tile_dirty);
 
2501
       sel_gdrw->tile = NULL;
 
2502
        }
 
2503
      gdrw->sel_gdrw = NULL;
 
2504
    }
 
2505
}
 
2506
 
 
2507
static void
 
2508
p_init_gdrw (t_GDRW       *gdrw,
 
2509
             GimpDrawable *drawable,
 
2510
             gint          dirty,
 
2511
             gint          shadow)
 
2512
{
 
2513
  gint32  l_image_id;
 
2514
  gint32  l_sel_channel_id;
 
2515
  gint32  l_x1, l_x2, l_y1, l_y2;
 
2516
  gint    l_offsetx, l_offsety;
 
2517
  gint    l_sel_offsetx, l_sel_offsety;
 
2518
  t_GDRW *l_sel_gdrw;
 
2519
  gint32  non_empty;
 
2520
 
 
2521
  if(g_Sdebug)  printf("\np_init_gdrw: drawable %p  ID: %d\n", drawable, (int)drawable->drawable_id);
 
2522
 
 
2523
  gdrw->drawable = drawable;
 
2524
  gdrw->tile = NULL;
 
2525
  gdrw->tile_dirty = FALSE;
 
2526
  gdrw->tile_width = gimp_tile_width ();
 
2527
  gdrw->tile_height = gimp_tile_height ();
 
2528
  gdrw->shadow = shadow;
 
2529
  gdrw->tile_swapcount = 0;
 
2530
  gdrw->seldeltax = 0;
 
2531
  gdrw->seldeltay = 0;
 
2532
  gimp_drawable_offsets (drawable->drawable_id, &l_offsetx, &l_offsety);  /* get offsets within the image */
 
2533
 
 
2534
  gimp_drawable_mask_bounds (drawable->drawable_id,
 
2535
                             &gdrw->x1, &gdrw->y1, &gdrw->x2, &gdrw->y2);
 
2536
 
 
2537
  gdrw->bpp = drawable->bpp;
 
2538
  if (gimp_drawable_has_alpha(drawable->drawable_id))
 
2539
    {
 
2540
      /* index of the alpha channelbyte {1|3} */
 
2541
      gdrw->index_alpha = gdrw->bpp -1;
 
2542
    }
 
2543
  else
 
2544
    {
 
2545
      gdrw->index_alpha = 0;      /* there is no alpha channel */
 
2546
    }
 
2547
 
 
2548
  l_image_id = gimp_drawable_get_image (drawable->drawable_id);
 
2549
 
 
2550
  /* check and see if we have a selection mask */
 
2551
  l_sel_channel_id  = gimp_image_get_selection (l_image_id);
 
2552
 
 
2553
  if(g_Sdebug)
 
2554
    {
 
2555
      printf("p_init_gdrw: image_id %d sel_channel_id: %d\n", (int)l_image_id, (int)l_sel_channel_id);
 
2556
      printf("p_init_gdrw: BOUNDS     x1: %d y1: %d x2:%d y2: %d\n",
 
2557
             (int)gdrw->x1,  (int)gdrw->y1, (int)gdrw->x2,(int)gdrw->y2);
 
2558
      printf("p_init_gdrw: OFFS       x: %d y: %d\n", (int)l_offsetx, (int)l_offsety );
 
2559
    }
 
2560
 
 
2561
  gimp_selection_bounds (l_image_id, &non_empty, &l_x1, &l_y1, &l_x2, &l_y2);
 
2562
 
 
2563
  if (non_empty && (l_sel_channel_id >= 0))
 
2564
    {
 
2565
      /* selection is TRUE */
 
2566
      l_sel_gdrw = (t_GDRW *) calloc(1, sizeof(t_GDRW));
 
2567
      l_sel_gdrw->drawable = gimp_drawable_get (l_sel_channel_id);
 
2568
 
 
2569
      l_sel_gdrw->tile = NULL;
 
2570
      l_sel_gdrw->tile_dirty = FALSE;
 
2571
      l_sel_gdrw->tile_width = gimp_tile_width ();
 
2572
      l_sel_gdrw->tile_height = gimp_tile_height ();
 
2573
      l_sel_gdrw->shadow = shadow;
 
2574
      l_sel_gdrw->tile_swapcount = 0;
 
2575
      l_sel_gdrw->x1 = l_x1;
 
2576
      l_sel_gdrw->y1 = l_y1;
 
2577
      l_sel_gdrw->x2 = l_x2;
 
2578
      l_sel_gdrw->y2 = l_y2;
 
2579
      l_sel_gdrw->seldeltax = 0;
 
2580
      l_sel_gdrw->seldeltay = 0;
 
2581
      l_sel_gdrw->bpp = l_sel_gdrw->drawable->bpp;  /* should be always 1 */
 
2582
      l_sel_gdrw->index_alpha = 0;   /* there is no alpha channel */
 
2583
      l_sel_gdrw->sel_gdrw = NULL;
 
2584
 
 
2585
      /* offset delta between drawable and selection
 
2586
       * (selection always has image size and should always have offsets of 0 )
 
2587
       */
 
2588
      gimp_drawable_offsets (l_sel_channel_id, &l_sel_offsetx, &l_sel_offsety);
 
2589
      gdrw->seldeltax = l_offsetx - l_sel_offsetx;
 
2590
      gdrw->seldeltay = l_offsety - l_sel_offsety;
 
2591
 
 
2592
      gdrw->sel_gdrw = (t_GDRW *) l_sel_gdrw;
 
2593
 
 
2594
      if (g_Sdebug)
 
2595
        {
 
2596
          printf("p_init_gdrw: SEL_BOUNDS x1: %d y1: %d x2:%d y2: %d\n",
 
2597
                 (int)l_sel_gdrw->x1,  (int)l_sel_gdrw->y1, (int)l_sel_gdrw->x2,(int)l_sel_gdrw->y2);
 
2598
          printf("p_init_gdrw: SEL_OFFS   x: %d y: %d\n", (int)l_sel_offsetx, (int)l_sel_offsety );
 
2599
 
 
2600
          printf("p_init_gdrw: SEL_DELTA  x: %d y: %d\n", (int)gdrw->seldeltax, (int)gdrw->seldeltay );
 
2601
        }
 
2602
    }
 
2603
  else
 
2604
    {
 
2605
      gdrw->sel_gdrw = NULL;     /* selection is FALSE */
 
2606
    }
 
2607
}
 
2608
 
 
2609
/* analyze the colors in the sample_drawable */
 
2610
static int
 
2611
p_sample_analyze (t_GDRW *sample_gdrw)
 
2612
{
 
2613
   gint32             l_sample_pixels;
 
2614
   gint32             l_row, l_col;
 
2615
   gint32             l_first_row, l_first_col, l_last_row, l_last_col;
 
2616
   gint32             l_x, l_y;
 
2617
   gint32             l_x2, l_y2;
 
2618
   float l_progress_step;
 
2619
   float l_progress_max;
 
2620
   float l_progress;
 
2621
 
 
2622
   guchar             color[4];
 
2623
 
 
2624
   FILE     *prot_fp;
 
2625
 
 
2626
   l_sample_pixels = 0;
 
2627
 
 
2628
   /* init progress */
 
2629
   l_progress_max = (sample_gdrw->x2 - sample_gdrw->x1);
 
2630
   l_progress_step = 1.0 / l_progress_max;
 
2631
   l_progress = 0.0;
 
2632
   if(g_show_progress) gimp_progress_init (_("Sample Analyze..."));
 
2633
 
 
2634
   prot_fp = NULL;
 
2635
   if(g_Sdebug) prot_fp = fopen("sample_colors.dump", "w");
 
2636
   p_print_values(prot_fp);
 
2637
 
 
2638
   /* ------------------------------------------------
 
2639
    * foreach pixel in the SAMPLE_drawable:
 
2640
    *  calculate brightness intensity LUM
 
2641
    * ------------------------------------------------
 
2642
    * the inner loops (l_x/l_y) are designed to process
 
2643
    * all pixels of one tile in the sample drawable, the outer loops (row/col) do step
 
2644
    * to the next tiles. (this was done to reduce tile swapping)
 
2645
    */
 
2646
 
 
2647
   l_first_row = sample_gdrw->y1 / sample_gdrw->tile_height;
 
2648
   l_last_row  = (sample_gdrw->y2 / sample_gdrw->tile_height);
 
2649
   l_first_col = sample_gdrw->x1 / sample_gdrw->tile_width;
 
2650
   l_last_col  = (sample_gdrw->x2 / sample_gdrw->tile_width);
 
2651
 
 
2652
   for(l_row = l_first_row; l_row <= l_last_row; l_row++)
 
2653
     {
 
2654
       for(l_col = l_first_col; l_col <= l_last_col; l_col++)
 
2655
         {
 
2656
           if(l_col == l_first_col)    l_x = sample_gdrw->x1;
 
2657
           else                        l_x = l_col * sample_gdrw->tile_width;
 
2658
           if(l_col == l_last_col)     l_x2 = sample_gdrw->x2;
 
2659
           else                        l_x2 = (l_col +1) * sample_gdrw->tile_width;
 
2660
 
 
2661
           for( ; l_x < l_x2; l_x++)
 
2662
             {
 
2663
               if(l_row == l_first_row)    l_y = sample_gdrw->y1;
 
2664
               else                        l_y = l_row * sample_gdrw->tile_height;
 
2665
               if(l_row == l_last_row)     l_y2 = sample_gdrw->y2;
 
2666
               else                        l_y2 = (l_row +1) * sample_gdrw->tile_height ;
 
2667
 
 
2668
               /* printf("X: %4d Y:%4d Y2:%4d\n", (int)l_x, (int)l_y, (int)l_y2); */
 
2669
 
 
2670
               for( ; l_y < l_y2; l_y++)
 
2671
                 {
 
2672
                   /* check if the pixel is in the selection */
 
2673
                   if(sample_gdrw->sel_gdrw)
 
2674
                     {
 
2675
                       p_get_pixel(sample_gdrw->sel_gdrw,
 
2676
                                   (l_x + sample_gdrw->seldeltax),
 
2677
                                   (l_y + sample_gdrw->seldeltay),
 
2678
                                   &color[0]);
 
2679
 
 
2680
                       if(color[0] == 0)
 
2681
                         {
 
2682
                           continue;
 
2683
                         }
 
2684
                     }
 
2685
 
 
2686
                   p_get_pixel(sample_gdrw, l_x, l_y, &color[0]);
 
2687
 
 
2688
                   /* if this is a visible (non-transparent) pixel */
 
2689
                   if((sample_gdrw->index_alpha < 1) || (color[sample_gdrw->index_alpha] != 0))
 
2690
                     {
 
2691
                       /* store color in the sublists of g_lum_tab  */
 
2692
                       p_add_color(&color[0]);
 
2693
                       l_sample_pixels++;
 
2694
                     }
 
2695
                 }
 
2696
               if(g_show_progress) gimp_progress_update (l_progress += l_progress_step);
 
2697
             }
 
2698
         }
 
2699
     }
 
2700
 
 
2701
   if(g_Sdebug) printf("ROWS: %d - %d  COLS: %d - %d\n", (int)l_first_row, (int)l_last_row, (int)l_first_col, (int)l_last_col);
 
2702
 
 
2703
   p_print_table(prot_fp);
 
2704
 
 
2705
   if(g_Sdebug) p_print_ppm("sample_color_all.ppm");
 
2706
 
 
2707
   /* findout ideal sample colors for each brightness intensity (lum)
 
2708
    * and set g_sample_color_tab to the ideal colors.
 
2709
    */
 
2710
   p_ideal_samples();
 
2711
   p_calculate_level_transfers ();
 
2712
   if(g_values.guess_missing) { p_guess_missing_colors(); }
 
2713
   else                       { p_fill_missing_colors(); }
 
2714
 
 
2715
   p_print_table(prot_fp);
 
2716
   if(g_Sdebug) p_print_ppm("sample_color_2.ppm");
 
2717
   p_print_transtable(prot_fp);
 
2718
   if(prot_fp) fclose(prot_fp);
 
2719
 
 
2720
   /* check if there was at least one visible pixel */
 
2721
   if (l_sample_pixels == 0)
 
2722
     {
 
2723
       printf("Error: Source sample has no visible Pixel\n");
 
2724
       return -1;
 
2725
     }
 
2726
   return 0;
 
2727
}                /* end p_sample_analyze */
 
2728
 
 
2729
static void
 
2730
p_rnd_remap (gint32  lum,
 
2731
             guchar *mapped_color)
 
2732
{
 
2733
  t_samp_color_elem *l_col_ptr;
 
2734
  gint               l_rnd;
 
2735
  gint               l_ct;
 
2736
  gint               l_idx;
 
2737
 
 
2738
  if (g_lum_tab[lum].all_samples > 1)
 
2739
    {
 
2740
      l_rnd = g_random_int_range (0, g_lum_tab[lum].all_samples);
 
2741
      l_ct  = 0;
 
2742
      l_idx = 0;
 
2743
 
 
2744
      for (l_col_ptr = g_lum_tab[lum].col_ptr;
 
2745
           l_col_ptr != NULL;
 
2746
           l_col_ptr = (t_samp_color_elem *)l_col_ptr->next)
 
2747
        {
 
2748
          l_ct += l_col_ptr->sum_color;
 
2749
 
 
2750
          if (l_rnd < l_ct)
 
2751
            {
 
2752
              /* printf("RND_remap: rnd: %d all:%d  ct:%d idx:%d\n",
 
2753
               * l_rnd, (int)g_lum_tab[lum].all_samples, l_ct, l_idx);
 
2754
               */
 
2755
              memcpy (mapped_color, &l_col_ptr->color[0], 3);
 
2756
              return;
 
2757
            }
 
2758
          l_idx++;
 
2759
        }
 
2760
    }
 
2761
 
 
2762
  memcpy (mapped_color, &g_sample_color_tab[lum + lum + lum], 3);
 
2763
}
 
2764
 
 
2765
static void
 
2766
p_remap_pixel (guchar       *pixel,
 
2767
               const guchar *original,
 
2768
               gint          bpp2)
 
2769
{
 
2770
  guchar mapped_color[4];
 
2771
  gint   l_lum;
 
2772
  double l_orig_lum, l_mapped_lum;
 
2773
  double l_grn, l_red, l_blu;
 
2774
  double l_mg,  l_mr,  l_mb;
 
2775
  double l_dg,  l_dr,  l_db;
 
2776
  double l_dlum;
 
2777
 
 
2778
  /* get brightness from (uncolorized) original */
 
2779
  l_lum = g_out_trans_tab[g_lvl_trans_tab[LUMINOSITY_1(original)]];
 
2780
  if (g_values.rnd_subcolors)
 
2781
    {
 
2782
      p_rnd_remap (l_lum, mapped_color);
 
2783
    }
 
2784
  else
 
2785
    {
 
2786
      memcpy (mapped_color, &g_sample_color_tab[3 * l_lum], 3);
 
2787
    }
 
2788
 
 
2789
  if (g_values.hold_inten)
 
2790
    {
 
2791
      if (g_values.orig_inten)
 
2792
        {
 
2793
          l_orig_lum = LUMINOSITY_0(original);
 
2794
        }
 
2795
      else
 
2796
        {
 
2797
          l_orig_lum = 100.0 * g_lvl_trans_tab[LUMINOSITY_1(original)];
 
2798
        }
 
2799
 
 
2800
      l_mapped_lum = LUMINOSITY_0 (mapped_color);
 
2801
 
 
2802
      if (l_mapped_lum == 0)
 
2803
        {
 
2804
          /* convert black to greylevel with desired brightness value */
 
2805
          mapped_color[0] = l_orig_lum / 100.0;
 
2806
          mapped_color[1] = mapped_color[0];
 
2807
          mapped_color[2] = mapped_color[0];
 
2808
        }
 
2809
      else
 
2810
        {
 
2811
          /* Calculate theoretical RGB to reach given intensity LUM
 
2812
           * value (l_orig_lum)
 
2813
           */
 
2814
          l_mr = mapped_color[0];
 
2815
          l_mg = mapped_color[1];
 
2816
          l_mb = mapped_color[2];
 
2817
 
 
2818
          if(l_mr > 0.0)
 
2819
            {
 
2820
              l_red =
 
2821
                l_orig_lum / (30 + (59 * l_mg / l_mr) + (11 * l_mb / l_mr));
 
2822
              l_grn = l_mg * l_red / l_mr;
 
2823
              l_blu = l_mb * l_red / l_mr;
 
2824
            }
 
2825
          else if (l_mg > 0.0)
 
2826
            {
 
2827
              l_grn =
 
2828
                l_orig_lum / ((30 * l_mr / l_mg) + 59 + (11 * l_mb / l_mg));
 
2829
              l_red = l_mr * l_grn / l_mg;
 
2830
              l_blu = l_mb * l_grn / l_mg;
 
2831
            }
 
2832
          else
 
2833
            {
 
2834
              l_blu =
 
2835
                l_orig_lum / ((30 * l_mr / l_mb) + (59 * l_mg / l_mb) + 11);
 
2836
              l_grn = l_mg * l_blu / l_mb;
 
2837
              l_red = l_mr * l_blu / l_mb;
 
2838
            }
 
2839
 
 
2840
          /* on overflow: Calculate real RGB values
 
2841
           * (this may change the hue and saturation,
 
2842
           * more and more into white)
 
2843
           */
 
2844
 
 
2845
          if (l_red > 255)
 
2846
            {
 
2847
              if ((l_blu < 255) && (l_grn < 255))
 
2848
                {
 
2849
                  /* overflow in the red channel (compensate with green and blu)  */
 
2850
                  l_dlum = (l_red - 255.0) * 30.0;
 
2851
                  if (l_mg > 0)
 
2852
                    {
 
2853
                      l_dg = l_dlum / (59.0 + (11.0 * l_mb / l_mg));
 
2854
                      l_db = l_dg * l_mb / l_mg;
 
2855
                    }
 
2856
                  else if (l_mb > 0)
 
2857
                    {
 
2858
                      l_db = l_dlum / (11.0 + (59.0 * l_mg / l_mb));
 
2859
                      l_dg = l_db * l_mg / l_mb;
 
2860
                    }
 
2861
                  else
 
2862
                    {
 
2863
                      l_db = l_dlum / (11.0 + 59.0);
 
2864
                      l_dg = l_dlum / (59.0 + 11.0);
 
2865
                    }
 
2866
 
 
2867
                  l_grn += l_dg;
 
2868
                  l_blu += l_db;
 
2869
                }
 
2870
 
 
2871
              l_red = 255.0;
 
2872
 
 
2873
              if (l_grn > 255)
 
2874
                {
 
2875
                  l_grn = 255.0;
 
2876
                  l_blu = (l_orig_lum - 22695) / 11;  /* 22695 =  (255*30) + (255*59)  */
 
2877
                }
 
2878
              if (l_blu > 255)
 
2879
                {
 
2880
                  l_blu = 255.0;
 
2881
                  l_grn = (l_orig_lum - 10455) / 59;  /* 10455 =  (255*30) + (255*11)  */
 
2882
                }
 
2883
            }
 
2884
          else if (l_grn > 255)
 
2885
            {
 
2886
              if ((l_blu < 255) && (l_red < 255))
 
2887
                {
 
2888
                  /* overflow in the green channel (compensate with red and blu)  */
 
2889
                  l_dlum = (l_grn - 255.0) * 59.0;
 
2890
 
 
2891
                  if (l_mr > 0)
 
2892
                    {
 
2893
                      l_dr = l_dlum / (30.0 + (11.0 * l_mb / l_mr));
 
2894
                      l_db = l_dr * l_mb / l_mr;
 
2895
                    }
 
2896
                  else if (l_mb > 0)
 
2897
                    {
 
2898
                      l_db = l_dlum / (11.0 + (30.0 * l_mr / l_mb));
 
2899
                      l_dr = l_db * l_mr / l_mb;
 
2900
                    }
 
2901
                  else
 
2902
                    {
 
2903
                      l_db = l_dlum / (11.0 + 30.0);
 
2904
                      l_dr = l_dlum / (30.0 + 11.0);
 
2905
                    }
 
2906
 
 
2907
                  l_red += l_dr;
 
2908
                  l_blu += l_db;
 
2909
                }
 
2910
 
 
2911
              l_grn = 255.0;
 
2912
 
 
2913
              if (l_red > 255)
 
2914
                {
 
2915
                  l_red = 255.0;
 
2916
                  l_blu = (l_orig_lum - 22695) / 11;  /* 22695 =  (255*59) + (255*30)  */
 
2917
                }
 
2918
              if (l_blu > 255)
 
2919
                {
 
2920
                  l_blu = 255.0;
 
2921
                  l_red = (l_orig_lum - 17850) / 30;  /* 17850 =  (255*59) + (255*11)  */
 
2922
                }
 
2923
            }
 
2924
          else if (l_blu > 255)
 
2925
            {
 
2926
              if ((l_red < 255) && (l_grn < 255))
 
2927
                {
 
2928
                  /* overflow in the blue channel (compensate with green and red)  */
 
2929
                  l_dlum = (l_blu - 255.0) * 11.0;
 
2930
 
 
2931
                  if (l_mg > 0)
 
2932
                    {
 
2933
                      l_dg = l_dlum / (59.0 + (30.0 * l_mr / l_mg));
 
2934
                      l_dr = l_dg * l_mr / l_mg;
 
2935
                    }
 
2936
                  else if (l_mr > 0)
 
2937
                    {
 
2938
                      l_dr = l_dlum / (30.0 + (59.0 * l_mg / l_mr));
 
2939
                      l_dg = l_dr * l_mg / l_mr;
 
2940
                    }
 
2941
                  else
 
2942
                    {
 
2943
                      l_dr = l_dlum / (30.0 + 59.0);
 
2944
                      l_dg = l_dlum / (59.0 + 30.0);
 
2945
                    }
 
2946
 
 
2947
                  l_grn += l_dg;
 
2948
                  l_red += l_dr;
 
2949
                }
 
2950
 
 
2951
              l_blu = 255.0;
 
2952
 
 
2953
              if (l_grn > 255)
 
2954
                {
 
2955
                  l_grn = 255.0;
 
2956
                  l_red = (l_orig_lum - 17850) / 30;  /* 17850 =  (255*11) + (255*59)  */
 
2957
                }
 
2958
              if (l_red > 255)
 
2959
                {
 
2960
                  l_red = 255.0;
 
2961
                  l_grn = (l_orig_lum - 10455) / 59;  /* 10455 =  (255*11) + (255*30)  */
 
2962
                }
 
2963
            }
 
2964
 
 
2965
          mapped_color[0] = CLAMP0255 (l_red + 0.5);
 
2966
          mapped_color[1] = CLAMP0255 (l_grn + 0.5);
 
2967
          mapped_color[2] = CLAMP0255 (l_blu + 0.5);
 
2968
        }
 
2969
    }
 
2970
 
 
2971
  /* set colorized pixel in shadow pr */
 
2972
  memcpy (pixel, &mapped_color[0], bpp2);
 
2973
}
 
2974
 
 
2975
static void
 
2976
colorize_func (const guchar *src,
 
2977
               guchar       *dest,
 
2978
               gint          bpp,
 
2979
               gpointer      data)
 
2980
{
 
2981
  gboolean has_alpha = GPOINTER_TO_INT (data);
 
2982
 
 
2983
  if (has_alpha)
 
2984
    {
 
2985
      bpp--;
 
2986
      dest[bpp] = src[bpp];
 
2987
    }
 
2988
 
 
2989
  p_remap_pixel (dest, src, bpp);
 
2990
}
 
2991
 
 
2992
static void
 
2993
p_colorize_drawable (gint32 drawable_id)
 
2994
{
 
2995
  GimpDrawable *drawable;
 
2996
  gboolean      has_alpha;
 
2997
 
 
2998
  drawable = gimp_drawable_get (drawable_id);
 
2999
  has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
 
3000
 
 
3001
  if (g_show_progress)
 
3002
    gimp_progress_init (_("Remap Colorized..."));
 
3003
 
 
3004
  gimp_rgn_iterate2 (drawable, 0 /* unused */, colorize_func,
 
3005
                     GINT_TO_POINTER (has_alpha));
 
3006
 
 
3007
  if (g_show_progress)
 
3008
    gimp_progress_update (0.0);
 
3009
}
 
3010
 
 
3011
/* colorize dst_drawable like sample_drawable */
 
3012
static int
 
3013
p_main_colorize (gint mc_flags)
 
3014
{
 
3015
   GimpDrawable *dst_drawable;
 
3016
   GimpDrawable *sample_drawable;
 
3017
   t_GDRW        l_sample_gdrw;
 
3018
   gint32        l_max;
 
3019
   gint32        l_id;
 
3020
   gint          l_rc;
 
3021
 
 
3022
   if(g_Sdebug)  p_get_filevalues ();  /* for debugging: read values from file */
 
3023
   sample_drawable = NULL;
 
3024
   dst_drawable = NULL;
 
3025
 
 
3026
   /* calculate value of tolerable color error */
 
3027
   l_max = p_color_error (0,0, 0, 255, 255, 255); /* 260100 */
 
3028
   g_tol_col_err = (((float)l_max  * (g_values.tol_col_err * g_values.tol_col_err)) / (100.0 *100.0));
 
3029
   g_max_col_err = l_max;
 
3030
 
 
3031
   l_rc = 0;
 
3032
 
 
3033
   if (mc_flags & MC_GET_SAMPLE_COLORS)
 
3034
     {
 
3035
       l_id = g_values.sample_id;
 
3036
       if ((l_id == SMP_GRADIENT) || (l_id == SMP_INV_GRADIENT))
 
3037
         {
 
3038
           p_get_gradient (l_id);
 
3039
         }
 
3040
       else
 
3041
         {
 
3042
           if (p_is_layer_alive (l_id) < 0)
 
3043
             {
 
3044
               return -1;
 
3045
             }
 
3046
 
 
3047
           sample_drawable = gimp_drawable_get (l_id);
 
3048
           p_init_gdrw (&l_sample_gdrw, sample_drawable, FALSE, FALSE);
 
3049
           p_free_colors ();
 
3050
           l_rc = p_sample_analyze (&l_sample_gdrw);
 
3051
         }
 
3052
     }
 
3053
 
 
3054
   if ((mc_flags & MC_DST_REMAP) && (l_rc == 0))
 
3055
     {
 
3056
       if (p_is_layer_alive (g_values.dst_id) < 0)
 
3057
         {
 
3058
           return -1;
 
3059
         }
 
3060
       dst_drawable = gimp_drawable_get (g_values.dst_id);
 
3061
       if (gimp_drawable_is_gray (g_values.dst_id))
 
3062
         {
 
3063
           if (mc_flags & MC_DST_REMAP)
 
3064
             {
 
3065
               gimp_image_convert_rgb (gimp_drawable_get_image (g_values.dst_id));
 
3066
             }
 
3067
         }
 
3068
 
 
3069
       p_colorize_drawable (dst_drawable->drawable_id);
 
3070
     }
 
3071
 
 
3072
   if (sample_drawable)
 
3073
     {
 
3074
       p_end_gdrw (&l_sample_gdrw);
 
3075
     }
 
3076
 
 
3077
   return l_rc;
 
3078
}