20
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
/* Value-Invert plug-in v1.1 by Adam D. Moss, adam@foxbox.org. 1999/02/27
21
* RGB<->HSV math optimizations by Mukund Sivaraman <muks@mukund.org>
22
* makes the plug-in 2-3 times faster. Using gimp_pixel_rgns_process()
23
* also makes memory management nicer. June 12, 2006.
25
* The plug-in only does v = 255 - v; for each pixel in the image, or
26
* each entry in the colormap depending upon the type of image, where 'v'
27
* is the value in HSV color model.
29
* The plug-in code is optimized towards this, in that it is not a full
30
* RGB->HSV->RGB transform, but shortcuts many of the calculations to
31
* effectively only do v = 255 - v. In fact, hue (0-360) is never
32
* calculated. The shortcuts can be derived from running a set of r, g, b
33
* values through the RGB->HSV transform and then from HSV->RGB and solving
34
* out the redundant portions.
36
* The plug-in also uses integer code exclusively for the main transform.
23
39
#include "config.h"
28
43
#include <libgimp/gimp.h>
30
45
#include "libgimp/stdplugins-intl.h"
48
#define PLUG_IN_PROC "plug-in-vinvert"
33
51
/* Declare local functions.
35
53
static void query (void);
64
static GimpParamDef args[] =
82
static const GimpParamDef args[] =
66
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
84
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
67
85
{ GIMP_PDB_IMAGE, "image", "Input image (used for indexed images)" },
68
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
86
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
71
gimp_install_procedure ("plug_in_vinvert",
72
"Invert the 'value' component of an indexed/RGB "
73
"image in HSV colorspace",
74
"This function takes an indexed/RGB image and "
75
"inverts its 'value' in HSV space. The upshot of "
76
"this is that the color and saturation at any given "
77
"point remains the same, but its brightness is "
78
"effectively inverted. Quite strange. Sometimes "
79
"produces unpleasant color artifacts on images from "
80
"lossy sources (ie. JPEG).",
81
"Adam D. Moss (adam@foxbox.org)",
82
"Adam D. Moss (adam@foxbox.org)",
87
G_N_ELEMENTS (args), 0,
89
gimp_install_procedure (PLUG_IN_PROC,
90
N_("Invert the brightness of each pixel"),
91
"This function takes an indexed/RGB image and "
92
"inverts its 'value' in HSV space. The upshot of "
93
"this is that the color and saturation at any given "
94
"point remains the same, but its brightness is "
95
"effectively inverted. Quite strange. Sometimes "
96
"produces unpleasant color artifacts on images from "
97
"lossy sources (ie. JPEG).",
98
"Adam D. Moss (adam@foxbox.org), "
99
"Mukund Sivaraman <muks@mukund.org>",
100
"Adam D. Moss (adam@foxbox.org), "
101
"Mukund Sivaraman <muks@mukund.org>",
107
G_N_ELEMENTS (args), 0,
90
gimp_plugin_menu_register ("plug_in_vinvert", "<Image>/Filters/Colors");
110
gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Colors/Invert");
111
131
values[0].type = GIMP_PDB_STATUS;
112
132
values[0].data.d_status = status;
114
/* Get the specified drawable */
115
drawable = gimp_drawable_get (param[2].data.d_drawable);
116
image_ID = param[1].data.d_image;
118
if (status == GIMP_PDB_SUCCESS)
134
if (strcmp (name, PLUG_IN_PROC) == 0)
136
GimpDrawable *drawable;
139
/* Get the specified drawable */
141
drawable = gimp_drawable_get (param[2].data.d_drawable);
142
image_ID = param[1].data.d_image;
120
144
/* Make sure that the drawable is indexed or RGB color */
121
146
if (gimp_drawable_is_rgb (drawable->drawable_id))
123
if (run_mode != GIMP_RUN_NONINTERACTIVE)
126
gimp_progress_init (_("Value Invert..."));
130
if (run_mode != GIMP_RUN_NONINTERACTIVE)
131
gimp_displays_flush ();
150
if (run_mode != GIMP_RUN_NONINTERACTIVE)
151
gimp_displays_flush ();
153
else if (gimp_drawable_is_indexed (drawable->drawable_id))
155
vinvert_indexed (image_ID);
157
if (run_mode != GIMP_RUN_NONINTERACTIVE)
158
gimp_displays_flush ();
134
if (gimp_drawable_is_indexed (drawable->drawable_id))
136
indexed_vinvert (image_ID);
137
if (run_mode != GIMP_RUN_NONINTERACTIVE)
138
gimp_displays_flush ();
142
status = GIMP_PDB_EXECUTION_ERROR;
162
status = GIMP_PDB_EXECUTION_ERROR;
165
gimp_drawable_detach (drawable);
169
status = GIMP_PDB_CALLING_ERROR;
146
172
values[0].data.d_status = status;
148
gimp_drawable_detach (drawable);
152
indexed_vinvert (gint32 image_ID)
176
vinvert (GimpDrawable *drawable)
178
gint x, y, width, height;
179
gdouble total, processed;
182
GimpPixelRgn src_rgn, dest_rgn;
183
guchar *src_row, *dest_row;
187
if (! gimp_drawable_mask_intersect (drawable->drawable_id,
188
&x, &y, &width, &height))
191
gimp_progress_init (_("Value Invert"));
193
channels = gimp_drawable_bpp (drawable->drawable_id);
195
gimp_pixel_rgn_init (&src_rgn, drawable, x, y, width, height, FALSE, FALSE);
196
gimp_pixel_rgn_init (&dest_rgn, drawable, x, y, width, height, TRUE, TRUE);
198
total = width * height;
201
for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn), update = 0;
203
pr = gimp_pixel_rgns_process (pr), update++)
205
src_row = src_rgn.data;
206
dest_row = dest_rgn.data;
208
for (i = 0; i < src_rgn.h; i++)
210
vinvert_render_row (src_row, dest_row, src_rgn.w, channels);
212
src_row += src_rgn.rowstride;
213
dest_row += dest_rgn.rowstride;
216
processed += src_rgn.w * src_rgn.h;
220
gimp_progress_update (processed / total);
223
gimp_progress_update (1.0);
225
gimp_drawable_flush (drawable);
226
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
227
gimp_drawable_update (drawable->drawable_id, x, y, width, height);
232
vinvert_indexed (gint32 image_ID)
169
vinvert_func (const guchar *src,
180
gimp_rgb_to_hsv_int (&v1, &v2, &v3);
182
gimp_hsv_to_rgb_int (&v1, &v2, &v3);
193
249
vinvert_render_row (const guchar *src,
195
gint row_width, /* in pixels */
251
gint width, /* in pixels */
256
gint value, value2, min;
259
for (j = 0; j < width; j++)
200
vinvert_func (src, dest, bpp, NULL);
277
if ((value == 0) || (delta == 0))
290
b = ((r * b) + value2) / value;
291
g = ((r * g) + value2) / value;
296
r = ((g * r) + value2) / value;
297
b = ((g * b) + value2) / value;
302
g = ((b * g) + value2) / value;
303
r = ((b * r) + value2) / value;
207
vinvert (GimpDrawable *drawable)
209
gimp_rgn_iterate2 (drawable, 0 /* unused */, vinvert_func, NULL);