2
* A GIMP Plug-In by Wolfgang Hofer
5
/* The GIMP -- an image manipulation program
6
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
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.
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.
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.
31
#include <libgimp/gimp.h>
32
#include <libgimp/gimpui.h>
34
#include "libgimp/stdplugins-intl.h"
37
/* Some useful macros */
38
#define RESPONSE_RESET 1
39
#define RESPONSE_GET_COLORS 2
41
#define PLUG_IN_NAME "plug_in_sample_colorize"
42
#define NUMBER_IN_ARGS 13
43
#define HELP_ID "plug-in-sample-colorize"
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)
50
#define SMP_GRADIENT -444
51
#define SMP_INV_GRADIENT -445
55
#define PREVIEW_SIZE_X 256
56
#define PREVIEW_SIZE_Y 256
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)
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
78
#define REFRESH_DST 0x400
81
#define MC_GET_SAMPLE_COLORS 1
82
#define MC_DST_REMAP 2
83
#define MC_ALL (MC_GET_SAMPLE_COLORS | MC_DST_REMAP)
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 */
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)
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;
124
gint slider_pos[5]; /* positions for the five sliders */
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;
137
guchar color[4]; /* R,G,B,A */
138
gint32 sum_color; /* nr. of sourcepixels with (nearly the same) color */
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 */
154
GimpDrawable *drawable;
161
gint index_alpha; /* 0 == no alpha, 1 == GREYA, 3 == RGBA */
172
gint32 tile_swapcount;
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 */
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;
192
/* Declare a local function.
194
static void query (void);
195
static void run (const gchar *name,
197
const GimpParam *param,
199
GimpParam **return_vals);
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,
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);
225
GimpPlugInInfo PLUG_IN_INFO =
227
NULL, /* init_proc */
228
NULL, /* quit_proc */
229
query, /* query_proc */
238
static GimpParamDef args[]=
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)" }
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";
289
gimp_install_procedure (PLUG_IN_NAME,
290
"Colorize the contents of the specified drawable "
291
"similar to sample drawable",
296
N_("_Sample Colorize..."),
299
G_N_ELEMENTS (args), 0,
302
gimp_plugin_menu_register (PLUG_IN_NAME,
303
"<Image>/Filters/Colors/Map");
307
run (const gchar *name,
309
const GimpParam *param,
311
GimpParam **return_vals)
313
static GimpParam values[1];
314
GimpDrawable *dst_drawable;
315
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
317
GimpRunMode run_mode;
321
l_env = g_getenv ("SAMPLE_COLORIZE_DEBUG");
324
if((*l_env != 'n') && (*l_env != 'N')) g_Sdebug = TRUE;
327
if(g_Sdebug) printf("sample colorize run\n");
328
g_show_progress = FALSE;
330
run_mode = param[0].data.d_int32;
333
*return_vals = values;
335
values[0].type = GIMP_PDB_STATUS;
336
values[0].data.d_status = status;
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;
344
/* Possibly retrieve data from a previous run */
345
gimp_get_data (PLUG_IN_NAME, &g_values);
348
g_values.tol_col_err = 5.5;
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 );
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))
360
gimp_tile_cache_ntiles (TILE_CACHE_SIZE);
364
case GIMP_RUN_INTERACTIVE:
367
gimp_set_data (PLUG_IN_NAME, &g_values, sizeof (t_values));
368
gimp_displays_flush ();
371
case GIMP_RUN_NONINTERACTIVE:
372
if (nparams == NUMBER_IN_ARGS)
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;
387
status = GIMP_PDB_CALLING_ERROR;
391
case GIMP_RUN_WITH_LAST_VALS:
397
status = GIMP_PDB_EXECUTION_ERROR;
400
values[0].data.d_status = status;
402
gimp_drawable_detach (dst_drawable);
405
/* ============================================================================
406
* callback and constraint procedures for the dialog
407
* ============================================================================
411
p_smp_response_callback (GtkWidget *widget,
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;
424
p_levels_update (ALL);
427
case RESPONSE_GET_COLORS:
428
p_smp_get_colors (widget);
431
case GTK_RESPONSE_APPLY:
432
g_show_progress = TRUE;
433
if (p_main_colorize (MC_DST_REMAP) == 0)
435
gimp_displays_flush ();
436
g_show_progress = FALSE;
439
gtk_dialog_set_response_sensitive (GTK_DIALOG (widget),
440
GTK_RESPONSE_APPLY, FALSE);
444
gtk_widget_destroy (widget);
451
p_smp_toggle_callback (GtkWidget *widget,
454
gint32 *toggle_val = (gint32 *) data;
456
if (GTK_TOGGLE_BUTTON (widget)->active) { *toggle_val = TRUE; }
457
else { *toggle_val = FALSE; }
459
if((data == &g_di.sample_show_selection) || (data == &g_di.sample_show_color))
461
p_update_preview (&g_values.sample_id);
465
if((data == &g_di.dst_show_selection) || (data == &g_di.dst_show_color))
467
p_update_preview (&g_values.dst_id);
471
if((data == &g_values.hold_inten) || (data == &g_values.orig_inten)
472
|| (data == &g_values.rnd_subcolors))
474
if(g_di.orig_inten_button)
476
gtk_widget_set_sensitive (g_di.orig_inten_button,g_values.hold_inten);
478
p_refresh_dst_preview (g_di.dst_preview, &g_dst_preview_buffer[0]);
481
if(data == &g_values.guess_missing)
483
if(g_values.guess_missing) { p_guess_missing_colors(); }
484
else { p_fill_missing_colors(); }
485
p_smp_get_colors (NULL);
491
p_smp_sample_combo_callback (GtkWidget *widget,
496
gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), &value);
498
g_values.sample_id = value;
500
if (value == SMP_GRADIENT || value == SMP_INV_GRADIENT)
502
p_get_gradient (value);
503
p_smp_get_colors (NULL);
505
if (g_di.sample_preview)
506
p_clear_preview (g_di.sample_preview);
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);
515
p_update_preview (&g_values.sample_id);
517
gtk_dialog_set_response_sensitive (GTK_DIALOG (g_di.dialog),
518
RESPONSE_GET_COLORS, TRUE);
523
p_smp_dest_combo_callback (GtkWidget *widget,
526
gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget),
529
p_update_preview (&g_values.dst_id);
531
gtk_dialog_set_response_sensitive (GTK_DIALOG (g_di.dialog),
532
RESPONSE_GET_COLORS, TRUE);
536
p_smp_constrain (gint32 image_id,
543
/* dont accept layers from indexed images */
544
if (gimp_drawable_is_indexed (drawable_id))
552
p_smp_adj_lvl_in_max_upd_callback (GtkAdjustment *adjustment,
558
value = CLAMP ((adjustment->value), 1, 255);
560
if (value != g_values.lvl_in_max)
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)
566
g_values.lvl_in_min = g_values.lvl_in_max;
567
upd_flags |= LOW_INPUT;
569
p_levels_update (upd_flags);
574
p_smp_adj_lvl_in_min_upd_callback(GtkAdjustment *adjustment,
580
value = CLAMP ((adjustment->value), 0, 254);
582
if (value != g_values.lvl_in_min)
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)
588
g_values.lvl_in_max = g_values.lvl_in_min;
589
upd_flags |= HIGH_INPUT;
591
p_levels_update (upd_flags);
596
p_smp_text_gamma_upd_callback (GtkAdjustment *adjustment,
601
value = CLAMP ((adjustment->value), 0.1, 10.0);
603
if (value != g_values.lvl_in_gamma)
605
g_values.lvl_in_gamma = value;
606
p_levels_update (INPUT_SLIDERS | INPUT_LEVELS | DRAW | REFRESH_DST);
611
p_smp_adj_lvl_out_max_upd_callback (GtkAdjustment *adjustment,
617
value = CLAMP ((adjustment->value), 1, 255);
619
if (value != g_values.lvl_out_max)
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)
625
g_values.lvl_out_min = g_values.lvl_out_max;
626
upd_flags |= LOW_OUTPUT;
628
p_levels_update (upd_flags);
633
p_smp_adj_lvl_out_min_upd_callback (GtkAdjustment *adjustment,
639
value = CLAMP ((adjustment->value), 0, 254);
641
if (value != g_values.lvl_out_min)
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)
647
g_values.lvl_out_max = g_values.lvl_out_min;
648
upd_flags |= HIGH_OUTPUT;
650
p_levels_update (upd_flags);
654
/* ============================================================================
655
* DIALOG helper procedures
656
* (workers for the updates on the preview widgets)
657
* ============================================================================
661
p_refresh_dst_preview (GtkWidget *preview,
664
guchar l_allrowsbuf[3 * PREVIEW_SIZE_X * PREVIEW_SIZE_Y];
673
l_preview_bpp = PREVIEW_BPP;
674
l_src_bpp = PREVIEW_BPP +1; /* 3 colors + 1 maskbyte */
675
l_src_ptr = src_buffer;
677
l_ptr = l_allrowsbuf;
678
for(l_y = 0; l_y < PREVIEW_SIZE_Y; l_y++)
680
for(l_x = 0; l_x < PREVIEW_SIZE_X; l_x++)
682
if((l_maskbyte = l_src_ptr[3]) == 0)
684
l_ptr[0] = l_src_ptr[0];
685
l_ptr[1] = l_src_ptr[1];
686
l_ptr[2] = l_src_ptr[2];
690
if(g_di.dst_show_color)
692
p_remap_pixel(l_ptr, l_src_ptr, 3);
696
/* l_lum = g_out_trans_tab[g_lvl_trans_tab[LUMINOSITY_1(l_src_ptr)]]; */
697
/* get brightness from (uncolorized) original */
699
l_lum = g_lvl_trans_tab[LUMINOSITY_1(l_src_ptr)];
700
/* get brightness from (uncolorized) original */
707
if (l_maskbyte < 255)
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);
714
l_ptr += l_preview_bpp;
715
l_src_ptr += l_src_bpp;
718
gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
719
0, 0, PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
723
} /* end p_refresh_dst_preview */
726
p_clear_preview (GtkWidget *preview)
728
gimp_preview_area_fill (GIMP_PREVIEW_AREA (preview),
729
0, 0, PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
731
} /* end p_clear_preview */
734
p_update_pv (GtkWidget *preview,
735
gint32 show_selection,
740
guchar l_allrowsbuf[4 * PREVIEW_SIZE_X * PREVIEW_SIZE_Y];
746
gint l_sel_width, l_sel_height;
747
double l_scale_x, l_scale_y;
750
guchar l_maskbytes[4];
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;
761
/* calculate scale factors and offsets */
764
l_sel_width = gdrw->x2 - gdrw->x1;
765
l_sel_height = gdrw->y2 - gdrw->y1;
767
if(l_sel_height > l_sel_width)
769
l_scale_y = (gfloat) l_sel_height / PREVIEW_SIZE_Y;
770
l_scale_x = l_scale_y;
772
((l_sel_width - (PREVIEW_SIZE_X * l_scale_x)) / 2));
777
l_scale_x = (gfloat) l_sel_width / PREVIEW_SIZE_X;
778
l_scale_y = l_scale_x;
781
((l_sel_height - (PREVIEW_SIZE_Y * l_scale_y)) / 2));
786
if (gdrw->drawable->height > gdrw->drawable->width)
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;
795
l_scale_x = (gfloat) gdrw->drawable->width / PREVIEW_SIZE_X;
796
l_scale_y = l_scale_x;
798
l_ofy = (gdrw->drawable->height - (PREVIEW_SIZE_Y * l_scale_y)) / 2;
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; }
808
l_ptr = l_allrowsbuf;
809
for (l_y = 0; l_y < PREVIEW_SIZE_Y; l_y++)
811
for(l_x = 0; l_x < PREVIEW_SIZE_X; l_x++)
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]);
820
p_get_pixel (gdrw->sel_gdrw,
821
l_x2 + gdrw->seldeltax,
822
l_y2 + gdrw->seldeltay,
827
l_maskbytes[0] = 255;
831
l_alpha = l_pixel[gdrw->index_alpha];
832
if (is_color && (gdrw->bpp > 2))
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];
840
if(gdrw->bpp > 2) *l_ptr = LUMINOSITY_1(l_pixel);
841
else *l_ptr = l_pixel[0];
844
l_buf_ptr[1] = l_ptr[1] = *l_ptr;
845
l_buf_ptr[2] = l_ptr[2] = *l_ptr;
847
if (gdrw->index_alpha == 0) /* has no alpha channel */
848
l_buf_ptr[3] = l_ptr[3] = 255;
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) */
857
if (dst_buffer == NULL)
859
gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
860
0, 0, PREVIEW_SIZE_X, PREVIEW_SIZE_Y,
864
gtk_widget_queue_draw (preview);
866
} /* end p_update_pv */
869
p_update_preview (gint32 *id_ptr)
871
GimpDrawable *drawable;
874
if(g_Sdebug) printf("UPD PREVIEWS ID:%d ENABLE_UPD:%d\n", (int)*id_ptr, (int)g_di.enable_preview_update);
876
if(id_ptr == NULL) { return; }
877
if(!g_di.enable_preview_update) { return; }
878
if(p_is_layer_alive(*id_ptr) < 0)
880
/* clear preview on invalid drawable id
881
* (SMP_GRADIENT and SMP_INV_GRADIENT)
883
if(id_ptr == &g_values.sample_id)
885
p_clear_preview(g_di.sample_preview);
887
if(id_ptr == &g_values.dst_id)
889
p_clear_preview(g_di.dst_preview);
894
drawable = gimp_drawable_get (*id_ptr);
896
if(id_ptr == &g_values.sample_id)
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);
901
else if (id_ptr == &g_values.dst_id)
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]);
909
p_end_gdrw (&l_gdrw);
910
} /* end p_update_preview */
913
p_levels_draw_slider (GdkWindow *window,
920
for (y = 0; y < CONTROL_HEIGHT; y++)
921
gdk_draw_line(window, fill_gc, xpos - y / 2, y,
924
gdk_draw_line(window, border_gc, xpos, 0,
925
xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
927
gdk_draw_line(window, border_gc, xpos, 0,
928
xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
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 */
936
p_levels_erase_slider (GdkWindow *window,
939
gdk_window_clear_area (window, xpos - (CONTROL_HEIGHT - 1) / 2, 0,
940
CONTROL_HEIGHT - 1, CONTROL_HEIGHT);
941
} /* end p_levels_erase_slider */
944
p_smp_get_colors (GtkWidget *dialog)
947
guchar buffer[3 * DA_WIDTH * GRADIENT_HEIGHT];
949
p_update_preview (&g_values.sample_id);
953
if (p_main_colorize (MC_GET_SAMPLE_COLORS) >= 0) /* do not colorize, just analyze sample colors */
955
gtk_dialog_set_response_sensitive (GTK_DIALOG (g_di.dialog),
956
GTK_RESPONSE_APPLY, TRUE);
959
for (i = 0; i < GRADIENT_HEIGHT; i++)
961
memcpy (buffer+i*3*DA_WIDTH, g_sample_color_tab, 3*DA_WIDTH);
963
p_update_preview (&g_values.dst_id);
965
gimp_preview_area_draw (GIMP_PREVIEW_AREA (g_di.sample_colortab_preview),
966
0, 0, DA_WIDTH, GRADIENT_HEIGHT,
974
p_levels_update (gint update)
978
if(g_Sdebug) printf("p_levels_update: update reques %x\n", update);
980
/* Recalculate the transfer array */
981
p_calculate_level_transfers();
982
if (update & REFRESH_DST)
984
p_refresh_dst_preview(g_di.dst_preview, &g_dst_preview_buffer[0]);
987
/* update the spinbutton entry widgets */
988
if (update & LOW_INPUT)
990
gtk_adjustment_set_value (g_di.adj_lvl_in_min,
991
g_values.lvl_in_min);
995
gtk_adjustment_set_value (g_di.adj_lvl_in_gamma,
996
g_values.lvl_in_gamma);
998
if (update & HIGH_INPUT)
1000
gtk_adjustment_set_value (g_di.adj_lvl_in_max,
1001
g_values.lvl_in_max);
1003
if (update & LOW_OUTPUT)
1005
gtk_adjustment_set_value (g_di.adj_lvl_out_min,
1006
g_values.lvl_out_min);
1008
if (update & HIGH_OUTPUT)
1010
gtk_adjustment_set_value (g_di.adj_lvl_out_max,
1011
g_values.lvl_out_max);
1013
if (update & INPUT_LEVELS)
1015
guchar buffer[DA_WIDTH * GRADIENT_HEIGHT];
1016
for (i = 0; i < GRADIENT_HEIGHT; i++)
1018
memcpy (buffer+DA_WIDTH*i, g_lvl_trans_tab, DA_WIDTH);
1020
gimp_preview_area_draw (GIMP_PREVIEW_AREA (g_di.in_lvl_gray_preview),
1021
0, 0, DA_WIDTH, GRADIENT_HEIGHT,
1027
if (update & INPUT_SLIDERS)
1029
gdouble width, mid, tmp;
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]);
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);
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);
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]);
1057
if (update & OUTPUT_SLIDERS)
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]);
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);
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]);
1074
} /* end p_levels_update */
1077
p_level_in_events (GtkWidget *widget,
1081
GdkEventButton *bevent;
1082
GdkEventMotion *mevent;
1084
double width, mid, tmp;
1087
gint update = FALSE;
1090
switch (event->type)
1093
if(g_Sdebug) printf("EVENT: GDK_EXPOSE\n");
1094
if (widget == g_di.in_lvl_drawarea)
1095
p_levels_update (INPUT_SLIDERS);
1098
case GDK_BUTTON_PRESS:
1099
if(g_Sdebug) printf("EVENT: GDK_BUTTON_PRESS\n");
1100
gtk_grab_add (widget);
1101
bevent = (GdkEventButton *) event;
1103
distance = G_MAXINT;
1104
for (i = 0; i < 3; i++)
1106
if (fabs (bevent->x - g_di.slider_pos[i]) < distance)
1108
g_di.active_slider = i;
1109
distance = fabs (bevent->x - g_di.slider_pos[i]);
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)
1122
case 0: /* low input */
1123
p_levels_update (LOW_INPUT | GAMMA | DRAW);
1126
p_levels_update (GAMMA);
1128
case 2: /* high input */
1129
p_levels_update (HIGH_INPUT | GAMMA | DRAW);
1133
p_refresh_dst_preview(g_di.dst_preview, &g_dst_preview_buffer[0]);
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);
1144
if(g_Sdebug) printf("EVENT: default\n");
1150
if(g_Sdebug) printf("EVENT: ** update **\n");
1151
switch (g_di.active_slider)
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);
1160
width = (double) (g_di.slider_pos[2] - g_di.slider_pos[0]) / 2.0;
1161
mid = g_di.slider_pos[0] + width;
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);
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);
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);
1179
p_levels_update (INPUT_SLIDERS | INPUT_LEVELS | DRAW);
1183
} /* end p_level_in_events */
1186
p_level_out_events (GtkWidget *widget,
1190
GdkEventButton *bevent;
1191
GdkEventMotion *mevent;
1194
gint update = FALSE;
1196
switch (event->type)
1199
if(g_Sdebug) printf("OUT_EVENT: GDK_EXPOSE\n");
1200
if (widget == g_di.sample_drawarea)
1201
p_levels_update (OUTPUT_SLIDERS);
1204
case GDK_BUTTON_PRESS:
1205
if(g_Sdebug) printf("OUT_EVENT: GDK_BUTTON_PRESS\n");
1206
bevent = (GdkEventButton *) event;
1208
distance = G_MAXINT;
1209
for (i = 3; i < 5; i++)
1211
if (fabs (bevent->x - g_di.slider_pos[i]) < distance)
1213
g_di.active_slider = i;
1214
distance = fabs (bevent->x - g_di.slider_pos[i]);
1222
case GDK_BUTTON_RELEASE:
1223
if(g_Sdebug) printf("OUT_EVENT: GDK_BUTTON_RELEASE\n");
1224
switch (g_di.active_slider)
1226
case 3: /* low output */
1227
p_levels_update (LOW_OUTPUT | DRAW);
1229
case 4: /* high output */
1230
p_levels_update (HIGH_OUTPUT | DRAW);
1234
p_refresh_dst_preview(g_di.dst_preview, &g_dst_preview_buffer[0]);
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);
1245
if(g_Sdebug) printf("OUT_EVENT: default\n");
1251
if(g_Sdebug) printf("OUT_EVENT: ** update **\n");
1252
switch (g_di.active_slider)
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);
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);
1267
p_levels_update (OUTPUT_SLIDERS | OUTPUT_LEVELS | DRAW);
1271
} /* end p_level_out_events */
1274
/* ============================================================================
1276
* The Interactive Dialog
1277
* ============================================================================
1287
GtkWidget *check_button;
1290
GtkWidget *spinbutton;
1294
/* set flags for check buttons from mode value bits */
1295
if (g_Sdebug) g_print ("p_smp_dialog START\n");
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;
1306
gimp_ui_init ("sample_colorize", TRUE);
1309
g_di.dialog = dialog =
1310
gimp_dialog_new (_("Sample Colorize"), "sample_colorize",
1312
gimp_standard_help_func, HELP_ID,
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,
1321
g_signal_connect (dialog, "response",
1322
G_CALLBACK (p_smp_response_callback),
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);
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);
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),
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);
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);
1357
combo = gimp_layer_combo_box_new (p_smp_constrain, NULL);
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,
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,
1370
gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), g_values.sample_id,
1371
G_CALLBACK (p_smp_sample_combo_callback),
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);
1381
hbox = gtk_hbox_new (FALSE, 6);
1382
gtk_table_attach (GTK_TABLE (table), hbox, 0, 2, l_ty, l_ty + 1,
1384
gtk_widget_show (hbox);
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);
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);
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);
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);
1408
hbox = gtk_hbox_new (FALSE, 6);
1409
gtk_table_attach (GTK_TABLE (table), hbox, 3, 5, l_ty, l_ty + 1,
1411
gtk_widget_show (hbox);
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);
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);
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);
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);
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);
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);
1451
/* Preview (Sample)*/
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);
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);
1467
/* The levels graylevel prevev */
1468
frame = gtk_frame_new (NULL);
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);
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);
1482
g_signal_connect (g_di.in_lvl_gray_preview, "event",
1483
G_CALLBACK (p_level_in_events),
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);
1494
g_signal_connect (g_di.in_lvl_drawarea, "event",
1495
G_CALLBACK (p_level_in_events),
1498
gtk_widget_show(vbox2);
1499
gtk_widget_show(frame);
1501
/* The sample_colortable prevev */
1502
frame = gtk_frame_new (NULL);
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);
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);
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);
1523
g_signal_connect (g_di.sample_drawarea, "event",
1524
G_CALLBACK (p_level_out_events),
1527
gtk_widget_show(vbox2);
1528
gtk_widget_show(frame);
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,
1538
label = gtk_label_new (_("Input levels:"));
1539
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1540
gtk_widget_show (label);
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);
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);
1551
g_signal_connect (g_di.adj_lvl_in_min, "value_changed",
1552
G_CALLBACK (p_smp_adj_lvl_in_min_upd_callback),
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);
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);
1564
g_signal_connect (g_di.adj_lvl_in_gamma, "value_changed",
1565
G_CALLBACK (p_smp_text_gamma_upd_callback),
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);
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);
1577
g_signal_connect (g_di.adj_lvl_in_max, "value_changed",
1578
G_CALLBACK (p_smp_adj_lvl_in_max_upd_callback),
1581
gtk_widget_show (hbox);
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,
1588
label = gtk_label_new (_("Output Levels:"));
1589
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1590
gtk_widget_show (label);
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);
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);
1601
g_signal_connect (g_di.adj_lvl_out_min, "value_changed",
1602
G_CALLBACK (p_smp_adj_lvl_out_min_upd_callback),
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);
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);
1614
g_signal_connect (g_di.adj_lvl_out_max, "value_changed",
1615
G_CALLBACK (p_smp_adj_lvl_out_max_upd_callback),
1618
gtk_widget_show (hbox);
1622
hbox = gtk_hbox_new (FALSE, 6);
1623
gtk_table_attach (GTK_TABLE (table), hbox, 0, 2, l_ty, l_ty+1,
1625
gtk_widget_show (hbox);
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);
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);
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);
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);
1651
hbox = gtk_hbox_new (FALSE, 4);
1652
gtk_table_attach (GTK_TABLE (table), hbox, 3, 5, l_ty, l_ty+1,
1654
gtk_widget_show (hbox);
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);
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);
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);
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);
1680
gtk_widget_show (table);
1681
gtk_widget_show (frame);
1683
gtk_widget_show (dialog);
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);
1692
} /* end p_smp_dialog */
1694
/* -----------------------------
1695
* DEBUG print procedures START
1696
* -----------------------------
1700
p_print_ppm (const gchar *ppm_name)
1706
t_samp_color_elem *col_ptr;
1708
if (ppm_name == NULL)
1711
fp = fopen (ppm_name, "w");
1714
fprintf(fp, "P3\n# CREATOR: Gimp sample coloros\n256 256\n255\n");
1715
for(l_idx = 0; l_idx < 256; l_idx++)
1717
col_ptr = g_lum_tab[l_idx].col_ptr;
1719
for(l_cnt = 0; l_cnt < 256; l_cnt++)
1721
l_r = l_g = l_b = 0;
1724
if((col_ptr->sum_color > 0) && (l_cnt != 20))
1726
l_r = (gint) col_ptr->color[0];
1727
l_g = (gint) col_ptr->color[1];
1728
l_b = (gint) col_ptr->color[2];
1731
if (l_cnt > 20) col_ptr = col_ptr->next;
1733
fprintf(fp, "%d %d %d\n", l_r, l_g, l_b);
1741
p_print_color_list (FILE *fp, t_samp_color_elem *col_ptr)
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);
1755
col_ptr = col_ptr->next;
1760
p_print_table (FILE *fp)
1764
if(fp == NULL) return;
1766
fprintf(fp, "---------------------------\n");
1767
fprintf(fp, "p_print_table\n");
1768
fprintf(fp, "---------------------------\n");
1770
for(l_idx = 0; l_idx < 256; l_idx++)
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);
1778
p_print_transtable (FILE *fp)
1785
fprintf(fp, "---------------------------\n");
1786
fprintf(fp, "p_print_transtable\n");
1787
fprintf(fp, "---------------------------\n");
1789
for(l_idx = 0; l_idx < 256; l_idx++)
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]);
1797
p_print_values (FILE *fp)
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);
1813
fprintf(fp, "g_values.tol_col_err :%f\n", g_values.tol_col_err);
1816
/* -----------------------------
1817
* DEBUG print procedures END
1818
* -----------------------------
1821
/* DEBUG: read values from file */
1823
p_get_filevalues (void)
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;
1835
g_values.tol_col_err = 5.5;
1837
l_fp = fopen("sample_colorize.values", "r");
1840
fgets(&l_buf[0], 999, l_fp);
1841
sscanf (&l_buf[0], "%f", &g_values.tol_col_err);
1845
printf("g_values.tol_col_err :%f\n", g_values.tol_col_err);
1846
} /* end p_get_filevalues */
1849
p_color_error (guchar ref_red, guchar ref_green, guchar ref_blue,
1850
guchar cmp_red, guchar cmp_green, guchar cmp_blue)
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;
1860
l_fs = abs(ref_h - cmp_h);
1863
/* 2. add Red Color differences */
1864
l_fs = abs(ref_red - cmp_red);
1865
l_ff += (l_fs * l_fs);
1867
/* 3. add Green Color differences */
1868
l_fs = abs(ref_green - cmp_green);
1869
l_ff += (l_fs * l_fs);
1871
/* 4. add Blue Color differences */
1872
l_fs = abs(ref_blue - cmp_blue);
1873
l_ff += (l_fs * l_fs);
1875
return((gint32)(l_ff));
1876
} /* end p_color_error */
1879
p_provide_tile (t_GDRW *gdrw,
1887
if ( col != gdrw->tile_col || row != gdrw->tile_row || !gdrw->tile )
1891
gimp_tile_unref (gdrw->tile, gdrw->tile_dirty);
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);
1901
gdrw->tile_swapcount++;
1907
printf("\np_provide_tile: row: %d col: %d data:", (int)row, (int)col);
1909
ptr = gdrw->tile->data;
1910
for (i = 0; i < 16; i++)
1912
printf(" %d", (int)(*ptr));
1919
} /* end p_provide_tile */
1922
* return light gray transparent pixel if out of bounds
1923
* (should occur in the previews only)
1926
p_get_pixel (t_GDRW *gdrw,
1936
|| (x > gdrw->drawable->width -1)
1938
|| (y > gdrw->drawable->height - 1))
1940
pixel[0] = pixel[1] = pixel[2] = 200;
1945
col = x / gdrw->tile_width;
1946
row = y / gdrw->tile_height;
1947
offx = x % gdrw->tile_width;
1948
offy = y % gdrw->tile_height;
1950
p_provide_tile (gdrw, col, row, gdrw->shadow);
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);
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]);
1964
p_clear_tables (void)
1968
for (l_idx = 0; l_idx < 256; l_idx++)
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;
1980
/* free all allocated sample colors in table g_lum_tab */
1982
p_free_colors (void)
1986
t_samp_color_elem *l_col_ptr;
1987
t_samp_color_elem *l_next_ptr;
1989
for (l_lum = 0; l_lum < 256; l_lum++)
1991
for (l_col_ptr = g_lum_tab[l_lum].col_ptr;
1993
l_col_ptr = l_next_ptr)
1995
l_next_ptr = (t_samp_color_elem *)l_col_ptr->next;
1999
g_lum_tab[l_lum].col_ptr = NULL;
2000
g_lum_tab[l_lum].all_samples = 0;
2002
} /* end p_free_colors */
2004
/* setup lum transformer table according to input_levels, gamma and output levels
2005
* (uses sam algorithm as GIMP Level Tool)
2008
p_calculate_level_transfers (void)
2012
gint l_in_min, l_in_max;
2013
gint l_out_min, l_out_max;
2015
if(g_values.lvl_in_max >= g_values.lvl_in_min)
2017
l_in_max = g_values.lvl_in_max;
2018
l_in_min = g_values.lvl_in_min;
2022
l_in_max = g_values.lvl_in_min;
2023
l_in_min = g_values.lvl_in_max;
2025
if(g_values.lvl_out_max >= g_values.lvl_out_min)
2027
l_out_max = g_values.lvl_out_max;
2028
l_out_min = g_values.lvl_out_min;
2032
l_out_max = g_values.lvl_out_min;
2033
l_out_min = g_values.lvl_out_max;
2036
/* Recalculate the levels arrays */
2037
for (i = 0; i < 256; i++)
2039
/* determine input intensity */
2040
inten = (double) i / 255.0;
2041
if (g_values.lvl_in_gamma != 0.0)
2043
inten = pow (inten, (1.0 / g_values.lvl_in_gamma));
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);
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);
2055
} /* end p_calculate_level_transfers */
2059
/* alloc and init new col Element */
2060
static t_samp_color_elem *
2061
p_new_samp_color (const guchar *color)
2063
t_samp_color_elem *l_col_ptr;
2065
l_col_ptr = g_new0 (t_samp_color_elem, 1);
2066
if(l_col_ptr == NULL)
2068
printf("Error: cant get Memory\n");
2072
memcpy (&l_col_ptr->color[0], color, 4);
2074
l_col_ptr->sum_color = 1;
2075
l_col_ptr->next = NULL;
2078
} /* end p_new_samp_color */
2081
/* store color in g_lum_tab */
2083
p_add_color (const guchar *color)
2086
t_samp_color_elem *l_col_ptr;
2088
l_lum = LUMINOSITY_1(color);
2090
g_lum_tab[l_lum].all_samples++;
2091
g_lum_tab[l_lum].from_sample = TRUE;
2093
/* check if exactly the same color is already in the list */
2094
for(l_col_ptr = g_lum_tab[l_lum].col_ptr;
2096
l_col_ptr = (t_samp_color_elem *)l_col_ptr->next)
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]))
2102
l_col_ptr->sum_color++;
2107
/* alloc and init element for the new color */
2108
l_col_ptr = p_new_samp_color(color);
2110
if(l_col_ptr != NULL)
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;
2116
} /* end p_add_color */
2118
/* sort Sublists (color) by descending sum_color in g_lum_tab
2121
p_sort_color (gint32 lum)
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;
2130
l_sorted_col_ptr = NULL;
2133
while (g_lum_tab[lum].col_ptr != NULL)
2139
for (l_col_ptr = g_lum_tab[lum].col_ptr;
2141
l_col_ptr = l_next_ptr)
2143
l_next_ptr = l_col_ptr->next;
2144
if (l_col_ptr->sum_color > l_min)
2146
/* check min value for next loop */
2147
if((l_col_ptr->sum_color < l_min_next) || (l_min == l_min_next))
2149
l_min_next = l_col_ptr->sum_color;
2151
l_prev_ptr = l_col_ptr;
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;
2159
/* remove element from list */
2160
if(l_prev_ptr == NULL)
2162
g_lum_tab[lum].col_ptr = l_next_ptr; /* remove 1.st element */
2166
l_prev_ptr->next = l_next_ptr;
2173
g_lum_tab[lum].col_ptr = l_sorted_col_ptr;
2174
} /* end p_sort_color */
2177
p_cnt_same_sample_colortones (t_samp_color_elem *ref_ptr,
2182
gint32 l_col_error, l_ref_error;
2183
t_samp_color_elem *l_col_ptr;
2186
if (prev_color != NULL)
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]);
2192
/* collect colors that are (nearly) the same */
2193
for(l_col_ptr = ref_ptr->next;
2195
l_col_ptr = (t_samp_color_elem *)l_col_ptr->next)
2197
if(l_col_ptr->sum_color < 1)
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]);
2204
if (l_col_error <= g_tol_col_err )
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;
2211
if(prev_color != NULL)
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)
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;
2224
} /* end p_cnt_same_sample_colortones */
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
2231
p_ideal_samples (void)
2234
t_samp_color_elem *l_col_ptr;
2237
guchar l_color_tone[4];
2238
guchar l_color_ideal[4];
2239
gint l_csum, l_maxsum;
2242
for(l_lum = 0; l_lum < 256; l_lum++)
2244
if(g_lum_tab[l_lum].col_ptr == NULL) { continue; }
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);
2252
/* collect colors that are (nearly) the same */
2255
l_col_ptr = (t_samp_color_elem *)l_col_ptr->next)
2258
if(l_col_ptr->sum_color > 0)
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)
2265
memcpy(&l_color_ideal[0], &l_color_tone[0], 3);
2270
l_col_ptr->sum_color = abs(l_col_ptr->sum_color);
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);
2278
} /* end p_ideal_samples */
2281
p_guess_missing_colors (void)
2287
guchar l_lo_color[4];
2288
guchar l_hi_color[4];
2289
guchar l_new_color[4];
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;
2302
l_new_color[3] = 255;
2304
for(l_lum = 0; l_lum < 256; l_lum++)
2306
if((g_lum_tab[l_lum].col_ptr == NULL) || (g_lum_tab[l_lum].from_sample == FALSE))
2310
for(l_idx = l_lum; l_idx < 256; l_idx++)
2312
if((g_lum_tab[l_idx].col_ptr != NULL) && (g_lum_tab[l_idx].from_sample))
2314
memcpy(&l_hi_color[0], &g_sample_color_tab[l_idx + l_idx + l_idx], 3);
2319
l_hi_color[0] = 255;
2320
l_hi_color[1] = 255;
2321
l_hi_color[2] = 255;
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);
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]);
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);
2344
memcpy (&l_lo_color[0], &g_sample_color_tab [3 * l_lum], 3);
2346
} /* end p_guess_missing_colors */
2349
p_fill_missing_colors (void)
2355
guchar l_lo_color[4];
2356
guchar l_hi_color[4];
2357
guchar l_new_color[4];
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;
2370
l_new_color[3] = 255;
2373
for(l_lum = 0; l_lum < 256; l_lum++)
2375
if((g_lum_tab[l_lum].col_ptr == NULL) || (g_lum_tab[l_lum].from_sample == FALSE))
2379
for(l_idx = l_lum; l_idx < 256; l_idx++)
2381
if((g_lum_tab[l_idx].col_ptr != NULL) && (g_lum_tab[l_idx].from_sample))
2383
memcpy (&l_hi_color[0],
2384
&g_sample_color_tab[l_idx + l_idx + l_idx], 3);
2391
* l_hi_color[0] = 255;
2392
* l_hi_color[1] = 255;
2393
* l_hi_color[2] = 255;
2395
memcpy(&l_hi_color[0], &l_lo_color[0], 3);
2400
if((l_lum > (l_lo_idx + ((l_idx - l_lo_idx ) / 2)))
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];
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];
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);
2422
memcpy(&l_lo_color[0], &g_sample_color_tab[3 * l_lum], 3);
2425
} /* end p_fill_missing_colors */
2427
/* get 256 samples of active gradient (optional in invers order) */
2429
p_get_gradient (gint mode)
2434
gdouble *f_samp; /* float samples */
2439
name = gimp_context_get_gradient ();
2441
gimp_gradient_get_uniform_samples (name, 256 /* n_samples */,
2442
mode == SMP_INV_GRADIENT,
2443
&n_f_samples, &f_samples);
2447
for (l_lum = 0; l_lum < 256; l_lum++)
2449
f_samp = &f_samples[l_lum * 4];
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;
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;
2462
} /* end p_get_gradient */
2465
p_is_layer_alive(gint32 drawable_id)
2467
/* return -1 if layer has become invalid */
2469
if (drawable_id < 0)
2474
if (gimp_drawable_get_image (drawable_id) < 0)
2476
printf ("sample colorize: unknown layer_id %d (Image closed?)\n",
2485
p_end_gdrw(t_GDRW *gdrw)
2491
gimp_tile_unref (gdrw->tile, gdrw->tile_dirty);
2495
sel_gdrw = (t_GDRW*)(gdrw->sel_gdrw);
2500
gimp_tile_unref (sel_gdrw->tile, sel_gdrw->tile_dirty);
2501
sel_gdrw->tile = NULL;
2503
gdrw->sel_gdrw = NULL;
2508
p_init_gdrw (t_GDRW *gdrw,
2509
GimpDrawable *drawable,
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;
2521
if(g_Sdebug) printf("\np_init_gdrw: drawable %p ID: %d\n", drawable, (int)drawable->drawable_id);
2523
gdrw->drawable = drawable;
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 */
2534
gimp_drawable_mask_bounds (drawable->drawable_id,
2535
&gdrw->x1, &gdrw->y1, &gdrw->x2, &gdrw->y2);
2537
gdrw->bpp = drawable->bpp;
2538
if (gimp_drawable_has_alpha(drawable->drawable_id))
2540
/* index of the alpha channelbyte {1|3} */
2541
gdrw->index_alpha = gdrw->bpp -1;
2545
gdrw->index_alpha = 0; /* there is no alpha channel */
2548
l_image_id = gimp_drawable_get_image (drawable->drawable_id);
2550
/* check and see if we have a selection mask */
2551
l_sel_channel_id = gimp_image_get_selection (l_image_id);
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 );
2561
gimp_selection_bounds (l_image_id, &non_empty, &l_x1, &l_y1, &l_x2, &l_y2);
2563
if (non_empty && (l_sel_channel_id >= 0))
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);
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;
2585
/* offset delta between drawable and selection
2586
* (selection always has image size and should always have offsets of 0 )
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;
2592
gdrw->sel_gdrw = (t_GDRW *) l_sel_gdrw;
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 );
2600
printf("p_init_gdrw: SEL_DELTA x: %d y: %d\n", (int)gdrw->seldeltax, (int)gdrw->seldeltay );
2605
gdrw->sel_gdrw = NULL; /* selection is FALSE */
2609
/* analyze the colors in the sample_drawable */
2611
p_sample_analyze (t_GDRW *sample_gdrw)
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;
2618
float l_progress_step;
2619
float l_progress_max;
2626
l_sample_pixels = 0;
2629
l_progress_max = (sample_gdrw->x2 - sample_gdrw->x1);
2630
l_progress_step = 1.0 / l_progress_max;
2632
if(g_show_progress) gimp_progress_init (_("Sample Analyze..."));
2635
if(g_Sdebug) prot_fp = fopen("sample_colors.dump", "w");
2636
p_print_values(prot_fp);
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)
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);
2652
for(l_row = l_first_row; l_row <= l_last_row; l_row++)
2654
for(l_col = l_first_col; l_col <= l_last_col; l_col++)
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;
2661
for( ; l_x < l_x2; l_x++)
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 ;
2668
/* printf("X: %4d Y:%4d Y2:%4d\n", (int)l_x, (int)l_y, (int)l_y2); */
2670
for( ; l_y < l_y2; l_y++)
2672
/* check if the pixel is in the selection */
2673
if(sample_gdrw->sel_gdrw)
2675
p_get_pixel(sample_gdrw->sel_gdrw,
2676
(l_x + sample_gdrw->seldeltax),
2677
(l_y + sample_gdrw->seldeltay),
2686
p_get_pixel(sample_gdrw, l_x, l_y, &color[0]);
2688
/* if this is a visible (non-transparent) pixel */
2689
if((sample_gdrw->index_alpha < 1) || (color[sample_gdrw->index_alpha] != 0))
2691
/* store color in the sublists of g_lum_tab */
2692
p_add_color(&color[0]);
2696
if(g_show_progress) gimp_progress_update (l_progress += l_progress_step);
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);
2703
p_print_table(prot_fp);
2705
if(g_Sdebug) p_print_ppm("sample_color_all.ppm");
2707
/* findout ideal sample colors for each brightness intensity (lum)
2708
* and set g_sample_color_tab to the ideal colors.
2711
p_calculate_level_transfers ();
2712
if(g_values.guess_missing) { p_guess_missing_colors(); }
2713
else { p_fill_missing_colors(); }
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);
2720
/* check if there was at least one visible pixel */
2721
if (l_sample_pixels == 0)
2723
printf("Error: Source sample has no visible Pixel\n");
2727
} /* end p_sample_analyze */
2730
p_rnd_remap (gint32 lum,
2731
guchar *mapped_color)
2733
t_samp_color_elem *l_col_ptr;
2738
if (g_lum_tab[lum].all_samples > 1)
2740
l_rnd = g_random_int_range (0, g_lum_tab[lum].all_samples);
2744
for (l_col_ptr = g_lum_tab[lum].col_ptr;
2746
l_col_ptr = (t_samp_color_elem *)l_col_ptr->next)
2748
l_ct += l_col_ptr->sum_color;
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);
2755
memcpy (mapped_color, &l_col_ptr->color[0], 3);
2762
memcpy (mapped_color, &g_sample_color_tab[lum + lum + lum], 3);
2766
p_remap_pixel (guchar *pixel,
2767
const guchar *original,
2770
guchar mapped_color[4];
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;
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)
2782
p_rnd_remap (l_lum, mapped_color);
2786
memcpy (mapped_color, &g_sample_color_tab[3 * l_lum], 3);
2789
if (g_values.hold_inten)
2791
if (g_values.orig_inten)
2793
l_orig_lum = LUMINOSITY_0(original);
2797
l_orig_lum = 100.0 * g_lvl_trans_tab[LUMINOSITY_1(original)];
2800
l_mapped_lum = LUMINOSITY_0 (mapped_color);
2802
if (l_mapped_lum == 0)
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];
2811
/* Calculate theoretical RGB to reach given intensity LUM
2812
* value (l_orig_lum)
2814
l_mr = mapped_color[0];
2815
l_mg = mapped_color[1];
2816
l_mb = mapped_color[2];
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;
2825
else if (l_mg > 0.0)
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;
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;
2840
/* on overflow: Calculate real RGB values
2841
* (this may change the hue and saturation,
2842
* more and more into white)
2847
if ((l_blu < 255) && (l_grn < 255))
2849
/* overflow in the red channel (compensate with green and blu) */
2850
l_dlum = (l_red - 255.0) * 30.0;
2853
l_dg = l_dlum / (59.0 + (11.0 * l_mb / l_mg));
2854
l_db = l_dg * l_mb / l_mg;
2858
l_db = l_dlum / (11.0 + (59.0 * l_mg / l_mb));
2859
l_dg = l_db * l_mg / l_mb;
2863
l_db = l_dlum / (11.0 + 59.0);
2864
l_dg = l_dlum / (59.0 + 11.0);
2876
l_blu = (l_orig_lum - 22695) / 11; /* 22695 = (255*30) + (255*59) */
2881
l_grn = (l_orig_lum - 10455) / 59; /* 10455 = (255*30) + (255*11) */
2884
else if (l_grn > 255)
2886
if ((l_blu < 255) && (l_red < 255))
2888
/* overflow in the green channel (compensate with red and blu) */
2889
l_dlum = (l_grn - 255.0) * 59.0;
2893
l_dr = l_dlum / (30.0 + (11.0 * l_mb / l_mr));
2894
l_db = l_dr * l_mb / l_mr;
2898
l_db = l_dlum / (11.0 + (30.0 * l_mr / l_mb));
2899
l_dr = l_db * l_mr / l_mb;
2903
l_db = l_dlum / (11.0 + 30.0);
2904
l_dr = l_dlum / (30.0 + 11.0);
2916
l_blu = (l_orig_lum - 22695) / 11; /* 22695 = (255*59) + (255*30) */
2921
l_red = (l_orig_lum - 17850) / 30; /* 17850 = (255*59) + (255*11) */
2924
else if (l_blu > 255)
2926
if ((l_red < 255) && (l_grn < 255))
2928
/* overflow in the blue channel (compensate with green and red) */
2929
l_dlum = (l_blu - 255.0) * 11.0;
2933
l_dg = l_dlum / (59.0 + (30.0 * l_mr / l_mg));
2934
l_dr = l_dg * l_mr / l_mg;
2938
l_dr = l_dlum / (30.0 + (59.0 * l_mg / l_mr));
2939
l_dg = l_dr * l_mg / l_mr;
2943
l_dr = l_dlum / (30.0 + 59.0);
2944
l_dg = l_dlum / (59.0 + 30.0);
2956
l_red = (l_orig_lum - 17850) / 30; /* 17850 = (255*11) + (255*59) */
2961
l_grn = (l_orig_lum - 10455) / 59; /* 10455 = (255*11) + (255*30) */
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);
2971
/* set colorized pixel in shadow pr */
2972
memcpy (pixel, &mapped_color[0], bpp2);
2976
colorize_func (const guchar *src,
2981
gboolean has_alpha = GPOINTER_TO_INT (data);
2986
dest[bpp] = src[bpp];
2989
p_remap_pixel (dest, src, bpp);
2993
p_colorize_drawable (gint32 drawable_id)
2995
GimpDrawable *drawable;
2998
drawable = gimp_drawable_get (drawable_id);
2999
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
3001
if (g_show_progress)
3002
gimp_progress_init (_("Remap Colorized..."));
3004
gimp_rgn_iterate2 (drawable, 0 /* unused */, colorize_func,
3005
GINT_TO_POINTER (has_alpha));
3007
if (g_show_progress)
3008
gimp_progress_update (0.0);
3011
/* colorize dst_drawable like sample_drawable */
3013
p_main_colorize (gint mc_flags)
3015
GimpDrawable *dst_drawable;
3016
GimpDrawable *sample_drawable;
3017
t_GDRW l_sample_gdrw;
3022
if(g_Sdebug) p_get_filevalues (); /* for debugging: read values from file */
3023
sample_drawable = NULL;
3024
dst_drawable = NULL;
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;
3033
if (mc_flags & MC_GET_SAMPLE_COLORS)
3035
l_id = g_values.sample_id;
3036
if ((l_id == SMP_GRADIENT) || (l_id == SMP_INV_GRADIENT))
3038
p_get_gradient (l_id);
3042
if (p_is_layer_alive (l_id) < 0)
3047
sample_drawable = gimp_drawable_get (l_id);
3048
p_init_gdrw (&l_sample_gdrw, sample_drawable, FALSE, FALSE);
3050
l_rc = p_sample_analyze (&l_sample_gdrw);
3054
if ((mc_flags & MC_DST_REMAP) && (l_rc == 0))
3056
if (p_is_layer_alive (g_values.dst_id) < 0)
3060
dst_drawable = gimp_drawable_get (g_values.dst_id);
3061
if (gimp_drawable_is_gray (g_values.dst_id))
3063
if (mc_flags & MC_DST_REMAP)
3065
gimp_image_convert_rgb (gimp_drawable_get_image (g_values.dst_id));
3069
p_colorize_drawable (dst_drawable->drawable_id);
3072
if (sample_drawable)
3074
p_end_gdrw (&l_sample_gdrw);