gimp/plug-ins/common/illusion.c

345 lines
9.5 KiB
C
Raw Normal View History

/*******************************************************************************
illusion.c -- This is a plug-in for the GIMP 1.0
Copyright (C) 1997 Hirotsuna Mizuno
s1041150@u-aizu.ac.jp
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 <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "libgimp/stdplugins-intl.h"
#define PLUG_IN_NAME "plug_in_illusion"
#define PLUG_IN_VERSION "v0.7 (Dec. 25 1997)"
/******************************************************************************/
static void query (void);
static void run (gchar *name,
gint nparam,
GParam *param,
gint *nreturn_vals,
GParam **return_vals);
static void filter (GDrawable *drawable);
static gboolean dialog (void);
/******************************************************************************/
typedef struct
{
gint32 division;
} parameter_t;
/******************************************************************************/
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
static parameter_t parameters =
{
8
};
static gint image_width;
static gint image_height;
static gint image_bpp;
static gint image_has_alpha;
static gint select_x1;
static gint select_y1;
static gint select_x2;
static gint select_y2;
static gint select_width;
static gint select_height;
static gdouble center_x;
static gdouble center_y;
/******************************************************************************/
MAIN ()
/******************************************************************************/
static void
query (void)
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "interactive / non-interactive" },
{ PARAM_IMAGE, "image", "input image" },
{ PARAM_DRAWABLE, "drawable", "input drawable" },
{ PARAM_INT32, "division", "the number of divisions" }
};
static gint nargs = sizeof (args) / sizeof (args[0]);;
gimp_install_procedure (PLUG_IN_NAME,
"produce illusion",
"produce illusion",
"Hirotsuna Mizuno <s1041150@u-aizu.ac.jp>",
"Hirotsuna Mizuno",
PLUG_IN_VERSION,
N_("<Image>/Filters/Map/Illusion..."),
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs, 0,
args, NULL);
}
/******************************************************************************/
static void
run (gchar *name,
gint nparams,
GParam *params,
gint *nreturn_vals,
GParam **return_vals)
{
GDrawable *drawable;
GRunModeType run_mode;
static GParam returnv[1];
GStatusType status = STATUS_SUCCESS;
run_mode = params[0].data.d_int32;
drawable = gimp_drawable_get (params[2].data.d_drawable);
*nreturn_vals = 1;
*return_vals = returnv;
/* get the drawable info */
image_width = gimp_drawable_width (drawable->id);
image_height = gimp_drawable_height (drawable->id);
image_bpp = gimp_drawable_bpp (drawable->id);
image_has_alpha = gimp_drawable_has_alpha (drawable->id);
gimp_drawable_mask_bounds (drawable->id,
&select_x1, &select_y1, &select_x2, &select_y2);
select_width = select_x2 - select_x1;
select_height = select_y2 - select_y1;
center_x = select_x1 + (gdouble)select_width / 2;
center_y = select_y1 + (gdouble)select_height / 2;
/* switch the run mode */
switch (run_mode)
{
case RUN_INTERACTIVE:
INIT_I18N_UI();
gimp_get_data (PLUG_IN_NAME, &parameters);
if (! dialog())
return;
gimp_set_data (PLUG_IN_NAME, &parameters, sizeof (parameter_t));
break;
case RUN_NONINTERACTIVE:
if (nparams != 4)
{
status = STATUS_CALLING_ERROR;
}
else
{
parameters.division = params[3].data.d_int32;
}
break;
case RUN_WITH_LAST_VALS:
gimp_get_data (PLUG_IN_NAME, &parameters);
break;
}
if (status == STATUS_SUCCESS)
{
if (gimp_drawable_is_rgb (drawable->id) ||
gimp_drawable_is_gray (drawable->id))
{
gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width() + 1));
filter (drawable);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
}
else
{
status = STATUS_EXECUTION_ERROR;
}
}
returnv[0].type = PARAM_STATUS;
returnv[0].data.d_status = status;
gimp_drawable_detach (drawable);
}
/******************************************************************************/
static void
filter (GDrawable *drawable)
{
GPixelRgn srcPR, destPR;
guchar **pixels;
guchar **destpixels;
gint x, y, b;
gint xx, yy;
gdouble scale, radius, cx, cy, angle, offset;
gimp_pixel_rgn_init (&srcPR, drawable,
0, 0, image_width, image_height, FALSE, FALSE);
gimp_pixel_rgn_init (&destPR, drawable,
0, 0, image_width, image_height, TRUE, TRUE);
pixels = (guchar **) g_malloc (image_height * sizeof (guchar *));
destpixels = (guchar **) g_malloc (image_height * sizeof (guchar *));
for (y = 0; y < image_height; y++)
{
pixels[y] = (guchar *) g_malloc (image_width * image_bpp);
destpixels[y] = (guchar *) g_malloc (image_width * image_bpp);
gimp_pixel_rgn_get_row (&srcPR, pixels[y], 0, y, image_width);
}
/*
for( y = select_y1; y < select_y2; y++ ){
for( x = select_x1; x < select_x2; x++ ){
for( b = 0; b < image_bpp; b++ ){
destpixels[y][x*image_bpp+b] = 0;
}
}
}
*/
gimp_progress_init (PLUG_IN_NAME);
scale = sqrt (select_width * select_width + select_height * select_height) / 2;
offset = (gint) (scale / 2);
for (y = select_y1; y < select_y2; y++)
{
cy = ((gdouble)y - center_y) / scale;
for (x = select_x1; x < select_x2; x++)
{
cx = ((gdouble)x - center_x) / scale;
angle = floor (atan2 (cy, cx) * parameters.division / G_PI_2)
* G_PI_2 / parameters.division + (G_PI / parameters.division);
radius = sqrt ((gdouble) (cx * cx + cy * cy));
xx = x - offset * cos (angle);
yy = y - offset * sin (angle);
if (xx < 0) xx = 0;
else if (image_width <= xx) xx = image_width - 1;
if (yy < 0) yy = 0;
else if (image_height <= yy) yy = image_height - 1;
for (b = 0; b < image_bpp; b++)
destpixels[y][x*image_bpp+b] =
(1-radius) * pixels[y][x * image_bpp + b]
+ radius * pixels[yy][xx * image_bpp + b];
}
gimp_pixel_rgn_set_row (&destPR, destpixels[y], 0, y, image_width);
gimp_progress_update ((double) (y - select_y1) / (double) select_height);
}
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id,
select_x1, select_y1, select_width, select_height);
for (y = select_y1; y < select_y2; y++) g_free (pixels[y-select_y1]);
g_free (pixels);
for (y = select_y1; y < select_y2; y++) g_free (destpixels[y-select_y1]);
g_free (destpixels);
}
/******************************************************************************/
static gboolean dialog_status = FALSE;
static void
dialog_ok_handler (GtkWidget *widget,
gpointer data)
{
dialog_status = TRUE;
gtk_widget_destroy (GTK_WIDGET (data));
}
/******************************************************************************/
static gboolean
dialog (void)
{
GtkWidget *window;
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
GtkWidget *frame;
GtkWidget *table;
GtkWidget *spinbutton;
GtkObject *adj;
gimp_ui_init ("illusion", FALSE);
window = gimp_dialog_new (_("Illusion"), "illusion",
gimp_standard_help_func, "filters/illusion.html",
GTK_WIN_POS_MOUSE,
FALSE, TRUE, FALSE,
_("OK"), dialog_ok_handler,
NULL, NULL, NULL, TRUE, FALSE,
_("Cancel"), gtk_widget_destroy,
NULL, 1, NULL, FALSE, TRUE,
NULL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC (gtk_main_quit),
NULL);
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
frame = gtk_frame_new (_("Parameter Settings"));
gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame,
FALSE, FALSE, 0 );
gtk_widget_show (frame);
table = gtk_table_new (1, 2, FALSE);
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
gtk_container_set_border_width (GTK_CONTAINER (table), 4);
gtk_table_set_row_spacings (GTK_TABLE (table), 2);
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-26 01:46:56 +08:00
gtk_container_add (GTK_CONTAINER (frame), table);
gtk_widget_show (table);
spinbutton = gimp_spin_button_new (&adj, parameters.division,
G_MININT, G_MAXINT, 1, 10, 0, 1, 0);
gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
_("Division:"), 1.0, 0.5,
spinbutton, 1, TRUE);
gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
&parameters.division);
gtk_widget_show (window);
gtk_main ();
gdk_flush ();
return dialog_status;
}