/* harmonic.c * by Heinz Sollich * 04/1998 * * paints a harmonic (sinus-like) color distribution */ /* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "libgimp/gimp.h" #include "gtk/gtk.h" /* Declare local functions. */ static void query(void); static void run(char *name, int nparams, GimpParam * param, int *nreturn_vals, GimpParam ** return_vals); static gint dialog(); static void doit(GimpDrawable * drawable); GimpPlugInInfo PLUG_IN_INFO = { NULL, /* init_proc */ NULL, /* quit_proc */ query, /* query_proc */ run, /* run_proc */ }; gint bytes; gint width, height; gint sx1, sy1, sx2, sy2; int run_flag = 0; float *fx, *fy; typedef struct { float phasexr, phaseyr; float phasexg, phaseyg; float phasexb, phaseyb; float density; } config; config bval = { 0.00, 0.00, 0.17, 0.33, 0.80, 0.67 }; MAIN() static void query() { static GimpParamDef args[] = { {GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive"}, {GIMP_PDB_IMAGE, "image", "Input image (unused)"}, {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"}, {GIMP_PDB_FLOAT, "phasexr", "Phase x red"}, {GIMP_PDB_FLOAT, "phaseyr", "Phase y red"}, {GIMP_PDB_FLOAT, "phasexg", "Phase x green"}, {GIMP_PDB_FLOAT, "phaseyg", "Phase y green"}, {GIMP_PDB_FLOAT, "phasexb", "Phase x blue"}, {GIMP_PDB_FLOAT, "phaseyb", "Phase y blue"}, }; static GimpParamDef *return_vals = NULL; static int nargs = sizeof(args) / sizeof(args[0]); static int nreturn_vals = 0; gimp_install_procedure("plug_in_harmonic", "paints a harmonic (sinus-like) color distribution (tileable).", "more help", "Heinz Sollich ", "Heinz Sollich", "1998", "/Filters/Render/Harmonic Colors", "RGB*", GIMP_PLUGIN, nargs, nreturn_vals, args, return_vals); } /* query() */ static void run(char *name, int n_params, GimpParam * param, int *nreturn_vals, GimpParam ** return_vals) { static GimpParam values[1]; GimpDrawable *drawable; GimpRunModeType run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; *nreturn_vals = 1; *return_vals = values; run_mode = param[0].data.d_int32; if (run_mode == GIMP_RUN_NONINTERACTIVE) { if (n_params != 9) { status = GIMP_PDB_CALLING_ERROR; } else { bval.phasexr = param[3].data.d_float; bval.phaseyr = param[4].data.d_float; bval.phasexg = param[5].data.d_float; bval.phaseyg = param[6].data.d_float; bval.phasexb = param[7].data.d_float; bval.phaseyb = param[8].data.d_float; } } else { /* Possibly retrieve data */ gimp_get_data("plug_in_harmonic", &bval); if (run_mode == GIMP_RUN_INTERACTIVE) { if (!dialog()) { /* The dialog was closed, or something similarly evil happened. */ status = GIMP_PDB_EXECUTION_ERROR; } } } if (status == GIMP_PDB_SUCCESS) { /* Get the specified drawable */ drawable = gimp_drawable_get(param[2].data.d_drawable); /* Make sure that the drawable is gray or RGB color */ if ( gimp_drawable_is_rgb(drawable->id) ) { gimp_progress_init("Drawing Harmonic..."); gimp_tile_cache_ntiles(2 * (drawable->width / gimp_tile_width() + 1)); doit(drawable); if (run_mode != GIMP_RUN_NONINTERACTIVE) gimp_displays_flush(); if (run_mode == GIMP_RUN_INTERACTIVE) gimp_set_data("plug_in_harmonic", &bval, sizeof(bval)); } else { status = GIMP_PDB_EXECUTION_ERROR; } gimp_drawable_detach(drawable); } values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = status; } /* run() */ static void make_tables() { int i; float x, y, *p, pi2=3.14159*2; fx = (float*) malloc(2 * width * sizeof(float)); fy = (float*) malloc(2 * height * sizeof(float)); p = fx; for (i=0; i 3 ) for (j = 0; j < sw; j++) for (k = 0; k < sh; k++) tmp[(j + sw * k) * bytes + 3] = 255; gimp_pixel_rgn_set_rect(region, tmp, sx1, sy1, sw, sh); } /* draw */ static void doit(GimpDrawable * drawable) { GimpPixelRgn srcPR, destPR; int sw, sh; int i; guchar *tmp, *copybuf; gimp_drawable_mask_bounds(drawable->id, &sx1, &sy1, &sx2, &sy2); width = drawable->width; height = drawable->height; bytes = drawable->bpp; sw = sx2 - sx1; sh = sy2 - sy1; make_tables(); tmp = (guchar *) malloc(sw * sh * bytes); if (tmp == NULL) { return; } /* initialize the pixel regions */ gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, FALSE); gimp_pixel_rgn_init(&destPR, drawable, 0, 0, width, height, TRUE, TRUE); /* First off, copy the old one to the new one. */ copybuf = malloc(sw * bytes); if (copybuf == NULL) { return; } for (i = sy1; i < sy2; i++) { gimp_pixel_rgn_get_row(&srcPR, copybuf, sx1, i, sw); gimp_pixel_rgn_set_row(&destPR, copybuf, sx1, i, sw); } free(copybuf); draw(tmp, &destPR); free(tmp); gimp_drawable_flush(drawable); gimp_drawable_merge_shadow(drawable->id, TRUE); gimp_drawable_update(drawable->id, sx1, sy1, sw, sh); } /* doit */ static void close_callback(GtkWidget * widget, gpointer data) { gtk_main_quit(); } static void ok_callback(GtkWidget * widget, gpointer data) { run_flag = 1; gtk_widget_destroy(GTK_WIDGET(data)); } static void entry_callback(GtkWidget * widget, gpointer data) { if (data == &bval.phasexr) bval.phasexr = atof(gtk_entry_get_text(GTK_ENTRY(widget))); else if (data == &bval.phaseyr) bval.phaseyr = atof(gtk_entry_get_text(GTK_ENTRY(widget))); else if (data == &bval.phasexg) bval.phasexg = atof(gtk_entry_get_text(GTK_ENTRY(widget))); else if (data == &bval.phaseyg) bval.phaseyg = atof(gtk_entry_get_text(GTK_ENTRY(widget))); else if (data == &bval.phasexb) bval.phasexb = atof(gtk_entry_get_text(GTK_ENTRY(widget))); else if (data == &bval.phaseyb) bval.phaseyb = atof(gtk_entry_get_text(GTK_ENTRY(widget))); } static gint dialog() { GtkWidget *dlg; GtkWidget *button; GtkWidget *label; GtkWidget *entry; GtkWidget *table; gchar buffer[12]; gchar **argv; gint argc; argc = 1; argv = g_new(gchar *, 1); argv[0] = g_strdup("plasma"); gtk_init(&argc, &argv); gtk_rc_parse (gimp_gtkrc ()); dlg = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(dlg), "Harmonic"); gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE); gtk_signal_connect(GTK_OBJECT(dlg), "destroy", (GtkSignalFunc) close_callback, NULL); /* Action area */ button = gtk_button_new_with_label("OK"); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) ok_callback, dlg); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button, TRUE, TRUE, 0); gtk_widget_grab_default(button); gtk_widget_show(button); button = gtk_button_new_with_label("Cancel"); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", (GtkSignalFunc) gtk_widget_destroy, GTK_OBJECT(dlg)); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button, TRUE, TRUE, 0); gtk_widget_show(button); /* The main table */ /* Set its size (y, x) */ table = gtk_table_new(5, 3, FALSE); gtk_container_border_width(GTK_CONTAINER(table), 10); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), table, TRUE, TRUE, 0); gtk_widget_show(table); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); /********************** * Phaselabels **********************/ label = gtk_label_new("Phase x:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show(label); label = gtk_label_new("Phase y:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show(label); /********************* * red *********************/ label = gtk_label_new("red:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_set_usize(entry, 50, 0); sprintf(buffer, "%0.2f", bval.phasexr); gtk_entry_set_text(GTK_ENTRY(entry), buffer); gtk_signal_connect(GTK_OBJECT(entry), "changed", (GtkSignalFunc) entry_callback, &bval.phasexr); gtk_widget_show(entry); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_set_usize(entry, 50, 0); sprintf(buffer, "%0.2f", bval.phaseyr); gtk_entry_set_text(GTK_ENTRY(entry), buffer); gtk_signal_connect(GTK_OBJECT(entry), "changed", (GtkSignalFunc) entry_callback, &bval.phaseyr); gtk_widget_show(entry); /********************** * green **********************/ label = gtk_label_new("green:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_set_usize(entry, 50, 0); sprintf(buffer, "%0.2f", bval.phasexg); gtk_entry_set_text(GTK_ENTRY(entry), buffer); gtk_signal_connect(GTK_OBJECT(entry), "changed", (GtkSignalFunc) entry_callback, &bval.phasexg); gtk_widget_show(entry); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 2, 3, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_set_usize(entry, 50, 0); sprintf(buffer, "%0.2f", bval.phaseyg); gtk_entry_set_text(GTK_ENTRY(entry), buffer); gtk_signal_connect(GTK_OBJECT(entry), "changed", (GtkSignalFunc) entry_callback, &bval.phaseyg); gtk_widget_show(entry); /************************ * blue ************************/ label = gtk_label_new("blue:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_set_usize(entry, 50, 0); sprintf(buffer, "%0.2f", bval.phasexb); gtk_entry_set_text(GTK_ENTRY(entry), buffer); gtk_signal_connect(GTK_OBJECT(entry), "changed", (GtkSignalFunc) entry_callback, &bval.phasexb); gtk_widget_show(entry); entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), entry, 2, 3, 4, 5, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_set_usize(entry, 50, 0); sprintf(buffer, "%0.2f", bval.phaseyb); gtk_entry_set_text(GTK_ENTRY(entry), buffer); gtk_signal_connect(GTK_OBJECT(entry), "changed", (GtkSignalFunc) entry_callback, &bval.phaseyb); gtk_widget_show(entry); gtk_widget_show(dlg); gtk_main(); gdk_flush(); return run_flag; }