gimp/plug-ins/common/fp.c

2134 lines
65 KiB
C
Raw Normal View History

/*
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This is a plug-in for the GIMP.
*
* Copyright (C) Pavel Grinfeld (pavel@ml.com)
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include <libgimp/gimp.h>
2004-05-06 17:59:21 +00:00
#include <libgimp/gimpui.h>
gimprc.in replaced "color-cube" by "min-colors". 2000-04-30 Michael Natterer <mitch@gimp.org> * gimprc.in * app/gimprc.[ch]: replaced "color-cube" by "min-colors". * app/app_procs.c: read unitrc/gimprc before displaying the splash. * app/colormaps.c: set min_colors and install_cmap before initializing GdkRGB. * app/gimprc.[ch] * app/gimpunit.c: don't call the splash's progress_update function. * app/plug_in.c: pass min_colors instead of color_cube to plugins. * app/preferences_dialog.c: widget for min_colors. * libgimp/gimp.[ch]: s/color_cube/min_colors/ but left gimp_color_cube() there for source level compatibility. * libgimp/gimpprotocol.[ch]: changed the GPConfig message accordinly and increased the gimp protocol version number because the change breaks binary compatibility. Also actually pass the use_xshm variable over the wire (was only in the GPConfig struct before). Was it the right thing to do to increase the version number?? * libgimp/gimpui.c (gimp_ui_init): use the same code as the app for initializing GdkRGB. Never explicitly activate Gdk's SHM usage (only switch it off). * app/main.c * libgimp/gimp.c: reverted the handling of all signals except SIGCHLD back to plain old signal() because those signals are fatal anyway and sigaction() as used by gimp_signal_*() made debugging (stacktrace) impossible. * plug-ins/AlienMap/AlienMap.c * plug-ins/AlienMap2/AlienMap2.c * plug-ins/FractalExplorer/Dialogs.c * plug-ins/bmp/bmp.c * plug-ins/borderaverage/borderaverage.c * plug-ins/dbbrowser/dbbrowser.c * plug-ins/faxg3/faxg3.c * plug-ins/fits/fits.c * plug-ins/flame/flame.c * plug-ins/fp/fp.c * plug-ins/fp/fp_gtk.c * plug-ins/gdyntext/Makefile.am * plug-ins/gdyntext/gdyntext_ui.c * plug-ins/gfig/gfig.c * plug-ins/gflare/gflare.c * plug-ins/gfli/gfli.c * plug-ins/gimpressionist/gimpressionist.c * plug-ins/helpbrowser/helpbrowser.c * plug-ins/ifscompose/ifscompose.c * plug-ins/imagemap/Makefile.am * plug-ins/imagemap/imap_main.c * plug-ins/maze/maze_face.c * plug-ins/mosaic/mosaic.c * plug-ins/pagecurl/pagecurl.c * plug-ins/print/print.c * plug-ins/rcm/rcm_dialog.c * plug-ins/script-fu/script-fu-console.c * plug-ins/script-fu/script-fu-scripts.c * plug-ins/script-fu/script-fu-server.c * plug-ins/sel2path/Makefile.am * plug-ins/sel2path/sel2path.c * plug-ins/sgi/sgi.c * plug-ins/sinus/sinus.c * plug-ins/struc/struc.c * plug-ins/webbrowser/webbrowser.c * plug-ins/winsnap/winsnap.c * plug-ins/xjt/xjt.c: use gimp_ui_init(). * plug-ins/Lighting/lighting_ui.c * plug-ins/MapObject/mapobject_ui.c: only switch Gdk SHM usage off, never on. Don't use gimp_ui_init() here because of libgck.
2000-04-30 18:17:55 +00:00
1999-12-27 16:18:06 +00:00
#include "libgimp/stdplugins-intl.h"
#define PLUG_IN_PROC "plug-in-filter-pack"
#define PLUG_IN_BINARY "fp"
2004-05-06 17:59:21 +00:00
#define MAX_PREVIEW_SIZE 125
#define MAX_ROUGHNESS 128
#define RANGE_HEIGHT 15
#define PR_BX_BRDR 4
#define MARGIN 4
#define RANGE_ADJUST_MASK GDK_EXPOSURE_MASK | \
GDK_ENTER_NOTIFY_MASK | \
GDK_BUTTON_PRESS_MASK | \
GDK_BUTTON_RELEASE_MASK | \
GDK_BUTTON1_MOTION_MASK | \
GDK_POINTER_MOTION_HINT_MASK
2004-05-06 17:59:21 +00:00
typedef struct
{
2004-05-06 17:59:21 +00:00
gint run;
} fpInterface;
typedef struct
{
gint width;
gint height;
2004-05-06 17:59:21 +00:00
guchar *rgb;
gdouble *hsv;
guchar *mask;
} ReducedImage;
typedef enum
{
2004-05-06 17:59:21 +00:00
SHADOWS,
MIDTONES,
HIGHLIGHTS,
INTENSITIES
} FPIntensity;
enum
{
NONEATALL = 0,
CURRENT = 1,
HUE = 2,
SATURATION = 4,
VALUE = 8
2004-05-06 17:59:21 +00:00
};
enum
{
2004-05-06 17:59:21 +00:00
BY_HUE,
BY_SAT,
BY_VAL,
JUDGE_BY
};
enum
{
2004-05-06 17:59:21 +00:00
RED,
GREEN,
BLUE,
CYAN,
YELLOW,
MAGENTA,
ALL_PRIMARY
};
enum
{
2004-05-06 17:59:21 +00:00
DOWN = -1,
UP = 1
};
typedef struct
{
2004-05-06 17:59:21 +00:00
GtkWidget *window;
GtkWidget *range_preview;
GtkWidget *aliasing_preview;
GtkWidget *aliasing_graph;
2004-05-06 17:59:21 +00:00
} AdvancedWindow;
typedef struct
{
gdouble roughness;
gdouble aliasing;
gdouble preview_size;
FPIntensity intensity_range;
gint value_by;
gint selection_only;
gboolean real_time;
guchar offset;
guchar visible_frames;
guchar cutoff[INTENSITIES];
gint touched[JUDGE_BY];
gint red_adjust[JUDGE_BY][256];
gint blue_adjust[JUDGE_BY][256];
gint green_adjust[JUDGE_BY][256];
gint sat_adjust[JUDGE_BY][256];
} FPValues;
typedef struct
{
GtkWidget *roughness_scale;
GtkWidget *aliasing_scale;
GtkWidget *preview_size_scale;
GtkWidget *range_label[12];
} FPWidgets;
static void fp_show_hide_frame (GtkWidget *button,
GtkWidget *frame);
static ReducedImage * fp_reduce_image (GimpDrawable *drawable,
GimpDrawable *mask,
gint longer_size,
gint selection);
static void fp_render_preview (GtkWidget *preview,
gint change_what,
gint change_which);
static void update_current_fp (gint change_what,
gint change_which);
static void fp_create_nudge (gint *adj_array);
static gboolean fp_dialog (void);
static void fp_advanced_dialog (void);
static void fp_selection_made (GtkWidget *widget,
gpointer data);
static void fp_scale_update (GtkAdjustment *adjustment,
gdouble *scale_val);
static void fp_reset_filter_packs (void);
static void fp_create_smoothness_graph (GtkWidget *preview);
static void fp_range_preview_spill (GtkWidget *preview,
gint type);
static void fp_adjust_preview_sizes (gint width,
gint height);
static void fp_redraw_all_windows (void);
static void fp_refresh_previews (gint which);
static void fp_init_filter_packs (void);
static void fp_drag (GtkWidget *button);
static void fp_preview_scale_update (GtkAdjustment *adjustment,
gdouble *scale_val);
static void fp (GimpDrawable *drawable);
static GtkWidget * fp_create_bna (void);
static GtkWidget * fp_create_rough (void);
static GtkWidget * fp_create_range (void);
static GtkWidget * fp_create_circle_palette (void);
static GtkWidget * fp_create_lnd (void);
static GtkWidget * fp_create_show (void);
static GtkWidget * fp_create_msnls (void);
static GtkWidget * fp_create_pixels_select_by (void);
static void update_range_labels (void);
static gboolean fp_range_change_events (GtkWidget *widget,
GdkEvent *event,
FPValues *current);
static void fp_create_preview (GtkWidget **preview,
GtkWidget **frame,
gint preview_width,
gint preview_height);
static void fp_create_table_entry (GtkWidget **box,
GtkWidget *smaller_frame,
const gchar *description);
static void fp_checkbutton_in_box (GtkWidget *vbox,
const gchar *label,
GtkSignalFunc func,
gpointer data,
gboolean clicked);
static void fp_frames_checkbutton_in_box (GtkWidget *vbox,
const gchar *label,
GtkSignalFunc func,
GtkWidget *frame,
gboolean clicked);
2004-05-06 17:59:21 +00:00
static void fp_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
2004-05-06 17:59:21 +00:00
#define RESPONSE_RESET 1
/* These values are translated for the GUI but also used internally
to figure out which button the user pushed, etc.
Not my design, please don't blame me -- njl */
static const gchar *hue_red = N_("Red:");
static const gchar *hue_green = N_("Green:");
static const gchar *hue_blue = N_("Blue:");
static const gchar *hue_cyan = N_("Cyan:");
static const gchar *hue_yellow = N_("Yellow:");
static const gchar *hue_magenta = N_("Magenta:");
static const gchar *val_darker = N_("Darker:");
static const gchar *val_lighter = N_("Lighter:");
static const gchar *sat_more = N_("More Sat:");
static const gchar *sat_less = N_("Less Sat:");
static const gchar *current_val = N_("Current:");
static const gint colorSign[3][ALL_PRIMARY]=
2004-05-06 17:59:21 +00:00
{{1,-1,-1,-1,1,1},{-1,1,-1,1,1,-1},{-1,-1,1,1,-1,1}};
static AdvancedWindow AW = { NULL, NULL, NULL, NULL };
static FPWidgets fp_widgets = { NULL, NULL, NULL };
2004-05-06 17:59:21 +00:00
static gint nudgeArray[256];
static GtkWidget *origPreview, *curPreview;
static GtkWidget *rPreview, *gPreview, *bPreview;
static GtkWidget *cPreview, *yPreview, *mPreview;
static GtkWidget *centerPreview;
static GtkWidget *darkerPreview, *lighterPreview, *middlePreview;
static GtkWidget *dlg;
static GtkWidget *plusSatPreview, *SatPreview, *minusSatPreview;
static struct
{
GtkWidget *bna;
GtkWidget *palette;
GtkWidget *rough;
GtkWidget *range;
GtkWidget *show;
GtkWidget *lnd;
GtkWidget *pixelsBy;
GtkWidget *frameSelect;
GtkWidget *satur;
} fp_frames;
2004-05-06 17:59:21 +00:00
static fpInterface FPint =
{
FALSE /* run */
};
static ReducedImage *reduced;
static FPValues fpvals =
{
.25, /* Initial Roughness */
.6, /* Initial Degree of Aliasing */
80, /* Initial preview size */
MIDTONES, /* Initial Range */
BY_VAL, /* Initial God knows what */
TRUE, /* Selection Only */
TRUE, /* Real Time */
0, /* Offset */
0, /* Visible frames */
{32,224,255}, /* cutoffs */
{0,0,0} /* touched */
};
static GimpDrawable *drawable;
static GimpDrawable *mask;
2004-05-06 17:59:21 +00:00
static void query (void);
static void run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
const GimpPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
MAIN()
2004-05-06 17:59:21 +00:00
static void
query (void)
{
GimpParamDef args[] =
{
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
{ GIMP_PDB_IMAGE, "image", "Input image (used for indexed images)" },
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
};
gimp_install_procedure (PLUG_IN_PROC,
N_("Interactively modify the image colors"),
Bill Skaggs <weskaggs@primate.ucdavis.edu> * plug-ins/common/AlienMap2.c * plug-ins/common/CML_explorer.c * plug-ins/common/align_layers.c * plug-ins/common/animationplay.c * plug-ins/common/animoptimize.c * plug-ins/common/apply_lens.c * plug-ins/common/autocrop.c * plug-ins/common/autostretch_hsv.c * plug-ins/common/blinds.c * plug-ins/common/blur.c * plug-ins/common/borderaverage.c * plug-ins/common/bumpmap.c * plug-ins/common/c_astretch.c * plug-ins/common/cartoon.c * plug-ins/common/ccanalyze.c * plug-ins/common/channel_mixer.c * plug-ins/common/checkerboard.c * plug-ins/common/color_enhance.c * plug-ins/common/colorify.c * plug-ins/common/colortoalpha.c * plug-ins/common/compose.c * plug-ins/common/convmatrix.c * plug-ins/common/cubism.c * plug-ins/common/curve_bend.c * plug-ins/common/decompose.c * plug-ins/common/deinterlace.c * plug-ins/common/depthmerge.c * plug-ins/common/despeckle.c * plug-ins/common/destripe.c * plug-ins/common/diffraction.c * plug-ins/common/displace.c * plug-ins/common/dog.c * plug-ins/common/edge.c * plug-ins/common/emboss.c * plug-ins/common/engrave.c * plug-ins/common/exchange.c * plug-ins/common/film.c * plug-ins/common/flarefx.c * plug-ins/common/fp.c * plug-ins/common/fractaltrace.c * plug-ins/common/gauss.c * plug-ins/common/gee.c * plug-ins/common/gee_zoom.c * plug-ins/common/glasstile.c * plug-ins/common/gnomeprint.c * plug-ins/common/gqbist.c * plug-ins/common/gradmap.c * plug-ins/common/grid.c * plug-ins/common/guillotine.c * plug-ins/common/hot.c * plug-ins/common/illusion.c * plug-ins/common/iwarp.c * plug-ins/common/jigsaw.c * plug-ins/common/laplace.c * plug-ins/common/lic.c * plug-ins/common/mail.c * plug-ins/common/mapcolor.c * plug-ins/common/max_rgb.c * plug-ins/common/mblur.c * plug-ins/common/mosaic.c * plug-ins/common/neon.c * plug-ins/common/newsprint.c * plug-ins/common/nlfilt.c * plug-ins/common/noisify.c * plug-ins/common/normalize.c * plug-ins/common/nova.c * plug-ins/common/oilify.c * plug-ins/common/papertile.c * plug-ins/common/photocopy.c * plug-ins/common/pixelize.c * plug-ins/common/plasma.c * plug-ins/common/plugin-browser.c * plug-ins/common/polar.c * plug-ins/common/procedure-browser.c * plug-ins/common/randomize.c * plug-ins/common/retinex.c * plug-ins/common/ripple.c * plug-ins/common/sample_colorize.c * plug-ins/common/scatter_hsv.c * plug-ins/common/screenshot.c * plug-ins/common/sel_gauss.c * plug-ins/common/semiflatten.c * plug-ins/common/sharpen.c * plug-ins/common/shift.c * plug-ins/common/sinus.c * plug-ins/common/smooth_palette.c * plug-ins/common/snoise.c * plug-ins/common/sobel.c * plug-ins/common/softglow.c * plug-ins/common/sparkle.c * plug-ins/common/spheredesigner.c * plug-ins/common/spread.c * plug-ins/common/struc.c * plug-ins/common/threshold_alpha.c * plug-ins/common/tile.c * plug-ins/common/tileit.c * plug-ins/common/tiler.c * plug-ins/common/uniteditor.c * plug-ins/common/unsharp.c * plug-ins/common/video.c * plug-ins/common/vinvert.c * plug-ins/common/vpropagate.c * plug-ins/common/warp.c * plug-ins/common/waves.c * plug-ins/common/whirlpinch.c * plug-ins/common/wind.c * plug-ins/common/winprint.c * plug-ins/common/zealouscrop.c: Give "helpful" blurbs to menu- accessible plugins, and mark them for translation. Probably there is room for improvement in some of them. Still needs to be done for plug-ins not in "common".
2006-03-15 21:10:34 +00:00
"Interactively modify the image colors.",
"Pavel Grinfeld (pavel@ml.com)",
"Pavel Grinfeld (pavel@ml.com)",
"27th March 1997",
N_("_Filter Pack..."),
"RGB*",
GIMP_PLUGIN,
G_N_ELEMENTS (args), 0,
args, NULL);
gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Colors/Modify");
}
/********************************STANDARD RUN*************************/
2004-05-06 17:59:21 +00:00
static void
run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals)
{
GimpParam values[1];
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpRunMode run_mode;
*nreturn_vals = 1;
*return_vals = values;
2004-05-06 17:59:21 +00:00
run_mode = param[0].data.d_int32;
INIT_I18N ();
1999-12-27 16:18:06 +00:00
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = status;
fp_init_filter_packs();
drawable = gimp_drawable_get (param[2].data.d_drawable);
mask = gimp_drawable_get (gimp_image_get_selection (param[1].data.d_image));
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
/* Possibly retrieve data */
gimp_get_data (PLUG_IN_PROC, &fpvals);
if (gimp_drawable_is_indexed (drawable->drawable_id) ||
gimp_drawable_is_gray (drawable->drawable_id) )
{
gimp_message (_("FP can only be used on RGB images."));
status = GIMP_PDB_EXECUTION_ERROR;
}
else if (! fp_dialog())
{
status = GIMP_PDB_CANCEL;
}
break;
case GIMP_RUN_NONINTERACTIVE:
gimp_message (_("FP can only be run interactively."));
status = GIMP_PDB_CALLING_ERROR;
break;
case GIMP_RUN_WITH_LAST_VALS:
/* Possibly retrieve data */
gimp_get_data (PLUG_IN_PROC, &fpvals);
break;
default:
break;
}
if (status == GIMP_PDB_SUCCESS)
{
/* Make sure that the drawable is gray or RGB color */
if (gimp_drawable_is_rgb (drawable->drawable_id))
{
gimp_progress_init (_("Applying filter pack"));
gimp_tile_cache_ntiles (2 * (drawable->width /
gimp_tile_width () + 1));
fp (drawable);
/* Store data */
if (run_mode == GIMP_RUN_INTERACTIVE)
gimp_set_data (PLUG_IN_PROC, &fpvals, sizeof (FPValues));
gimp_displays_flush ();
}
else status = GIMP_PDB_EXECUTION_ERROR;
}
values[0].data.d_status = status;
if (status == GIMP_PDB_SUCCESS)
gimp_drawable_detach (drawable);
}
2004-05-06 17:59:21 +00:00
static void
fp_func (const guchar *src,
guchar *dest,
gint bpp,
gpointer data)
{
2004-05-06 17:59:21 +00:00
gint bytenum, k;
gint JudgeBy, Intensity = 0, P[3];
GimpRGB rgb;
GimpHSV hsv;
gint M, m, middle;
2004-05-06 17:59:21 +00:00
P[0] = src[0];
P[1] = src[1];
P[2] = src[2];
2004-05-06 17:59:21 +00:00
gimp_rgb_set_uchar (&rgb, (guchar) P[0], (guchar) P[1], (guchar) P[2]);
gimp_rgb_to_hsv (&rgb, &hsv);
2004-05-06 17:59:21 +00:00
for (JudgeBy = BY_HUE; JudgeBy < JUDGE_BY; JudgeBy++)
{
if (!fpvals.touched[JudgeBy])
continue;
2004-05-06 17:59:21 +00:00
switch (JudgeBy)
{
case BY_HUE:
Intensity = 255 * hsv.h;
break;
case BY_SAT:
Intensity = 255 * hsv.s;
break;
case BY_VAL:
Intensity = 255 * hsv.v;
break;
}
2004-05-06 17:59:21 +00:00
/* It's important to take care of Saturation first!!! */
2004-05-06 17:59:21 +00:00
m = MIN (MIN (P[0], P[1]), P[2]);
M = MAX (MAX (P[0], P[1]), P[2]);
middle = (M + m) / 2;
2004-05-06 17:59:21 +00:00
for (k = 0; k < 3; k++)
if (P[k] != m && P[k] != M)
middle = P[k];
2004-05-06 17:59:21 +00:00
for (k = 0; k < 3; k++)
if (M != m)
{
if (P[k] == M)
P[k] = MAX (P[k] + fpvals.sat_adjust[JudgeBy][Intensity], middle);
else if (P[k] == m)
P[k] = MIN (P[k] - fpvals.sat_adjust[JudgeBy][Intensity], middle);
}
P[0] += fpvals.red_adjust[JudgeBy][Intensity];
P[1] += fpvals.green_adjust[JudgeBy][Intensity];
P[2] += fpvals.blue_adjust[JudgeBy][Intensity];
2004-05-06 17:59:21 +00:00
P[0] = CLAMP0255(P[0]);
P[1] = CLAMP0255(P[1]);
P[2] = CLAMP0255(P[2]);
}
2004-05-06 17:59:21 +00:00
dest[0] = P[0];
dest[1] = P[1];
dest[2] = P[2];
2004-05-06 17:59:21 +00:00
for (bytenum = 3; bytenum < bpp; bytenum++)
dest[bytenum] = src[bytenum];
}
static void
2004-05-06 17:59:21 +00:00
fp (GimpDrawable *drawable)
{
gimp_rgn_iterate2 (drawable, 0 /* unused */, fp_func, NULL);
2004-05-06 17:59:21 +00:00
}
2004-05-06 17:59:21 +00:00
/***********************************************************/
/************ Main Dialog Window ******************/
/***********************************************************/
2004-05-06 17:59:21 +00:00
static GtkWidget *
fp_create_bna (void)
{
GtkWidget *table;
GtkWidget *label;
GtkWidget *bframe, *aframe;
fp_create_preview (&origPreview, &bframe, reduced->width, reduced->height);
fp_create_preview (&curPreview, &aframe, reduced->width, reduced->height);
2004-05-06 17:59:21 +00:00
table = gtk_table_new (2, 2, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
label = gtk_label_new (_("Original:"));
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
GTK_SHRINK, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), bframe, 0, 1, 1, 2,
GTK_EXPAND, 0, 0, 0);
label = gtk_label_new (_("Current:"));
gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
GTK_SHRINK, GTK_SHRINK, 0, 0);
gtk_widget_show (label);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), aframe, 1, 2, 1, 2,
GTK_EXPAND, 0, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_widget_show (table);
return table;
2004-05-06 17:59:21 +00:00
}
/* close a sub dialog (from window manager) by simulating toggle click */
static gboolean
sub_dialog_destroy (GtkWidget *dialog,
GdkEvent *ev,
gpointer dummy)
2004-05-06 17:59:21 +00:00
{
GtkWidget *button =
GTK_WIDGET (g_object_get_data (G_OBJECT (dialog), "ctrlButton"));
gtk_button_clicked (GTK_BUTTON (button));
return TRUE;
}
static GtkWidget *
fp_create_circle_palette (void)
{
GtkWidget *table;
2004-05-06 17:59:21 +00:00
GtkWidget *rVbox, *rFrame;
GtkWidget *gVbox, *gFrame;
GtkWidget *bVbox, *bFrame;
GtkWidget *cVbox, *cFrame;
GtkWidget *yVbox, *yFrame;
GtkWidget *mVbox, *mFrame;
GtkWidget *centerVbox, *centerFrame;
GtkWidget *win;
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gimp_help_connect (win, gimp_standard_help_func, PLUG_IN_PROC, NULL);
gtk_window_set_title (GTK_WINDOW (win), _("Hue Variations"));
g_signal_connect (win, "delete-event",
G_CALLBACK (sub_dialog_destroy),
NULL);
2004-05-06 17:59:21 +00:00
table = gtk_table_new (11, 11, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
gtk_container_set_border_width (GTK_CONTAINER (table), 12);
gtk_container_add (GTK_CONTAINER (win), table);
2004-05-06 17:59:21 +00:00
gtk_widget_show (table);
fp_create_preview (&rPreview, &rFrame, reduced->width, reduced->height);
fp_create_preview (&gPreview, &gFrame, reduced->width, reduced->height);
fp_create_preview (&bPreview, &bFrame, reduced->width, reduced->height);
fp_create_preview (&cPreview, &cFrame, reduced->width, reduced->height);
fp_create_preview (&yPreview, &yFrame, reduced->width, reduced->height);
fp_create_preview (&mPreview, &mFrame, reduced->width, reduced->height);
fp_create_preview (&centerPreview, &centerFrame,
reduced->width, reduced->height);
2004-05-06 17:59:21 +00:00
fp_create_table_entry (&rVbox, rFrame, hue_red);
fp_create_table_entry (&gVbox, gFrame, hue_green);
fp_create_table_entry (&bVbox, bFrame, hue_blue);
fp_create_table_entry (&cVbox, cFrame, hue_cyan);
fp_create_table_entry (&yVbox, yFrame, hue_yellow);
fp_create_table_entry (&mVbox, mFrame, hue_magenta);
fp_create_table_entry (&centerVbox, centerFrame, current_val);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), rVbox, 8, 11 ,4 , 7,
GTK_EXPAND , GTK_EXPAND, 0 ,0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), gVbox, 2, 5, 0, 3,
GTK_EXPAND, GTK_EXPAND, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), bVbox, 2, 5, 8, 11,
GTK_EXPAND, GTK_EXPAND,0,0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), cVbox, 0, 3, 4, 7,
GTK_EXPAND, GTK_EXPAND, 0 ,0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), yVbox, 6, 9, 0, 3,
GTK_EXPAND, GTK_EXPAND, 0 ,0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), mVbox, 6, 9, 8, 11,
GTK_EXPAND, GTK_EXPAND, 0 ,0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), centerVbox, 4, 7, 4, 7,
GTK_EXPAND, GTK_EXPAND, 0 ,0);
2004-05-06 17:59:21 +00:00
return win;
}
static GtkWidget *
fp_create_rough (void)
{
GtkWidget *frame, *vbox, *scale;
2004-05-06 17:59:21 +00:00
GtkObject *data;
frame = gimp_frame_new (_("Roughness"));
2004-05-06 17:59:21 +00:00
gtk_widget_show (frame);
vbox = gtk_vbox_new (FALSE, 6);
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_widget_show (vbox);
data = gtk_adjustment_new (fpvals.roughness, 0, 1.0, 0.05, 0.01, 0.0);
fp_widgets.roughness_scale = scale = gtk_hscale_new (GTK_ADJUSTMENT (data));
2004-05-06 17:59:21 +00:00
gtk_widget_set_size_request (scale, 60, -1);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_scale_set_digits (GTK_SCALE (scale), 2);
gtk_widget_show (scale);
g_signal_connect (data, "value-changed",
2004-05-06 17:59:21 +00:00
G_CALLBACK (fp_scale_update),
&fpvals.roughness);
2004-05-06 17:59:21 +00:00
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
return frame;
}
static void
fp_change_current_range (GtkWidget *widget,
gpointer data)
2004-05-06 17:59:21 +00:00
{
gimp_radio_button_update (widget, data);
if (GTK_TOGGLE_BUTTON (widget)->active)
{
fp_refresh_previews (fpvals.visible_frames);
2004-05-06 17:59:21 +00:00
if (AW.window && GTK_WIDGET_VISIBLE (AW.window))
fp_create_smoothness_graph (AW.aliasing_preview);
2004-05-06 17:59:21 +00:00
}
}
static GtkWidget *
fp_create_range (void)
{
GtkWidget *frame;
frame = gimp_int_radio_group_new (TRUE, _("Affected Range"),
G_CALLBACK (fp_change_current_range),
&fpvals.intensity_range, fpvals.intensity_range,
2004-05-06 17:59:21 +00:00
_("Sha_dows"), SHADOWS, NULL,
_("_Midtones"), MIDTONES, NULL,
_("H_ighlights"), HIGHLIGHTS, NULL,
2004-05-06 17:59:21 +00:00
NULL);
gtk_widget_show (frame);
return frame;
}
static GtkWidget *
fp_create_control (void)
{
GtkWidget *frame, *box;
frame = gimp_frame_new (_("Windows"));
2004-05-06 17:59:21 +00:00
box = gtk_vbox_new (FALSE, 6);
2004-05-06 17:59:21 +00:00
gtk_container_add (GTK_CONTAINER (frame), box);
gtk_widget_show (box);
fp_frames_checkbutton_in_box (box, _("_Hue"),
GTK_SIGNAL_FUNC (fp_show_hide_frame),
fp_frames.palette,
fpvals.visible_frames & HUE);
fp_frames_checkbutton_in_box (box, _("_Saturation"),
GTK_SIGNAL_FUNC (fp_show_hide_frame),
fp_frames.satur,
fpvals.visible_frames & SATURATION);
fp_frames_checkbutton_in_box (box, _("_Value"),
GTK_SIGNAL_FUNC (fp_show_hide_frame),
fp_frames.lnd,
fpvals.visible_frames & VALUE);
fp_frames_checkbutton_in_box (box, _("A_dvanced"),
GTK_SIGNAL_FUNC (fp_show_hide_frame),
AW.window,
FALSE);
gtk_widget_show (frame);
2004-05-06 17:59:21 +00:00
return frame;
}
static GtkWidget *
fp_create_lnd (void)
{
GtkWidget *table, *lighterFrame, *middleFrame, *darkerFrame;
2004-05-06 17:59:21 +00:00
GtkWidget *lighterVbox, *middleVbox, *darkerVbox;
GtkWidget *win;
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gimp_help_connect (win, gimp_standard_help_func, PLUG_IN_PROC, NULL);
gtk_window_set_title (GTK_WINDOW (win), _("Value Variations"));
g_signal_connect (win, "delete-event",
G_CALLBACK (sub_dialog_destroy),
NULL);
fp_create_preview (&lighterPreview, &lighterFrame,
reduced->width, reduced->height);
fp_create_preview (&middlePreview, &middleFrame,
reduced->width, reduced->height);
fp_create_preview (&darkerPreview, &darkerFrame,
reduced->width, reduced->height);
2004-05-06 17:59:21 +00:00
fp_create_table_entry (&lighterVbox, lighterFrame, val_lighter);
fp_create_table_entry (&middleVbox, middleFrame, current_val);
fp_create_table_entry (&darkerVbox, darkerFrame, val_darker);
2004-05-06 17:59:21 +00:00
table = gtk_table_new (1, 11, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
gtk_container_set_border_width (GTK_CONTAINER (table), 12);
gtk_container_add (GTK_CONTAINER (win), table);
2004-05-06 17:59:21 +00:00
gtk_widget_show (table);
gtk_table_attach (GTK_TABLE (table), lighterVbox, 0, 3, 0, 1,
GTK_EXPAND , GTK_EXPAND, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), middleVbox, 4, 7, 0, 1,
GTK_EXPAND, GTK_EXPAND, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), darkerVbox, 8, 11, 0, 1,
GTK_EXPAND, GTK_EXPAND, 0, 0);
2004-05-06 17:59:21 +00:00
return win;
}
static GtkWidget *
fp_create_msnls (void)
{
GtkWidget *table, *lessFrame, *middleFrame, *moreFrame;
2004-05-06 17:59:21 +00:00
GtkWidget *lessVbox, *middleVbox, *moreVbox;
GtkWidget *win;
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gimp_help_connect (win, gimp_standard_help_func, PLUG_IN_PROC, NULL);
gtk_window_set_title (GTK_WINDOW (win), _("Saturation Variations"));
g_signal_connect (win, "delete-event",
G_CALLBACK (sub_dialog_destroy),
NULL);
fp_create_preview (&minusSatPreview, &lessFrame,
reduced->width, reduced->height);
fp_create_preview (&SatPreview, &middleFrame,
reduced->width, reduced->height);
fp_create_preview (&plusSatPreview, &moreFrame,
reduced->width, reduced->height);
2004-05-06 17:59:21 +00:00
fp_create_table_entry (&moreVbox, moreFrame, sat_more);
fp_create_table_entry (&middleVbox, middleFrame, current_val);
fp_create_table_entry (&lessVbox, lessFrame, sat_less);
2004-05-06 17:59:21 +00:00
table = gtk_table_new (1, 11, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
gtk_container_set_border_width (GTK_CONTAINER (table), 12);
gtk_container_add (GTK_CONTAINER (win), table);
2004-05-06 17:59:21 +00:00
gtk_widget_show (table);
gtk_table_attach (GTK_TABLE (table), moreVbox, 0, 3, 0, 1,
GTK_EXPAND, GTK_EXPAND, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), middleVbox, 4, 7, 0, 1,
GTK_EXPAND, GTK_EXPAND, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), lessVbox, 8, 11, 0, 1,
GTK_EXPAND, GTK_EXPAND, 0, 0);
2004-05-06 17:59:21 +00:00
return win;
}
static void
fp_change_current_pixels_by (GtkWidget *widget,
gpointer data)
2004-05-06 17:59:21 +00:00
{
gimp_radio_button_update (widget, data);
if (GTK_TOGGLE_BUTTON (widget)->active)
{
fp_refresh_previews (fpvals.visible_frames);
if (AW.window && GTK_WIDGET_VISIBLE (AW.window) && AW.range_preview)
fp_range_preview_spill (AW.range_preview,fpvals.value_by);
2004-05-06 17:59:21 +00:00
}
}
static GtkWidget *
fp_create_pixels_select_by (void)
{
GtkWidget *frame;
frame = gimp_int_radio_group_new (TRUE, _("Select Pixels By"),
2004-05-06 17:59:21 +00:00
G_CALLBACK (fp_change_current_pixels_by),
&fpvals.value_by,
fpvals.value_by,
2004-05-06 17:59:21 +00:00
_("H_ue"), 0, NULL,
_("Satu_ration"), 1, NULL,
_("V_alue"), 2, NULL,
2004-05-06 17:59:21 +00:00
NULL);
gtk_widget_show (frame);
return frame;
}
static void
fp_change_selection (GtkWidget *widget,
gpointer data)
2004-05-06 17:59:21 +00:00
{
gimp_radio_button_update (widget, data);
2004-05-06 17:59:21 +00:00
if (GTK_TOGGLE_BUTTON (widget)->active)
{
fp_redraw_all_windows ();
}
}
static GtkWidget *
fp_create_show (void)
{
GtkWidget *frame;
frame = gimp_int_radio_group_new (TRUE, _("Show"),
G_CALLBACK (fp_change_selection),
&fpvals.selection_only,
fpvals.selection_only,
2004-05-06 17:59:21 +00:00
_("_Entire image"), 0, NULL,
_("Se_lection only"), 1, NULL,
_("Selec_tion in context"), 2, NULL,
2004-05-06 17:59:21 +00:00
NULL);
gtk_widget_show (frame);
return frame;
}
static void
fp_create_preview (GtkWidget **preview,
GtkWidget **frame,
gint preview_width,
gint preview_height)
2004-05-06 17:59:21 +00:00
{
*frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (*frame), GTK_SHADOW_IN);
gtk_widget_show (*frame);
*preview = gimp_preview_area_new ();
gtk_widget_set_size_request (*preview, preview_width, preview_height);
g_signal_connect (*preview, "size_allocate",
G_CALLBACK (fp_preview_size_allocate), NULL);
2004-05-06 17:59:21 +00:00
gtk_widget_show (*preview);
gtk_container_add (GTK_CONTAINER (*frame), *preview);
}
static void
fp_checkbutton_in_box (GtkWidget *vbox,
const gchar *label,
GtkSignalFunc function,
gpointer data,
gboolean clicked)
2004-05-06 17:59:21 +00:00
{
GtkWidget *button;
button = gtk_check_button_new_with_mnemonic (label);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
g_signal_connect (button, "clicked",
G_CALLBACK (function),
data);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clicked);
}
static void
fp_frames_checkbutton_in_box (GtkWidget *vbox,
const gchar *label,
GtkSignalFunc function,
GtkWidget *frame,
gboolean clicked)
2004-05-06 17:59:21 +00:00
{
GtkWidget *button;
button = gtk_check_button_new_with_mnemonic (label);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
g_object_set_data (G_OBJECT (frame), "ctrlButton", (gpointer) button);
gtk_widget_show (button);
g_signal_connect (button, "clicked",
G_CALLBACK (function),
frame);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clicked);
}
static void
fp_create_table_entry (GtkWidget **box,
GtkWidget *smaller_frame,
const gchar *description)
2004-05-06 17:59:21 +00:00
{
GtkWidget *label;
GtkWidget *button;
GtkWidget *table;
2004-05-06 17:59:21 +00:00
*box = gtk_vbox_new (FALSE, 1);
gtk_container_set_border_width (GTK_CONTAINER (*box), PR_BX_BRDR);
gtk_widget_show (*box);
/* Delayed translation applied here */
label = gtk_label_new (gettext (description));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_widget_show (label);
table = gtk_table_new (2, 1, FALSE);
gtk_widget_show (table);
gtk_box_pack_start (GTK_BOX (*box), table, TRUE, TRUE, 0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
0, 0, 0, 0);
2004-05-06 17:59:21 +00:00
if (description != current_val)
{
button = gtk_button_new ();
gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2,
0, 0, 0, 4);
2004-05-06 17:59:21 +00:00
gtk_widget_show (button);
gtk_container_add (GTK_CONTAINER (button), smaller_frame);
2004-05-06 17:59:21 +00:00
g_signal_connect (button, "clicked",
G_CALLBACK (fp_selection_made),
2004-05-06 17:59:21 +00:00
(gchar *) description);
}
else
{
gtk_table_attach (GTK_TABLE (table), smaller_frame, 0, 1, 1, 2,
0, 0, 0, 4);
2004-05-06 17:59:21 +00:00
}
}
static void
fp_redraw_all_windows (void)
{
if (reduced)
{
g_free (reduced->rgb);
g_free (reduced->hsv);
g_free (reduced->mask);
g_free (reduced);
}
reduced = fp_reduce_image (drawable, mask,
fpvals.preview_size,
fpvals.selection_only);
fp_adjust_preview_sizes (reduced->width, reduced->height);
gtk_widget_queue_draw (fp_frames.palette);
gtk_widget_queue_draw (fp_frames.satur);
gtk_widget_queue_draw (fp_frames.lnd);
2004-05-06 17:59:21 +00:00
gtk_widget_queue_draw (dlg);
fp_refresh_previews (fpvals.visible_frames);
2004-05-06 17:59:21 +00:00
}
static void
fp_show_hide_frame (GtkWidget *button,
GtkWidget *frame)
2004-05-06 17:59:21 +00:00
{
gint prev = fpvals.visible_frames;
2004-05-06 17:59:21 +00:00
if (frame == NULL)
return;
2004-05-06 17:59:21 +00:00
if (GTK_TOGGLE_BUTTON (button)->active)
{
if (!GTK_WIDGET_VISIBLE (frame))
{
gtk_widget_show (frame);
if (frame==fp_frames.palette)
fpvals.visible_frames |= HUE;
else if (frame==fp_frames.satur)
fpvals.visible_frames |= SATURATION;
else if (frame==fp_frames.lnd)
fpvals.visible_frames |= VALUE;
fp_refresh_previews (fpvals.visible_frames & ~prev);
fp_create_smoothness_graph (AW.aliasing_preview);
fp_range_preview_spill (AW.range_preview,fpvals.value_by);
}
2004-05-06 17:59:21 +00:00
}
else
{
if (GTK_WIDGET_VISIBLE (frame))
{
gtk_widget_hide (frame);
if (frame==fp_frames.palette)
fpvals.visible_frames &= ~HUE;
else if (frame==fp_frames.satur)
fpvals.visible_frames &= ~SATURATION;
else if (frame==fp_frames.lnd)
fpvals.visible_frames &= ~VALUE;
}
2004-05-06 17:59:21 +00:00
}
}
static void
fp_adjust_preview_sizes (gint width,
gint height)
2004-05-06 17:59:21 +00:00
{
gtk_widget_set_size_request (origPreview, width, height);
gtk_widget_set_size_request (curPreview, width, height);
gtk_widget_set_size_request (rPreview, width, height);
gtk_widget_set_size_request (gPreview, width, height);
gtk_widget_set_size_request (bPreview, width, height);
gtk_widget_set_size_request (cPreview, width, height);
gtk_widget_set_size_request (yPreview, width, height);
gtk_widget_set_size_request (mPreview, width, height);
gtk_widget_set_size_request (centerPreview, width, height);
gtk_widget_set_size_request (lighterPreview, width, height);
gtk_widget_set_size_request (darkerPreview, width, height);
gtk_widget_set_size_request (middlePreview, width, height);
gtk_widget_set_size_request (minusSatPreview, width, height);
gtk_widget_set_size_request (SatPreview, width, height);
gtk_widget_set_size_request (plusSatPreview, width, height);
2004-05-06 17:59:21 +00:00
}
static void
fp_selection_made (GtkWidget *widget,
gpointer data)
2004-05-06 17:59:21 +00:00
{
fpvals.touched[fpvals.value_by] = 1;
2004-05-06 17:59:21 +00:00
if (data == (gpointer) hue_red)
{
update_current_fp (HUE, RED);
}
else if (data == (gpointer) hue_green)
{
update_current_fp (HUE, GREEN);
}
else if (data == (gpointer) hue_blue)
{
update_current_fp (HUE, BLUE);
}
else if (data == (gpointer) hue_cyan)
{
update_current_fp (HUE, CYAN);
}
else if (data == (gpointer) hue_yellow)
{
update_current_fp (HUE, YELLOW);
}
else if (data == (gpointer) hue_magenta)
{
update_current_fp (HUE, MAGENTA);
}
else if (data == (gpointer) val_darker)
{
update_current_fp (VALUE, DOWN);
}
else if (data == (gpointer) val_lighter)
{
update_current_fp (VALUE, UP);
}
else if (data == (gpointer) sat_more)
{
update_current_fp (SATURATION, UP);
}
else if (data == (gpointer) sat_less)
{
update_current_fp (SATURATION, DOWN);
}
2004-05-06 17:59:21 +00:00
fp_refresh_previews (fpvals.visible_frames);
2004-05-06 17:59:21 +00:00
}
static void
fp_refresh_previews (gint which)
2004-05-06 17:59:21 +00:00
{
fp_create_nudge (nudgeArray);
2004-05-06 17:59:21 +00:00
fp_render_preview (origPreview, NONEATALL, 0);
fp_render_preview (curPreview, CURRENT, 0);
2004-05-06 17:59:21 +00:00
if (which & HUE)
{
fp_render_preview (rPreview, HUE, RED);
fp_render_preview (gPreview, HUE, GREEN);
fp_render_preview (bPreview, HUE, BLUE);
fp_render_preview (cPreview, HUE, CYAN);
fp_render_preview (yPreview, HUE, YELLOW);
fp_render_preview (mPreview, HUE, MAGENTA);
fp_render_preview (centerPreview, CURRENT, 0);
}
2004-05-06 17:59:21 +00:00
if (which & VALUE)
{
fp_render_preview (lighterPreview, VALUE, UP);
fp_render_preview (middlePreview, CURRENT, 0);
fp_render_preview (darkerPreview, VALUE, DOWN);
}
2004-05-06 17:59:21 +00:00
if (which & SATURATION)
{
fp_render_preview (plusSatPreview, SATURATION, UP);
fp_render_preview (SatPreview, CURRENT, 0);
fp_render_preview (minusSatPreview, SATURATION, DOWN);
}
}
static void
fp_response (GtkWidget *widget,
gint response_id,
gpointer data)
{
switch (response_id)
{
case RESPONSE_RESET:
fp_reset_filter_packs ();
2004-05-06 17:59:21 +00:00
break;
case GTK_RESPONSE_OK:
FPint.run = TRUE;
gtk_widget_destroy (widget);
break;
default:
gtk_widget_destroy (widget);
break;
}
}
static void
fp_scale_update (GtkAdjustment *adjustment,
gdouble *scale_val)
2004-05-06 17:59:21 +00:00
{
static gdouble prevValue = 0.25;
2004-05-06 17:59:21 +00:00
*scale_val = adjustment->value;
if (prevValue != adjustment->value)
{
fp_create_nudge (nudgeArray);
fp_refresh_previews (fpvals.visible_frames);
2004-05-06 17:59:21 +00:00
if (AW.window != NULL && GTK_WIDGET_VISIBLE (AW.window))
fp_create_smoothness_graph (AW.aliasing_preview);
2004-05-06 17:59:21 +00:00
prevValue = adjustment->value;
}
}
static gboolean
2004-05-06 17:59:21 +00:00
fp_dialog (void)
{
GtkWidget *bna;
GtkWidget *palette;
GtkWidget *lnd;
GtkWidget *show;
GtkWidget *rough;
GtkWidget *range;
GtkWidget *pixelsBy;
GtkWidget *satur;
GtkWidget *control;
GtkWidget *table;
reduced = fp_reduce_image (drawable, mask,
fpvals.preview_size,
fpvals.selection_only);
2004-05-06 17:59:21 +00:00
gimp_ui_init (PLUG_IN_BINARY, TRUE);
2004-05-06 17:59:21 +00:00
dlg = gimp_dialog_new (_("Filter Pack Simulation"), PLUG_IN_BINARY,
2004-05-06 17:59:21 +00:00
NULL, 0,
gimp_standard_help_func, PLUG_IN_PROC,
2004-05-06 17:59:21 +00:00
GIMP_STOCK_RESET, RESPONSE_RESET,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
2004-05-06 17:59:21 +00:00
NULL);
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dlg),
RESPONSE_RESET,
GTK_RESPONSE_OK,
GTK_RESPONSE_CANCEL,
-1);
Added parent window API to the GimpProgress interface and to the libgimp 2005-09-09 Michael Natterer <mitch@gimp.org> Added parent window API to the GimpProgress interface and to the libgimp progress stuff. Might look strange, but does the right thing in almost all cases (image window, file dialog, script-fu dialog etc). Fixes bug #62988. * app/core/gimpprogress.[ch]: added GimpProgress::get_window() which should return a toplevel window ID if the progress is in a window that wants to be the transient parent of plug-in dialogs. * app/widgets/gimpwidgets-utils.[ch] (gimp_window_get_native): new function which returns the window handle of a GtkWindow's GdkWindow. * app/widgets/gimpfiledialog.c: implement ::get_window(). * app/display/gimpdisplay.[ch]: ditto. Removed window handle API. * app/gui/gui-vtable.c: changed accordingly. * libgimpbase/gimpbaseenums.[ch] (enum GimpProgressCommand): added GIMP_PROGRESS_COMMAND_GET_WINDOW. * app/plug-in/plug-in-progress.[ch] (plug_in_progress_get_window): new function. Also renamed some functions to match the GimpProgress interface, and not the legacy PDB procedure names. * tools/pdbgen/pdb/progress.pdb * app/core/gimppdbprogress.c: implement get_window() on both sides of the wire, keeping backward compatibility (hopefully). * libgimp/gimpprogress.[ch]: deprecated gimp_progress_install() and added gimp_progress_install_vtable() which takes a vtable with padding to be extensible. Added get_window() vtable entry and dispatch it accordingly. Also added pulse() which was implemented in a hackish way before. Everything is of course backward compatible. * libgimp/gimpprogressbar.c: inmplement the get_window() stuff so a plug-in dialog containing a progress can be the transient parent of another dialog in another plug-in. * libgimp/gimpui.[ch] (gimp_ui_get_progress_window): new function which returns a foreign GdkWindow of this plug-ins progress window. Renamed gimp_window_set_transient_for_default_display() to gimp_window_set_transient() and make it use the progress' window handle instead of the display's (which is the right thing to do in almost all cases). * libgimp/gimp.def * libgimp/gimpui.def: add the new functions. * tools/pdbgen/enums.pl * app/pdb/internal_procs.c * app/pdb/progress_cmds.c * libgimp/gimpprogress_pdb.[ch]: regenerated. * libgimp/gimpexport.c * plug-ins/*/*.c: follow API change.
2005-09-09 18:07:31 +00:00
gimp_window_set_transient (GTK_WINDOW (dlg));
2004-05-06 17:59:21 +00:00
g_signal_connect (dlg, "response",
G_CALLBACK (fp_response),
dlg);
g_signal_connect (dlg, "destroy",
G_CALLBACK (gtk_main_quit),
NULL);
fp_advanced_dialog ();
fp_frames.bna = bna = fp_create_bna();
fp_frames.rough = rough = fp_create_rough();
fp_frames.range = range = fp_create_range();
fp_frames.palette = palette = fp_create_circle_palette();
fp_frames.lnd = lnd = fp_create_lnd();
fp_frames.show = show = fp_create_show();
fp_frames.satur = satur = fp_create_msnls();
fp_frames.pixelsBy = pixelsBy = fp_create_pixels_select_by();
control = fp_create_control();
2004-05-06 17:59:21 +00:00
/********************************************************************/
/******************** PUT EVERYTHING TOGETHER ******************/
table = gtk_table_new (4, 2, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (table), 6);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
gtk_container_set_border_width (GTK_CONTAINER (table), 12);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), table, TRUE, TRUE, 0);
gtk_widget_show (table);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), bna, 0, 2, 0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), control, 1, 2, 1, 3,
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), rough, 1, 2, 3, 4,
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), show, 0, 1, 1, 2,
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), range, 0, 1, 2, 3,
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_table_attach (GTK_TABLE (table), pixelsBy, 0, 1, 3, 4,
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_widget_show (dlg);
fp_refresh_previews (fpvals.visible_frames);
2004-05-06 17:59:21 +00:00
gtk_main ();
return FPint.run;
}
/***********************************************************/
/************ Advanced Options Window ******************/
/***********************************************************/
static void
fp_drag (GtkWidget *button)
2004-05-06 17:59:21 +00:00
{
static gboolean notFirstTime = FALSE;
if (! notFirstTime)
return;
notFirstTime = TRUE;
if (GTK_TOGGLE_BUTTON (button)->active)
{
fpvals.real_time=TRUE;
gtk_range_set_update_policy (GTK_RANGE (fp_widgets.roughness_scale),0);
gtk_range_set_update_policy (GTK_RANGE (fp_widgets.aliasing_scale),0);
gtk_range_set_update_policy (GTK_RANGE (fp_widgets.preview_size_scale),0);
2004-05-06 17:59:21 +00:00
}
else
{
fpvals.real_time=FALSE;
gtk_range_set_update_policy (GTK_RANGE (fp_widgets.roughness_scale),
GTK_UPDATE_DELAYED);
gtk_range_set_update_policy (GTK_RANGE (fp_widgets.aliasing_scale),
GTK_UPDATE_DELAYED);
gtk_range_set_update_policy (GTK_RANGE (fp_widgets.preview_size_scale),
GTK_UPDATE_DELAYED);
2004-05-06 17:59:21 +00:00
}
}
static void
fp_preview_scale_update (GtkAdjustment *adjustment,
gdouble *scale_val)
2004-05-06 17:59:21 +00:00
{
fpvals.preview_size = adjustment->value;
2004-05-06 17:59:21 +00:00
fp_redraw_all_windows();
}
static void
fp_advanced_dialog (void)
{
gchar *rangeNames[] = { N_("Shadows:"),
N_("Midtones:"),
N_("Highlights:") };
GtkWidget *frame, *mainvbox;
GtkObject *smoothnessData;
GtkWidget *graphFrame, *table, *scale;
GtkWidget *vbox, *label, *labelTable, *alignment, *inner_vbox;
2004-05-06 17:59:21 +00:00
gint i;
AW.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gimp_help_connect (AW.window, gimp_standard_help_func, PLUG_IN_PROC, NULL);
2004-05-06 17:59:21 +00:00
gtk_window_set_title (GTK_WINDOW (AW.window),
_("Advanced Filter Pack Options"));
2004-05-06 17:59:21 +00:00
g_signal_connect (AW.window, "delete-event",
2004-05-06 17:59:21 +00:00
G_CALLBACK (sub_dialog_destroy),
NULL);
mainvbox = gtk_hbox_new (FALSE, 12);
gtk_container_set_border_width (GTK_CONTAINER (mainvbox), 12);
2004-05-06 17:59:21 +00:00
gtk_container_add (GTK_CONTAINER (AW.window), mainvbox);
gtk_widget_show (mainvbox);
frame = gimp_frame_new (_("Smoothness of Aliasing"));
2004-05-06 17:59:21 +00:00
gtk_box_pack_start (GTK_BOX (mainvbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
table = gtk_table_new (3, 1, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2004-05-06 17:59:21 +00:00
gtk_container_add (GTK_CONTAINER (frame), table);
gtk_widget_show (table);
graphFrame = gtk_aspect_frame_new (NULL, 0.5, 0.5, 1, TRUE);
2004-05-06 17:59:21 +00:00
gtk_frame_set_shadow_type (GTK_FRAME (graphFrame), GTK_SHADOW_IN);
gtk_container_set_border_width (GTK_CONTAINER (graphFrame),0);
gtk_widget_show (graphFrame);
gtk_table_attach (GTK_TABLE (table), graphFrame, 0, 1, 0, 1,
GTK_EXPAND, 0, 0, 0);
2004-05-06 17:59:21 +00:00
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (graphFrame), vbox);
gtk_widget_show (vbox);
alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_box_pack_start_defaults (GTK_BOX (vbox), alignment);
gtk_widget_show (alignment);
inner_vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (alignment), inner_vbox);
gtk_widget_show (inner_vbox);
AW.aliasing_preview = gimp_preview_area_new ();
gtk_widget_set_size_request (AW.aliasing_preview, 256, MAX_ROUGHNESS);
gtk_box_pack_start (GTK_BOX (inner_vbox), AW.aliasing_preview, TRUE, TRUE, 0);
gtk_widget_show (AW.aliasing_preview);
2004-05-06 17:59:21 +00:00
fp_create_smoothness_graph (AW.aliasing_preview);
2004-05-06 17:59:21 +00:00
AW.range_preview = gimp_preview_area_new ();
gtk_widget_set_size_request (AW.range_preview, 256, RANGE_HEIGHT);
gtk_box_pack_start(GTK_BOX (inner_vbox), AW.range_preview, TRUE, TRUE, 0);
gtk_widget_show (AW.range_preview);
2004-05-06 17:59:21 +00:00
fp_range_preview_spill (AW.range_preview, fpvals.value_by);
2004-05-06 17:59:21 +00:00
labelTable = gtk_table_new (3, 4, FALSE);
gtk_table_set_col_spacings (GTK_TABLE (labelTable), 6);
gtk_table_set_row_spacings (GTK_TABLE (labelTable), 6);
2004-05-06 17:59:21 +00:00
gtk_widget_show (labelTable);
gtk_table_attach (GTK_TABLE (table), labelTable, 0, 1, 1, 2,
GTK_EXPAND, 0, 0, 0);
2004-05-06 17:59:21 +00:00
for (i = 0; i < 12; i++)
{
label = fp_widgets.range_label[i] = gtk_label_new ("-");
2004-05-06 17:59:21 +00:00
if (!(i % 4))
{
gtk_label_set_text (GTK_LABEL(label), gettext (rangeNames[i/4]));
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
}
2004-05-06 17:59:21 +00:00
gtk_widget_show (label);
gtk_table_attach (GTK_TABLE (labelTable), label, i%4, i%4+1, i/4, i/4+1,
GTK_EXPAND | GTK_FILL, 0, 0, 0);
2004-05-06 17:59:21 +00:00
}
/************************************************************/
AW.aliasing_graph = gtk_drawing_area_new ();
gtk_widget_set_size_request (AW.aliasing_graph,
2004-05-06 17:59:21 +00:00
2 * MARGIN + 256,
RANGE_HEIGHT);
gtk_box_pack_start (GTK_BOX (vbox), AW.aliasing_graph, TRUE, TRUE, 0);
gtk_widget_show (AW.aliasing_graph);
gtk_widget_set_events (AW.aliasing_graph, RANGE_ADJUST_MASK);
2004-05-06 17:59:21 +00:00
g_signal_connect (AW.aliasing_graph, "event",
G_CALLBACK (fp_range_change_events),
&fpvals);
2004-05-06 17:59:21 +00:00
/************************************************************/
smoothnessData = gtk_adjustment_new (fpvals.aliasing,
0, 1.0, 0.05, 0.01, 0.0);
2004-05-06 17:59:21 +00:00
fp_widgets.aliasing_scale = scale =
2004-05-06 17:59:21 +00:00
gtk_hscale_new (GTK_ADJUSTMENT (smoothnessData));
gtk_widget_set_size_request (scale, 200, -1);
gtk_scale_set_digits (GTK_SCALE (scale), 2);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (scale), 0);
gtk_table_attach (GTK_TABLE (table), scale, 0, 1, 2, 3,
0, 0, 0, 0);
2004-05-06 17:59:21 +00:00
gtk_widget_show (scale);
g_signal_connect (smoothnessData, "value-changed",
2004-05-06 17:59:21 +00:00
G_CALLBACK (fp_scale_update),
&fpvals.aliasing);
2004-05-06 17:59:21 +00:00
/******************* MISC OPTIONS ***************************/
vbox = gtk_vbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0);
2004-05-06 17:59:21 +00:00
gtk_widget_show (vbox);
fp_checkbutton_in_box (vbox, _("Preview as You Drag"),
GTK_SIGNAL_FUNC (fp_drag),
NULL, TRUE);
2004-05-06 17:59:21 +00:00
frame = gimp_frame_new (_("Preview Size"));
2004-05-06 17:59:21 +00:00
gtk_widget_show (frame);
smoothnessData = gtk_adjustment_new (fpvals.preview_size,
50, MAX_PREVIEW_SIZE,
5, 5, 0.0);
2004-05-06 17:59:21 +00:00
fp_widgets.preview_size_scale = scale =
2004-05-06 17:59:21 +00:00
gtk_hscale_new (GTK_ADJUSTMENT (smoothnessData));
gtk_container_add (GTK_CONTAINER (frame), scale);
2004-05-06 17:59:21 +00:00
gtk_widget_set_size_request (scale, 100, -1);
gtk_scale_set_digits (GTK_SCALE (scale), 0);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (scale), 0);
gtk_widget_show (scale);
g_signal_connect (smoothnessData, "value-changed",
G_CALLBACK (fp_preview_scale_update),
&fpvals.preview_size);
2004-05-06 17:59:21 +00:00
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
}
static void
slider_erase (GdkWindow *window,
int xpos)
2004-05-06 17:59:21 +00:00
{
gdk_window_clear_area (window, MARGIN + xpos - (RANGE_HEIGHT - 1) / 2, 0,
RANGE_HEIGHT, RANGE_HEIGHT);
2004-05-06 17:59:21 +00:00
}
static void
draw_slider (GdkWindow *window,
GdkGC *border_gc,
GdkGC *fill_gc,
gint xpos)
2004-05-06 17:59:21 +00:00
{
gint i;
for (i = 0; i < RANGE_HEIGHT; i++)
gdk_draw_line (window, fill_gc, MARGIN + xpos-i/2, i, MARGIN + xpos+i/2,i);
2004-05-06 17:59:21 +00:00
gdk_draw_line (window, border_gc, MARGIN + xpos, 0,
MARGIN + xpos - (RANGE_HEIGHT - 1) / 2, RANGE_HEIGHT - 1);
2004-05-06 17:59:21 +00:00
gdk_draw_line (window, border_gc, MARGIN + xpos, 0,
MARGIN + xpos + (RANGE_HEIGHT - 1) / 2, RANGE_HEIGHT - 1);
2004-05-06 17:59:21 +00:00
gdk_draw_line (window, border_gc, MARGIN + xpos- (RANGE_HEIGHT - 1)/2,
RANGE_HEIGHT-1, MARGIN + xpos + (RANGE_HEIGHT-1)/2,
RANGE_HEIGHT - 1);
2004-05-06 17:59:21 +00:00
}
static void
draw_it (GtkWidget *widget)
{
draw_slider (AW.aliasing_graph->window,
AW.aliasing_graph->style->black_gc,
AW.aliasing_graph->style->dark_gc[GTK_STATE_NORMAL],
fpvals.cutoff[SHADOWS]);
draw_slider (AW.aliasing_graph->window,
AW.aliasing_graph->style->black_gc,
AW.aliasing_graph->style->dark_gc[GTK_STATE_NORMAL],
fpvals.cutoff[MIDTONES]);
draw_slider (AW.aliasing_graph->window,
AW.aliasing_graph->style->black_gc,
AW.aliasing_graph->style->dark_gc[GTK_STATE_SELECTED],
fpvals.offset);
}
2004-05-06 17:59:21 +00:00
static gboolean
fp_range_change_events (GtkWidget *widget,
GdkEvent *event,
FPValues *current)
2004-05-06 17:59:21 +00:00
{
GdkEventButton *bevent;
GdkEventMotion *mevent;
gint shad, mid, offset, min;
static guchar *new;
gint x;
switch (event->type)
{
case GDK_EXPOSE:
draw_it (NULL);
break;
2004-05-06 17:59:21 +00:00
case GDK_BUTTON_PRESS:
bevent= (GdkEventButton *) event;
shad = abs (bevent->x - fpvals.cutoff[SHADOWS]);
mid = abs (bevent->x - fpvals.cutoff[MIDTONES]);
offset = abs (bevent->x - fpvals.offset);
2004-05-06 17:59:21 +00:00
min = MIN (MIN (shad, mid), offset);
2004-05-06 17:59:21 +00:00
if (bevent->x >0 && bevent->x<256)
{
if (min == shad)
new = &fpvals.cutoff[SHADOWS];
else if (min == mid)
new = &fpvals.cutoff[MIDTONES];
else
new = &fpvals.offset;
slider_erase (AW.aliasing_graph->window, *new);
*new = bevent->x;
}
2004-05-06 17:59:21 +00:00
draw_it (NULL);
if (fpvals.real_time)
{
fp_range_preview_spill (AW.range_preview, fpvals.value_by);
update_range_labels ();
fp_create_smoothness_graph (AW.aliasing_preview);
fp_refresh_previews (fpvals.visible_frames);
}
2004-05-06 17:59:21 +00:00
break;
case GDK_BUTTON_RELEASE:
if (!fpvals.real_time)
{
fp_range_preview_spill (AW.range_preview, fpvals.value_by);
update_range_labels ();
fp_create_smoothness_graph (AW.aliasing_preview);
fp_refresh_previews (fpvals.visible_frames);
}
2004-05-06 17:59:21 +00:00
break;
case GDK_MOTION_NOTIFY:
mevent = (GdkEventMotion *) event;
gdk_window_get_pointer (widget->window, &x, NULL, NULL);
if (x >= 0 && x < 256)
{
slider_erase (AW.aliasing_graph->window, *new);
*new = x;
draw_it (NULL);
if (fpvals.real_time)
{
fp_range_preview_spill (AW.range_preview, fpvals.value_by);
update_range_labels ();
fp_create_smoothness_graph (AW.aliasing_preview);
fp_refresh_previews (fpvals.visible_frames);
}
}
2004-05-06 17:59:21 +00:00
break;
default:
break;
}
2004-05-06 17:59:21 +00:00
return FALSE;
}
static void
update_range_labels (void)
{
gchar buffer[3];
gtk_label_set_text (GTK_LABEL(fp_widgets.range_label[1]),"0");
2004-05-06 17:59:21 +00:00
g_snprintf (buffer, sizeof (buffer), "%d", fpvals.cutoff[SHADOWS]);
gtk_label_set_text (GTK_LABEL (fp_widgets.range_label[3]), buffer);
gtk_label_set_text (GTK_LABEL (fp_widgets.range_label[5]), buffer);
2004-05-06 17:59:21 +00:00
g_snprintf (buffer, sizeof (buffer), "%d", fpvals.cutoff[MIDTONES]);
gtk_label_set_text (GTK_LABEL (fp_widgets.range_label[7]), buffer);
gtk_label_set_text (GTK_LABEL (fp_widgets.range_label[9]), buffer);
2004-05-06 17:59:21 +00:00
gtk_label_set_text (GTK_LABEL(fp_widgets.range_label[11]), "255");
2004-05-06 17:59:21 +00:00
}
static void
fp_init_filter_packs (void)
2004-05-06 17:59:21 +00:00
{
gint i, j;
for (i = 0; i < 256; i++)
for (j = BY_HUE; j < JUDGE_BY; j++)
2004-05-06 17:59:21 +00:00
{
fpvals.red_adjust [j][i] = 0;
fpvals.green_adjust [j][i] = 0;
fpvals.blue_adjust [j][i] = 0;
fpvals.sat_adjust [j][i] = 0;
2004-05-06 17:59:21 +00:00
}
}
static void
fp_reset_filter_packs (void)
2004-05-06 17:59:21 +00:00
{
fp_init_filter_packs ();
fp_refresh_previews (fpvals.visible_frames);
2004-05-06 17:59:21 +00:00
}
2004-05-06 17:59:21 +00:00
static ReducedImage *
fp_reduce_image (GimpDrawable *drawable,
GimpDrawable *mask,
gint longer_size,
gint selection)
{
gint RH, RW, bytes = drawable->bpp;
gint x, y, width, height;
ReducedImage *temp = g_new0 (ReducedImage, 1);
2004-05-06 17:59:21 +00:00
guchar *tempRGB, *src_row, *tempmask, *src_mask_row, R, G, B;
gint i, j, whichcol, whichrow;
2004-05-06 17:59:21 +00:00
GimpPixelRgn srcPR, srcMask;
gdouble *tempHSV;
GimpRGB rgb;
GimpHSV hsv;
switch (selection)
{
case 0:
x = 0;
width = drawable->width;
y = 0;
height = drawable->height;
break;
case 1:
if (! gimp_drawable_mask_intersect (drawable->drawable_id,
&x, &y, &width, &height))
return temp;
break;
case 2:
if (! gimp_drawable_mask_intersect (drawable->drawable_id,
&x, &y, &width, &height) ||
! gimp_rectangle_intersect (x - width / 2, y - height / 2,
2 * width, 2 * height,
0, 0, drawable->width, drawable->height,
&x, &y, &width, &height))
return temp;
break;
default:
return temp;
}
2004-05-06 17:59:21 +00:00
if (width > height)
{
RW = longer_size;
RH = (gdouble) height * (gdouble) longer_size / (gdouble) width;
2004-05-06 17:59:21 +00:00
}
else
{
RH = longer_size;
RW = (gdouble) width * (gdouble) longer_size / (gdouble) height;
2004-05-06 17:59:21 +00:00
}
tempRGB = g_new (guchar, RW * RH * bytes);
tempHSV = g_new (gdouble, RW * RH * bytes);
tempmask = g_new (guchar, RW * RH);
gimp_pixel_rgn_init (&srcPR, drawable, x, y, width, height, FALSE, FALSE);
gimp_pixel_rgn_init (&srcMask, mask, x, y, width, height, FALSE, FALSE);
src_row = g_new (guchar, width * bytes);
src_mask_row = g_new (guchar, width * bytes);
2004-05-06 17:59:21 +00:00
for (i = 0; i < RH; i++)
{
whichrow = (gdouble) i * (gdouble) height / (gdouble) RH;
2004-05-06 17:59:21 +00:00
gimp_pixel_rgn_get_row (&srcPR, src_row, x, y + whichrow, width);
gimp_pixel_rgn_get_row (&srcMask, src_mask_row, x, y + whichrow, width);
2004-05-06 17:59:21 +00:00
for (j = 0; j < RW; j++)
{
whichcol = (gdouble) j * (gdouble) width / (gdouble) RW;
2004-05-06 17:59:21 +00:00
tempmask[i * RW + j] = src_mask_row[whichcol];
2004-05-06 17:59:21 +00:00
R = src_row[whichcol * bytes + 0];
G = src_row[whichcol * bytes + 1];
B = src_row[whichcol * bytes + 2];
gimp_rgb_set_uchar (&rgb, R, G, B);
gimp_rgb_to_hsv (&rgb, &hsv);
tempRGB[i * RW * bytes + j * bytes + 0] = R;
tempRGB[i * RW * bytes + j * bytes + 1] = G;
tempRGB[i * RW * bytes + j * bytes + 2] = B;
tempHSV[i * RW * bytes + j * bytes + 0] = hsv.h;
tempHSV[i * RW * bytes + j * bytes + 1] = hsv.s;
tempHSV[i * RW * bytes + j * bytes + 2] = hsv.v;
if (bytes == 4)
tempRGB[i * RW * bytes + j * bytes + 3] =
src_row[whichcol * bytes + 3];
}
}
g_free (src_row);
g_free (src_mask_row);
2004-05-06 17:59:21 +00:00
temp->width = RW;
temp->height = RH;
temp->rgb = tempRGB;
temp->hsv = tempHSV;
temp->mask = tempmask;
return temp;
}
static void
fp_render_preview (GtkWidget *preview,
gint change_what,
gint change_which)
{
2004-05-06 17:59:21 +00:00
guchar *a;
gint Inten;
gint bytes = drawable->bpp;
gint i, j, k, nudge, M, m, middle, JudgeBy;
gdouble partial;
gint RW = reduced->width;
gint RH = reduced->height;
gint backupP[3];
gint P[3];
gint tempSat[JUDGE_BY][256];
2004-05-06 17:59:21 +00:00
a = g_new (guchar, 4 * RW * RH);
if (change_what == SATURATION)
for (k = 0; k < 256; k++)
{
for (JudgeBy = BY_HUE; JudgeBy < JUDGE_BY; JudgeBy++)
tempSat[JudgeBy][k] = 0;
tempSat[fpvals.value_by][k] +=
change_which * nudgeArray[(k + fpvals.offset) % 256];
}
for (i = 0; i < RH; i++)
{
for (j = 0; j < RW; j++)
{
backupP[0] = P[0] = reduced->rgb[i * RW * bytes + j * bytes + 0];
backupP[1] = P[1] = reduced->rgb[i * RW * bytes + j * bytes + 1];
backupP[2] = P[2] = reduced->rgb[i * RW * bytes + j * bytes + 2];
m = MIN (MIN (P[0], P[1]), P[2]);
M = MAX (MAX (P[0], P[1]), P[2]);
middle = (M + m) / 2;
for (k = 0; k < 3; k++)
if (P[k] != m && P[k] != M) middle = P[k];
partial = reduced->mask[i * RW + j] / 255.0;
for (JudgeBy = BY_HUE; JudgeBy < JUDGE_BY; JudgeBy++)
{
if (!fpvals.touched[JudgeBy])
continue;
2004-05-06 17:59:21 +00:00
Inten =
reduced->hsv[i * RW * bytes + j * bytes + JudgeBy] * 255.0;
/*DO SATURATION FIRST*/
if (change_what != NONEATALL)
{
if (M != m)
{
for (k = 0; k < 3; k++)
if (backupP[k] == M)
P[k] = MAX (P[k] +
partial * fpvals.sat_adjust[JudgeBy][Inten],
middle);
else if (backupP[k] == m)
P[k] = MIN (P[k] -
partial * fpvals.sat_adjust[JudgeBy][Inten],
middle);
}
P[0] += partial * fpvals.red_adjust[JudgeBy][Inten];
P[1] += partial * fpvals.green_adjust[JudgeBy][Inten];
P[2] += partial * fpvals.blue_adjust[JudgeBy][Inten];
}
}
2004-05-06 17:59:21 +00:00
Inten =
reduced->hsv[i * RW * bytes + j * bytes + fpvals.value_by] * 255.0;
nudge = partial * nudgeArray[(Inten + fpvals.offset) % 256];
2004-05-06 17:59:21 +00:00
switch (change_what)
{
case HUE:
P[0] += colorSign[RED][change_which] * nudge;
P[1] += colorSign[GREEN][change_which] * nudge;
P[2] += colorSign[BLUE][change_which] * nudge;
break;
case SATURATION:
for (JudgeBy = BY_HUE; JudgeBy < JUDGE_BY; JudgeBy++)
for (k = 0; k < 3; k++)
if (M != m)
{
if (backupP[k] == M)
P[k] = MAX (P[k] + partial * tempSat[JudgeBy][Inten],
middle);
else if (backupP[k] == m)
P[k] = MIN (P[k]- partial * tempSat[JudgeBy][Inten],
middle);
}
break;
case VALUE:
P[0] += change_which * nudge;
P[1] += change_which * nudge;
P[2] += change_which * nudge;
break;
default:
break;
}
a[(i * RW + j) * 4 + 0] = CLAMP0255(P[0]);
a[(i * RW + j) * 4 + 1] = CLAMP0255(P[1]);
a[(i * RW + j) * 4 + 2] = CLAMP0255(P[2]);
2004-05-06 17:59:21 +00:00
if (bytes == 4)
a[(i * RW + j) * 4 + 3] = reduced->rgb[i * RW * bytes + j * bytes + 3];
else
a[(i * RW + j) * 4 + 3] = 255;
}
2004-05-06 17:59:21 +00:00
}
gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
0, 0, RW, RH,
GIMP_RGBA_IMAGE,
a,
RW * 4);
g_free (a);
2004-05-06 17:59:21 +00:00
}
static void
update_current_fp (gint change_what,
gint change_which)
2004-05-06 17:59:21 +00:00
{
gint i;
for (i = 0; i < 256; i++)
2004-05-06 17:59:21 +00:00
{
gint nudge;
fp_create_nudge (nudgeArray);
nudge = nudgeArray[(i + fpvals.offset) % 256];
switch (change_what) {
2004-05-06 17:59:21 +00:00
case HUE:
fpvals.red_adjust[fpvals.value_by][i] +=
colorSign[RED][change_which] * nudge;
fpvals.green_adjust[fpvals.value_by][i] +=
colorSign[GREEN][change_which] * nudge;
fpvals.blue_adjust[fpvals.value_by][i] +=
colorSign[BLUE][change_which] * nudge;
break;
2004-05-06 17:59:21 +00:00
case SATURATION:
fpvals.sat_adjust[fpvals.value_by][i] += change_which * nudge;
break;
2004-05-06 17:59:21 +00:00
case VALUE:
fpvals.red_adjust[fpvals.value_by][i] += change_which * nudge;
fpvals.green_adjust[fpvals.value_by][i] += change_which * nudge;
fpvals.blue_adjust[fpvals.value_by][i] += change_which * nudge;
break;
2004-05-06 17:59:21 +00:00
default:
break;
}
2004-05-06 17:59:21 +00:00
}
}
static void
fp_create_smoothness_graph (GtkWidget *preview)
{
guchar data[256 * MAX_ROUGHNESS * 3];
2004-05-06 17:59:21 +00:00
gint nArray[256];
gint i, j;
gboolean toBeBlack;
fp_create_nudge(nArray);
2004-05-06 17:59:21 +00:00
for (i = 0; i < MAX_ROUGHNESS; i++)
{
gint coor = MAX_ROUGHNESS - i;
for (j = 0; j < 256; j++) {
data[3 * (i * 256 + j) + 0] = 255;
data[3 * (i * 256 + j) + 1] = 255;
data[3 * (i * 256 + j) + 2] = 255;
if (!(i % (MAX_ROUGHNESS / 4))) {
data[3 * (i * 256 + j) + 0] = 255;
data[3 * (i * 256 + j) + 1] = 128;
data[3 * (i * 256 + j) + 2] = 128;
}
if (!((j + 1) % 32)) {
data[3 * (i * 256 + j) + 0] = 255;
data[3 * (i * 256 + j) + 1] = 128;
data[3 * (i * 256 + j) + 2] = 128;
}
toBeBlack = FALSE;
if (nArray[j] == coor)
toBeBlack = TRUE;
if (j < 255) {
gint jump = abs (nArray[j] - nArray[j+1]);
if (abs (coor - nArray[j]) < jump &&
abs (coor - nArray[j + 1]) < jump)
toBeBlack = TRUE;
}
if (toBeBlack) {
data[3 * (i * 256 + j) + 0] = 0;
data[3 * (i * 256 + j) + 1] = 0;
data[3 * (i * 256 + j) + 2] = 0;
}
2004-05-06 17:59:21 +00:00
}
}
gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
0, 0, 256, MAX_ROUGHNESS,
GIMP_RGB_IMAGE,
data,
256 * 3);
2004-05-06 17:59:21 +00:00
}
static void
fp_range_preview_spill (GtkWidget *preview,
gint type)
{
gint i, j;
guchar data[256 * RANGE_HEIGHT * 3];
2004-05-06 17:59:21 +00:00
for (i = 0; i < RANGE_HEIGHT; i++)
{
for (j = 0; j < 256; j++)
{
GimpRGB rgb;
GimpHSV hsv;
2004-05-06 17:59:21 +00:00
if (! ((j + 1) % 32))
{
data[3 * (i * 256 + j) + 0] = 255;
data[3 * (i * 256 + j) + 1] = 128;
data[3 * (i * 256 + j) + 2] = 128;
2004-05-06 17:59:21 +00:00
}
else
{
switch (type)
{
case BY_VAL:
data[3 * (i * 256 + j) + 0] = j - fpvals.offset;
data[3 * (i * 256 + j) + 1] = j - fpvals.offset;
data[3 * (i * 256 + j) + 2] = j - fpvals.offset;
2004-05-06 17:59:21 +00:00
break;
2004-05-06 17:59:21 +00:00
case BY_HUE:
gimp_hsv_set (&hsv,
((j - fpvals.offset + 256) % 256) / 255.0,
2004-05-06 17:59:21 +00:00
1.0,
0.5);
gimp_hsv_to_rgb (&hsv, &rgb);
gimp_rgb_get_uchar (&rgb,
&data[3 * (i * 256 + j) + 0],
&data[3 * (i * 256 + j) + 1],
&data[3 * (i * 256 + j) + 2]);
2004-05-06 17:59:21 +00:00
break;
2004-05-06 17:59:21 +00:00
case BY_SAT:
gimp_hsv_set (&hsv,
0.5,
((j-(gint)fpvals.offset+256)%256) / 255.0,
2004-05-06 17:59:21 +00:00
0.5);
gimp_hsv_to_rgb (&hsv, &rgb);
gimp_rgb_get_uchar (&rgb,
&data[3 * (i * 256 + j) + 0],
&data[3 * (i * 256 + j) + 1],
&data[3 * (i * 256 + j) + 2]);
2004-05-06 17:59:21 +00:00
break;
}
}
}
}
gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
0, 0, 256, RANGE_HEIGHT,
GIMP_RGB_IMAGE,
data,
256 * 3);
2004-05-06 17:59:21 +00:00
}
static void
fp_create_nudge (gint *adj_array)
2004-05-06 17:59:21 +00:00
{
gint left, right, middle,i;
/* The following function was determined by trial and error */
gdouble Steepness = pow (1 - fpvals.aliasing, 4) * .8;
2004-05-06 17:59:21 +00:00
left = (fpvals.intensity_range == SHADOWS) ? 0 : fpvals.cutoff[fpvals.intensity_range - 1];
right = fpvals.cutoff[fpvals.intensity_range];
middle = (left + right)/2;
2004-05-06 17:59:21 +00:00
if (fpvals.aliasing)
2004-05-06 17:59:21 +00:00
for (i = 0; i < 256; i++)
if (i <= middle)
adj_array[i] = MAX_ROUGHNESS *
fpvals.roughness * (1 + tanh (Steepness * (i - left))) / 2;
2004-05-06 17:59:21 +00:00
else
adj_array[i] = MAX_ROUGHNESS *
fpvals.roughness * (1 + tanh (Steepness * (right - i))) / 2;
2004-05-06 17:59:21 +00:00
else
for (i = 0; i < 256; i++)
adj_array[i] = (left <= i && i <= right)
? MAX_ROUGHNESS * fpvals.roughness : 0;
2004-05-06 17:59:21 +00:00
}
static void
fp_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
gint which = fpvals.visible_frames;
if (widget == origPreview)
fp_render_preview (origPreview, NONEATALL, 0);
else if (widget == curPreview)
fp_render_preview (curPreview, CURRENT, 0);
if (which & HUE)
{
if (widget == rPreview)
fp_render_preview (rPreview, HUE, RED);
else if (widget == gPreview)
fp_render_preview (gPreview, HUE, GREEN);
else if (widget == bPreview)
fp_render_preview (bPreview, HUE, BLUE);
else if (widget == cPreview)
fp_render_preview (cPreview, HUE, CYAN);
else if (widget == yPreview)
fp_render_preview (yPreview, HUE, YELLOW);
else if (widget == mPreview)
fp_render_preview (mPreview, HUE, MAGENTA);
else if (widget == centerPreview)
fp_render_preview (centerPreview, CURRENT, 0);
}
if (which & VALUE)
{
if (widget == lighterPreview)
fp_render_preview (lighterPreview, VALUE, UP);
else if (widget == middlePreview)
fp_render_preview (middlePreview, CURRENT, 0);
else if (widget == darkerPreview)
fp_render_preview (darkerPreview, VALUE, DOWN);
}
if (which & SATURATION)
{
if (widget == plusSatPreview)
fp_render_preview (plusSatPreview, SATURATION, UP);
else if (widget == SatPreview)
fp_render_preview (SatPreview, CURRENT, 0);
else if (widget == minusSatPreview)
fp_render_preview (minusSatPreview, SATURATION, DOWN);
}
}