gimp/plug-ins/rcm/rcm.c

279 lines
8.0 KiB
C
Raw Normal View History

1999-04-06 04:31:20 +08:00
/*
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This is a plug-in for the GIMP.
*
* Colormap-Rotation plug-in. Exchanges two color ranges.
*
* Copyright (C) 1999 Sven Anders (anderss@fmi.uni-passau.de)
* Based on code from 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.
*/
/*-----------------------------------------------------------------------------------
* Change log:
*
* Version 2.0, 04 April 1999.
* Nearly complete rewrite, made plug-in stable.
* (Works with GIMP 1.1 and GTK+ 1.2)
*
* Version 1.0, 27 March 1997.
* Initial (unstable) release by Pavel Grinfeld
*
*-----------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpintl.h>
#include "rcm.h"
#include "rcm_misc.h"
#include "rcm_dialog.h"
#include "rcm_callback.h"
/*-----------------------------------------------------------------------------------*/
/* Forward declarations */
/*-----------------------------------------------------------------------------------*/
void query(void);
void run(char *name, int nparams, GParam *param, int *nreturn_vals, GParam **return_vals);
/*-----------------------------------------------------------------------------------*/
/* Global variables */
/*-----------------------------------------------------------------------------------*/
RcmParams Current =
{
SELECTION, /* SELECTION ONLY */
TRUE, /* REAL TIME */
FALSE, /* SUCCESS */
RADIANS_OVER_PI, /* START IN RADIANS OVER PI */
GRAY_TO
};
/*-----------------------------------------------------------------------------------*/
/* Local variables */
/*-----------------------------------------------------------------------------------*/
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
/*-----------------------------------------------------------------------------------*/
/* Dummy function */
/*-----------------------------------------------------------------------------------*/
MAIN()
1999-04-06 04:31:20 +08:00
/*-----------------------------------------------------------------------------------*/
/* Query plug-in */
/*-----------------------------------------------------------------------------------*/
void query(void)
{
GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image (used for indexed images)" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
};
GParamDef *return_vals = NULL;
int nargs = sizeof (args) / sizeof (args[0]);
int nreturn_vals = 0;
1999-06-18 17:16:33 +08:00
gimp_install_procedure ("plug-in-rotate-colormap",
1999-04-06 04:31:20 +08:00
"Colormap rotation as in xv",
"Exchanges two color ranges. "\
"Based on code from Pavel Grinfeld (pavel@ml.com). "\
"This version written by Sven Anders (anderss@fmi.uni-passau.de).",
"Sven Anders (anderss@fmi.uni-passau.de) and Pavel Grinfeld (pavel@ml.com)",
"Sven Anders (anderss@fmi.uni-passau.de)",
"04th April 1999",
Reorganized the core menu items (everything except <Image>/Filters). 1999-11-20 Michael Natterer <mitch@gimp.org> Reorganized the core menu items (everything except <Image>/Filters). Everything is of course trivial to change again, so please comment on the new "menu feeling" ;-) * app/menus.[ch]: - Applied the suggestions collected by Olof. - Added "..." to all items which open a dialog. - Introduced some additional separators (e.g. in "Dialogs"). - Reorder some plugins and the color correct tools after initialisation. - A menu entry to invoke the tooltips inspector. - A debugging menu entry which dumps the menu paths and their help pages (will of course go away when the help sys is consistent). There are currently two identical "Help" menus because <Toolbox>/Help trashes the menu bar if the toolbox is too narrow (gtk doesn't seem to support multi-line menubars, any idea?) * app/app_procs.c: call menus_reorder_plugins() after loading the plugins to beautify the "Xtns" menu. * app/commands.[ch]: reordered some functions to match the new menu structure (for easier source navigation) and renamed some to be consistent (e.g. all help functions are now called help_*). Show/Hide the rulers with ordinary gtk_widget_[show|hide]() commands. I've tested it several times and it looks exactly the same as the old code which used internal gtk knowledge. * app/gdisplay.c: applied the menu changes to gdisplay_set_menu_sensitivity(). * app/gimphelp.[ch]: new public function gimp_context_help() which invokes the tooltips inspector. Code cleanup. * app/resize.c: changed the dialogs' titles to match the menu entries. * app/session.c: renamed the gradient selection cmd callback to be consistent with brushes/patterns. * app/tools.c: added "..." to the menu paths of the tools which have dialogs. * app/fileops.c * app/channels_dialog.c * app/layers_dialog.c * app/paths_dialog.c: added some "...". * plug-ins/common/align_layers.c * plug-ins/common/autostretch_hsv.c * plug-ins/common/c_astretch.c * plug-ins/common/color_enhance.c * plug-ins/common/compose.c * plug-ins/common/decompose.c * plug-ins/common/mail.c * plug-ins/common/normalize.c * plug-ins/common/threshold_alpha.c * plug-ins/dbbrowser/dbbrowser.c * plug-ins/fp/fp.c * plug-ins/print/print.c * plug-ins/rcm/rcm.c: changed the menu paths and added "...".
1999-11-20 20:12:41 +08:00
"<Image>/Image/Colors/Colormap Rotation...",
1999-04-06 04:31:20 +08:00
"RGB*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
/*-----------------------------------------------------------------------------------*/
/* Rotate colormap of a single row */
/*-----------------------------------------------------------------------------------*/
void rcm_row(const guchar *src_row, guchar *dest_row,
gint row, gint row_width, gint bytes)
{
gint col, bytenum, skip;
hsv H,S,V,R,G,B;
for (col=0; col < row_width; col++)
{
skip = 0;
R = (float)src_row[col*bytes + 0]/255.0;
G = (float)src_row[col*bytes + 1]/255.0;
B = (float)src_row[col*bytes + 2]/255.0;
rgb_to_hsv(R,G,B, &H,&S,&V);
if (rcm_is_gray(S))
{
if (Current.Gray_to_from == GRAY_FROM)
{
if (rcm_angle_inside_slice(Current.Gray->hue,Current.From->angle) <= 1)
{
H = Current.Gray->hue / TP;
S = Current.Gray->satur;
}
else
{
skip = 1;
}
}
else
{
skip = 1;
hsv_to_rgb(Current.Gray->hue/TP, Current.Gray->satur, V, &R, &G, &B);
}
}
if (!skip)
{
H = rcm_linear(rcm_left_end(Current.From->angle),
rcm_right_end(Current.From->angle),
rcm_left_end(Current.To->angle),
rcm_right_end(Current.To->angle),
H*TP);
H = angle_mod_2PI(H) / TP;
hsv_to_rgb(H,S,V, &R,&G,&B);
}
dest_row[col*bytes +0] = R * 255;
dest_row[col*bytes +1] = G * 255;
dest_row[col*bytes +2] = B * 255;
if (bytes > 3)
{
for (bytenum=3; bytenum<bytes; bytenum++)
dest_row[col*bytes+bytenum] = src_row[col*bytes+bytenum];
}
}
}
/*-----------------------------------------------------------------------------------*/
/* Rotate colormap row by row ... */
/*-----------------------------------------------------------------------------------*/
void rcm(GDrawable *drawable)
{
GPixelRgn srcPR, destPR;
gint width, height;
gint bytes;
guchar *src_row, *dest_row;
gint row;
gint x1, y1, x2, y2;
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
width = drawable->width;
height = drawable->height;
bytes = drawable->bpp;
src_row = (guchar *) malloc ((x2 - x1) * bytes);
dest_row = (guchar *) malloc ((x2 - x1) * bytes);
gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
gimp_pixel_rgn_init(&destPR, drawable, 0, 0, width, height, TRUE, TRUE);
for (row=y1; row < y2; row++)
{
gimp_pixel_rgn_get_row(&srcPR, src_row, x1, row, (x2 - x1));
rcm_row(src_row, dest_row, row, (x2 - x1), bytes);
gimp_pixel_rgn_set_row(&destPR, dest_row, x1, row, (x2 - x1));
if ((row % 10) == 0)
gimp_progress_update((double) row / (double) (y2 - y1));
}
/* update the processed region */
gimp_drawable_flush(drawable);
gimp_drawable_merge_shadow(drawable->id, TRUE);
gimp_drawable_update(drawable->id, x1, y1, (x2 - x1), (y2 - y1));
free (src_row);
free (dest_row);
}
/*-----------------------------------------------------------------------------------*/
/* STANDARD RUN */
/*-----------------------------------------------------------------------------------*/
void run(char *name, int nparams, GParam *param, int *nreturn_vals, GParam **return_vals)
{
GParam values[1];
GStatusType status = STATUS_SUCCESS;
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
Current.drawable = gimp_drawable_get(param[2].data.d_drawable);
Current.mask = gimp_drawable_get(gimp_image_get_selection(param[1].data.d_image));
/* works not on INDEXED images */
1999-10-17 08:07:55 +08:00
if (gimp_drawable_is_indexed (Current.drawable->id) ||
gimp_drawable_is_gray (Current.drawable->id) )
1999-04-06 04:31:20 +08:00
{
status = STATUS_EXECUTION_ERROR;
}
else
{
/* call dialog and rotate the colormap */
1999-10-25 04:49:09 +08:00
if (gimp_drawable_is_rgb(Current.drawable->id) && rcm_dialog())
1999-04-06 04:31:20 +08:00
{
gimp_progress_init(_("Rotating the colormap..."));
gimp_tile_cache_ntiles(2 * (Current.drawable->width / gimp_tile_width() + 1));
rcm(Current.drawable);
gimp_displays_flush();
}
else
status = STATUS_EXECUTION_ERROR;
}
values[0].data.d_status = status;
if (status == STATUS_SUCCESS)
gimp_drawable_detach(Current.drawable);
}