new source files that implement pixel Look Up Table functions.

* app/gimplut.[ch]: new source files that implement pixel Look Up
 	Table functions.

	* app/Makefile.am: build gimplut.[ch]


	* app/brightness_contrast.c
	* app/curves.c
	* app/invert.c
	* app/levels.c
	* app/posterize.c: Use the new lut functions.  Use
 	pixel_region_process_parallel in the PDB versions of these routines.

	* libgimp/parasite.h
	* libgimp/parasite.c: new functions parasite_name and
 	parasite_compare.

	* app/gimpdrawable.c:
	* app/gimpdrawable.h: new function
 	gimp_drawable_get_color_at(...) returns the RGBA[color index]
 	value at a specified position in the drawable.  Don't set the dirty
 	bit on the image if a new parasite is the same as the old.

	* app/gimpimage.c
	* app/gimpimage.h new function
 	gimp_image_get_color_at(...) returns the RGBA[color index]
 	value at a specified position in the drawable.  Don't set the dirty
 	bit on the image if a new parasite is the same as the old.

	* app/by_color_select.c
	* app/color_picker.c: use the new gimp_*_get_color_at
 	functions instead of messing with the tiles.

	* app/layer.c: fixed a minor warning.

	* app/commands.c:
	don't scale the image if the new size == the old size

	* app/channel.c: optimized channel_bounds by only checking the
 	pixels in a tile if it is not already entirely within the
 	currently computed bounds.
This commit is contained in:
jaycox 1999-02-16 08:53:54 +00:00
parent ed92f2189f
commit a26f8d3f5c
63 changed files with 1846 additions and 1171 deletions

View File

@ -186,6 +186,8 @@ gimp_SOURCES = \
gimplist.h \
gimplistF.h \
gimplistP.h \
gimplut.c \
gimplut.h \
gimpparasite.c \
gimpparasite.h \
gimpprogress.c \

View File

@ -1133,7 +1133,9 @@ image_scale_callback (GtkWidget *w,
image_scale = (ImageResize *) client_data;
if ((gimage = image_scale->gimage) != NULL)
if ((gimage = image_scale->gimage) != NULL &&
(image_scale->resize->width != gimage->width ||
image_scale->resize->height != gimage->height))
{
if (image_scale->resize->width > 0 &&
image_scale->resize->height > 0)

View File

@ -30,6 +30,7 @@
#include "image_map.h"
#include "interface.h"
#include "curves.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -96,6 +97,8 @@ struct _CurvesDialog
int curve_type;
int points[5][17][2];
unsigned char curve[5][256];
GimpLut *lut;
};
typedef double CRMatrix[4][4];
@ -141,65 +144,49 @@ static CRMatrix CR_basis =
};
static void curves (PixelRegion *, PixelRegion *, void *);
static Argument * curves_spline_invoker (Argument *);
static Argument * curves_explicit_invoker (Argument *);
/* curves machinery */
static void
curves (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
curves_lut_func(CurvesDialog *cd,
int nchannels, int channel, float value)
{
CurvesDialog *cd;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h;
float f;
int index;
double inten;
int j;
cd = (CurvesDialog *) user_data;
if (nchannels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
the first time and j = 0 the second time */
/* For bw images this runs through the loop with j = 0 the first and
only time */
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (nchannels == 2 || nchannels == 4)
&& channel == nchannels -1)
return inten;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
while (h--)
if (inten < 0.0)
inten = cd->curve[j][0]/255.0;
else if (inten >= 1.0)
inten = cd->curve[j][255]/255.0;
else /* interpolate the curve */
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (cd->color)
{
/* The contributions from the individual channel level settings */
d[RED_PIX] = cd->curve[HISTOGRAM_RED][s[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_GREEN][s[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_BLUE][s[BLUE_PIX]];
/* The overall changes */
d[RED_PIX] = cd->curve[HISTOGRAM_VALUE][d[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_VALUE][d[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_VALUE][d[BLUE_PIX]];
}
else
d[GRAY_PIX] = cd->curve[HISTOGRAM_VALUE][s[GRAY_PIX]];
if (has_alpha) {
d[alpha] = cd->curve[HISTOGRAM_ALPHA][s[alpha]];
/* d[alpha] = s[alpha]; */
}
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
index = floor(inten * 255.0);
f = inten*255.0 - index;
inten = ((1.0 - f) * cd->curve[j][index ] +
( f) * cd->curve[j][index + 1] ) / 255.0;
}
}
return inten;
}
/* curves action functions */
@ -446,6 +433,7 @@ curves_new_dialog ()
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd->curve[i][j] = j;
cd->lut = gimp_lut_new();
for (i = 0; i < 5; i++)
channel_items [i].user_data = (gpointer) cd;
@ -810,6 +798,9 @@ curves_calculate_curve (CurvesDialog *cd)
}
break;
}
gimp_lut_setup(cd->lut, (GimpLutFunc) curves_lut_func,
(void *) cd, gimp_drawable_bytes(cd->drawable));
}
static void
@ -820,7 +811,8 @@ curves_preview (CurvesDialog *cd)
active_tool->preserve = TRUE; /* Going to dirty the display... */
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
active_tool->preserve = FALSE; /* All done */
}
@ -988,7 +980,8 @@ curves_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE; /* We're about to dirty... */
if (!cd->preview)
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
if (cd->image_map)
image_map_commit (cd->image_map);
@ -1361,6 +1354,7 @@ curves_spline_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
@ -1407,6 +1401,7 @@ curves_spline_invoker (Argument *args)
/* arrange to modify the curves */
if (success)
{
cd.lut = gimp_lut_new();
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd.curve[i][j] = j;
@ -1435,9 +1430,10 @@ curves_spline_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
gimp_lut_free(cd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
@ -1509,6 +1505,7 @@ curves_explicit_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
@ -1564,15 +1561,18 @@ curves_explicit_invoker (Argument *args)
for (j = 0; j < 256; j++)
cd.curve[cd.channel][j] = curve[j];
cd.lut = gimp_lut_new();
gimp_lut_setup(cd.lut, (GimpLutFunc) curves_lut_func,
(void *) &cd, gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

169
app/base/gimplut.c Normal file
View File

@ -0,0 +1,169 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplut.c: Copyright (C) 1999 Jay Cox <jaycox@earthlink.net>
*
* 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 "gimplutP.h"
#include "gimplut.h"
#include <stdio.h>
GimpLut *
gimp_lut_new()
{
GimpLut *lut;
lut = g_new(GimpLut, 1);
lut->luts = NULL;
lut->nchannels = 0;
return lut;
}
void
gimp_lut_free(GimpLut *lut)
{
int i;
for (i = 0; i < lut->nchannels; i++)
g_free(lut->luts[i]);
if (lut->luts)
g_free(lut->luts);
}
void
gimp_lut_setup (GimpLut *lut, GimpLutFunc func,
void *user_data, int nchannels)
{
int i, v;
double val;
if (lut->luts)
{
for (i = 0; i < lut->nchannels; i++)
g_free(lut->luts[i]);
g_free(lut->luts);
}
lut->nchannels = nchannels;
lut->luts = g_new(unsigned char*, lut->nchannels);
for (i = 0; i < lut->nchannels; i++)
{
lut->luts[i] = g_new(unsigned char, 256);
for (v = 0; v < 256; v++)
{ /* to add gamma correction use func(v ^ g) ^ 1/g instead. */
val = 255.0 * func(user_data, lut->nchannels, i, v/255.0) + 0.5;
if (val < 0.0)
lut->luts[i][v] = 0;
else if (val >= 255.0)
lut->luts[i][v] = 255;
else
lut->luts[i][v] = val;
}
}
}
void
gimp_lut_setup_exact (GimpLut *lut, GimpLutFunc func,
void *user_data, int nchannels)
{
gimp_lut_setup(lut, func, user_data, nchannels);
}
void
gimp_lut_process (GimpLut *lut,
PixelRegion *srcPR,
PixelRegion *destPR)
{
int h, width, src_r_i, dest_r_i;
unsigned char *src, *dest;
unsigned char *lut0, *lut1, *lut2, *lut3;
if (lut->nchannels > 0)
lut0 = lut->luts[0];
if (lut->nchannels > 1)
lut1 = lut->luts[1];
if (lut->nchannels > 2)
lut2 = lut->luts[2];
if (lut->nchannels > 3)
lut3 = lut->luts[3];
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
width = srcPR->w;
src_r_i = srcPR->rowstride - (srcPR->bytes * srcPR->w);
dest_r_i = destPR->rowstride - (destPR->bytes * srcPR->w);
if (src_r_i == 0 && dest_r_i == 0)
{
width *= h;
h = 1;
}
while (h--)
{
switch (lut->nchannels)
{
case 1:
while (width--)
{
*dest = lut0[*src];
src++;
dest++;
}
break;
case 2:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
src += 2;
dest += 2;
}
break;
case 3:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
dest[2] = lut2[src[2]];
src += 3;
dest += 3;
}
break;
case 4:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
dest[2] = lut2[src[2]];
dest[3] = lut3[src[3]];
src += 4;
dest += 4;
}
break;
default:
fprintf(stderr, "gimplut: Error: nchannels = %d\n", lut->nchannels);
}
width = srcPR->w;
src += src_r_i;
dest += dest_r_i;
}
}
void
gimp_lut_process_2 (PixelRegion *srcPR,
PixelRegion *destPR,
GimpLut *lut)
{
gimp_lut_process(lut, srcPR, destPR);
}

61
app/base/gimplut.h Normal file
View File

@ -0,0 +1,61 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplut.h: Copyright (C) 1999 Jay Cox <jaycox@earthlink.net>
*
* 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.
*/
#ifndef __GIMP_LUT_H__
#define __GIMP_LUT_H__
#include "gimplutF.h"
#include "pixel_region.h"
/* TODO: the GimpLutFunc should really be passed the ColorModel of the region,
not just the number of channels */
/* GimpLutFuncs should assume that the input and output gamma are 1.0
and do no correction as this will be handled by gimp_lut_setup */
typedef float (*GimpLutFunc)(void *user_data, int nchannels,
int channel, float value);
GimpLut * gimp_lut_new ();
void gimp_lut_free (GimpLut *lut);
void gimp_lut_setup (GimpLut *, GimpLutFunc,
void *user_data,
int nchannels);
/* gimp_lut_setup_exact is currently identical to gimp_lut_setup. It
however is guaranteed to never perform any interpolation or gamma
correction on the lut */
void gimp_lut_setup_exact (GimpLut *, GimpLutFunc,
void *user_data,
int nchannels);
void gimp_lut_process (GimpLut *lut,
PixelRegion *srcPR,
PixelRegion *destPR);
/* gimp_lut_process_2 is the same as gimp_lut_process but the lut
perameter is last instead of first. this is necesary because
pixel_region_process_paralell sends the user_data as the 1st
parameter, and the image_map functions send user_data as the last
parameter */
void gimp_lut_process_2 (PixelRegion *srcPR,
PixelRegion *destPR,
GimpLut *lut);
#endif /* __GIMP_LUT_H__ */

View File

@ -27,6 +27,7 @@
#include "gdisplay.h"
#include "image_map.h"
#include "interface.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -66,6 +67,8 @@ struct _BrightnessContrastDialog
double contrast;
gint preview;
GimpLut *lut;
};
/* brightness contrast action functions */
@ -91,83 +94,58 @@ static void brightness_contrast_contrast_text_update (GtkWidget *, gpointer
static void *brightness_contrast_options = NULL;
static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
static void brightness_contrast (PixelRegion *, PixelRegion *, void *);
static Argument * brightness_contrast_invoker (Argument *);
/* brightness contrast machinery */
static void
brightness_contrast (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
brightness_contrast_lut_func(BrightnessContrastDialog *bcd,
int nchannels, int channel, float value)
{
BrightnessContrastDialog *bcd;
unsigned char *src, *s;
unsigned char *dest, *d;
unsigned char brightness[256];
unsigned char contrast[256];
float nvalue;
double power;
int has_alpha;
int alpha;
int w, h, b;
gint32 value;
int i;
bcd = (BrightnessContrastDialog *) user_data;
/* Set the transfer arrays (for speed) */
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (bcd->brightness < 0)
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) ((i * (255 + bcd->brightness)) / 255);
value = value * (1.0 + bcd->brightness/255.0);
else
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) (i + ((255 - i) * bcd->brightness) / 255);
value = value + ((1.0 - value) * bcd->brightness/255.0);
/* apply contrast */
if (bcd->contrast < 0)
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
value = (int) (127.0 * pow ((double) (value ? value : 1) / 127.0,
(double) (127 + bcd->contrast) / 127.0));
value = CLAMP0255 (value);
contrast[i] = (i > 127) ? (255 - value) : value;
}
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
nvalue = 0.5 * pow (nvalue * 2.0 , (double) (127 + bcd->contrast) / 127.0);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
else
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
value = (int) (127.0 * pow ((double) value / 127.0, power));
value = CLAMP0255 (value);
contrast[i] = (i > 127) ? (255 - value) : value;
}
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = contrast[brightness[s[b]]];
if (has_alpha)
d[alpha] = s[alpha];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
nvalue = 0.5 * pow (2.0 * nvalue, power);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
return value;
}
@ -334,6 +312,8 @@ brightness_contrast_new_dialog ()
bcd = g_malloc (sizeof (BrightnessContrastDialog));
bcd->preview = TRUE;
bcd->lut = gimp_lut_new();
/* The shell and main vbox */
bcd->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (bcd->shell), "brightness_contrast", "Gimp");
@ -483,7 +463,10 @@ brightness_contrast_preview (BrightnessContrastDialog *bcd)
if (!bcd->image_map)
g_message (_("brightness_contrast_preview(): No image map"));
active_tool->preserve = TRUE;
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) bcd, gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut);
active_tool->preserve = FALSE;
}
@ -501,7 +484,12 @@ brightness_contrast_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!bcd->preview)
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
{
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) bcd, gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut);
}
if (bcd->image_map)
image_map_commit (bcd->image_map);
@ -736,6 +724,7 @@ brightness_contrast_invoker (Argument *args)
{
bcd.brightness = brightness;
bcd.contrast = contrast;
bcd.lut = gimp_lut_new();
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -743,9 +732,13 @@ brightness_contrast_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
brightness_contrast (&srcPR, &destPR, (void *) &bcd);
gimp_lut_setup(bcd.lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) &bcd, gimp_drawable_bytes(drawable));
pixel_regions_process_parallel((p_func)gimp_lut_process, bcd.lut,
2, &srcPR, &destPR);
gimp_lut_free(bcd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -340,9 +340,7 @@ by_color_select_button_release (Tool *tool,
GDisplay * gdisp;
int x, y;
GimpDrawable *drawable;
Tile *tile;
unsigned char col[MAX_CHANNELS];
unsigned char *data;
unsigned char *color;
int use_offsets;
gdisp = (GDisplay *) gdisp_ptr;
@ -360,25 +358,17 @@ by_color_select_button_release (Tool *tool,
/* Get the start color */
if (by_color_options->sample_merged)
{
if (x < 0 || y < 0 || x >= gdisp->gimage->width || y >= gdisp->gimage->height)
if (!(color = gimp_image_get_color_at(gdisp->gimage, x, y)))
return;
tile = tile_manager_get_tile (gimage_composite (gdisp->gimage), x, y, TRUE, FALSE);
data = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimage_get_color (gdisp->gimage, gimage_composite_type(gdisp->gimage), col, data);
tile_release (tile, FALSE);
}
else
{
if (x < 0 || y < 0 || x >= drawable_width (drawable) || y >= drawable_height (drawable))
if (!(color = gimp_drawable_get_color_at(drawable, x, y)))
return;
tile = tile_manager_get_tile (drawable_data (drawable), x, y, TRUE, FALSE);
data = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimage_get_color (gdisp->gimage, drawable_type(drawable), col, data);
tile_release (tile, FALSE);
}
/* select the area */
by_color_select (gdisp->gimage, drawable, col,
by_color_select (gdisp->gimage, drawable, color,
by_color_dialog->threshold,
by_color_sel->operation,
by_color_options->antialias,
@ -386,6 +376,8 @@ by_color_select_button_release (Tool *tool,
by_color_options->feather_radius,
by_color_options->sample_merged);
g_free(color);
/* show selection on all views */
gdisplays_flush ();

View File

@ -628,27 +628,36 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
data = maskPR.data;
ex = maskPR.x + maskPR.w;
ey = maskPR.y + maskPR.h;
for (y = maskPR.y; y < ey; y++)
{
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++)
if (*data)
{
if (x < *x1)
*x1 = x;
if (x > *x2)
*x2 = x;
found = TRUE;
}
if (found)
/* only check the pixels if this tile is not fully within the currently
computed bounds */
if (maskPR.x < *x1 || ex > *x2 ||
maskPR.y < *y1 || ey > *y2)
{
for (y = maskPR.y; y < ey; y++)
{
if (y < *y1)
*y1 = y;
if (y > *y2)
*y2 = y;
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++)
if (*data)
{
if (x < *x1)
*x1 = x;
else if (x > *x2)
*x2 = x;
found = TRUE;
}
if (found)
{
if (y < *y1)
*y1 = y;
else if (y > *y2)
*y2 = y;
}
}
}
if (x1 > x2)
x2 = x1;
if (y1 > y2)
y2 = y1;
}
*x2 = BOUNDS (*x2 + 1, 0, GIMP_DRAWABLE(mask)->width);

View File

@ -28,8 +28,6 @@
#include "libgimp/gimpintl.h"
#include "tile.h" /* ick. */
/* maximum information buffer size */
#define MAX_INFO_BUF 8
@ -289,15 +287,14 @@ get_color (GImage *gimage,
int sample_merged,
int final)
{
unsigned char *color;
unsigned char *src, *cmap, alpha;
TileManager *tiles;
Tile *tile;
int offx, offy;
int width, height;
int bytes;
int index;
int has_alpha;
int is_indexed;
if (!drawable && !sample_merged)
return FALSE;
@ -306,73 +303,33 @@ get_color (GImage *gimage,
drawable_offsets (drawable, &offx, &offy);
x -= offx;
y -= offy;
width = drawable_width (drawable);
height = drawable_height (drawable);
tiles = drawable_data (drawable);
bytes = drawable_bytes (drawable);
has_alpha = drawable_has_alpha (drawable);
sample_type = drawable_type (drawable);
cmap = drawable_cmap (drawable);
if (!(color = gimp_drawable_get_color_at(drawable, x, y)))
return FALSE;
sample_type = gimp_drawable_type(drawable);
is_indexed = gimp_drawable_indexed (drawable);
}
else
{
width = gimage->width;
height = gimage->height;
tiles = gimage_composite (gimage);
bytes = gimage_composite_bytes (gimage);
sample_type = gimage_composite_type (gimage);
has_alpha = (sample_type == RGBA_GIMAGE ||
sample_type == GRAYA_GIMAGE ||
sample_type == INDEXEDA_GIMAGE);
cmap = gimage_cmap (gimage);
if (!(color = gimp_image_get_color_at(gimage, x, y)))
return FALSE;
sample_type = gimp_image_composite_type(gimage);
is_indexed = FALSE;
}
if (x >= 0 && y >= 0 && x < width && y < height)
{
tile = tile_manager_get_tile (tiles, x, y, TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
}
else
return FALSE;
has_alpha = TYPE_HAS_ALPHA(sample_type);
/* if the alpha channel (if one exists) is 0, out of bounds */
col_value[RED_PIX] = color[RED_PIX];
col_value[GREEN_PIX] = color[GREEN_PIX];
col_value[BLUE_PIX] = color[BLUE_PIX];
if (has_alpha)
{
alpha = src[bytes - 1];
col_value [ALPHA_PIX] = alpha;
col_value [ALPHA_PIX] = color[3];
}
/* If the image is color, get RGB */
switch (sample_type)
{
case RGB_GIMAGE: case RGBA_GIMAGE:
col_value [RED_PIX] = src [RED_PIX];
col_value [GREEN_PIX] = src [GREEN_PIX];
col_value [BLUE_PIX] = src [BLUE_PIX];
break;
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
col_value [4] = src [0];
index = src [0] * 3;
col_value [RED_PIX] = cmap [index + 0];
col_value [GREEN_PIX] = cmap [index + 1];
col_value [BLUE_PIX] = cmap [index + 2];
break;
case GRAY_GIMAGE: case GRAYA_GIMAGE:
col_value [RED_PIX] = src [GRAY_PIX];
col_value [GREEN_PIX] = src [GRAY_PIX];
col_value [BLUE_PIX] = src [GRAY_PIX];
break;
default :
break;
}
tile_release (tile, FALSE);
if (is_indexed)
col_value [4] = color[4];
palette_set_active_color (col_value [RED_PIX], col_value [GREEN_PIX],
col_value [BLUE_PIX], final);
g_free(color);
return TRUE;
}

View File

@ -1133,7 +1133,9 @@ image_scale_callback (GtkWidget *w,
image_scale = (ImageResize *) client_data;
if ((gimage = image_scale->gimage) != NULL)
if ((gimage = image_scale->gimage) != NULL &&
(image_scale->resize->width != gimage->width ||
image_scale->resize->height != gimage->height))
{
if (image_scale->resize->width > 0 &&
image_scale->resize->height > 0)

View File

@ -628,27 +628,36 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
data = maskPR.data;
ex = maskPR.x + maskPR.w;
ey = maskPR.y + maskPR.h;
for (y = maskPR.y; y < ey; y++)
{
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++)
if (*data)
{
if (x < *x1)
*x1 = x;
if (x > *x2)
*x2 = x;
found = TRUE;
}
if (found)
/* only check the pixels if this tile is not fully within the currently
computed bounds */
if (maskPR.x < *x1 || ex > *x2 ||
maskPR.y < *y1 || ey > *y2)
{
for (y = maskPR.y; y < ey; y++)
{
if (y < *y1)
*y1 = y;
if (y > *y2)
*y2 = y;
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++)
if (*data)
{
if (x < *x1)
*x1 = x;
else if (x > *x2)
*x2 = x;
found = TRUE;
}
if (found)
{
if (y < *y1)
*y1 = y;
else if (y > *y2)
*y2 = y;
}
}
}
if (x1 > x2)
x2 = x1;
if (y1 > y2)
y2 = y1;
}
*x2 = BOUNDS (*x2 + 1, 0, GIMP_DRAWABLE(mask)->width);

View File

@ -628,27 +628,36 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
data = maskPR.data;
ex = maskPR.x + maskPR.w;
ey = maskPR.y + maskPR.h;
for (y = maskPR.y; y < ey; y++)
{
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++)
if (*data)
{
if (x < *x1)
*x1 = x;
if (x > *x2)
*x2 = x;
found = TRUE;
}
if (found)
/* only check the pixels if this tile is not fully within the currently
computed bounds */
if (maskPR.x < *x1 || ex > *x2 ||
maskPR.y < *y1 || ey > *y2)
{
for (y = maskPR.y; y < ey; y++)
{
if (y < *y1)
*y1 = y;
if (y > *y2)
*y2 = y;
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++)
if (*data)
{
if (x < *x1)
*x1 = x;
else if (x > *x2)
*x2 = x;
found = TRUE;
}
if (found)
{
if (y < *y1)
*y1 = y;
else if (y > *y2)
*y2 = y;
}
}
}
if (x1 > x2)
x2 = x1;
if (y1 > y2)
y2 = y1;
}
*x2 = BOUNDS (*x2 + 1, 0, GIMP_DRAWABLE(mask)->width);

View File

@ -23,6 +23,7 @@
#include "interface.h"
#include "invert.h"
#include "gimage.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -57,54 +58,41 @@ image_invert (GImage *gimage)
}
static float
invert_lut_func(void *unused,
int nchannels, int channel, float value)
{
/* don't invert the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
return 1.0 - value;
}
/* Inverter */
static void
invert (GimpDrawable *drawable)
{
PixelRegion srcPR, destPR;
unsigned char *src, *s;
unsigned char *dest, *d;
int h, j, b;
int has_alpha;
int alpha, bytes;
void *pr;
int x1, y1, x2, y2;
GimpLut *lut;
lut = gimp_lut_new();
gimp_lut_setup_exact(lut, (GimpLutFunc) invert_lut_func,
(void *) NULL, gimp_drawable_bytes(drawable));
bytes = drawable_bytes (drawable);
has_alpha = drawable_has_alpha (drawable);
alpha = has_alpha ? (bytes - 1) : bytes;
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
{
src = srcPR.data;
dest = destPR.data;
h = srcPR.h;
pixel_regions_process_parallel((p_func)gimp_lut_process, lut,
2, &srcPR, &destPR);
while (h--)
{
s = src;
d = dest;
for (j = 0; j < srcPR.w; j++)
{
for (b = 0; b < alpha; b++)
d[b] = 255 - s[b];
if (has_alpha)
d[alpha] = s[alpha];
d += bytes;
s += bytes;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
}
gimp_lut_free(lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

View File

@ -383,6 +383,39 @@ gimp_drawable_set_name (GimpDrawable *drawable, char *name)
drawable->name = g_strdup(name);
}
unsigned char *
gimp_drawable_get_color_at (GimpDrawable *drawable, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (!drawable ||
(!gimp_drawable_gimage(drawable) && gimp_drawable_indexed(drawable))
|| x < 0 || y < 0 ||
x >= drawable->width || y >= drawable->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_drawable_data (drawable), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimp_drawable_gimage(drawable),
gimp_drawable_type (drawable), dest, src);
if(TYPE_HAS_ALPHA(gimp_drawable_type (drawable)))
dest[3] = src[gimp_drawable_bytes (drawable) - 1];
else
dest[3] = 255;
if (gimp_drawable_indexed(drawable))
dest[4] = src[0];
else
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
Parasite *
gimp_drawable_find_parasite (const GimpDrawable *drawable, const char *name)
@ -411,9 +444,13 @@ gimp_drawable_parasite_list (GimpDrawable *drawable, gint *count)
void
gimp_drawable_attach_parasite (GimpDrawable *drawable, Parasite *parasite)
{
parasite_list_add(drawable->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite) &&
!parasite_compare(parasite, gimp_drawable_find_parasite(drawable,
parasite_name(parasite))))
gimp_image_dirty(drawable->gimage);
parasite_list_add(drawable->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -73,6 +73,10 @@ unsigned char * gimp_drawable_cmap (GimpDrawable *);
char * gimp_drawable_get_name (GimpDrawable *);
void gimp_drawable_set_name (GimpDrawable *, char *);
unsigned char * gimp_drawable_get_color_at (GimpDrawable *,
int x, int y);
Parasite * gimp_drawable_find_parasite (const GimpDrawable *,
const char *name);
void gimp_drawable_attach_parasite (GimpDrawable *, Parasite *);

View File

@ -773,6 +773,31 @@ gimp_image_get_background (GimpImage *gimage, GimpDrawable *drawable, unsigned c
gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}
unsigned char *
gimp_image_get_color_at (GimpImage *gimage, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
if(TYPE_HAS_ALPHA(gimp_image_composite_type (gimage)))
dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
else
dest[3] = 255;
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
void
gimp_image_get_color (GimpImage *gimage, int d_type,
unsigned char *rgb, unsigned char *src)
@ -945,9 +970,13 @@ gimp_image_parasite_list (GimpImage *image, gint *count)
void
gimp_image_attach_parasite (GimpImage *gimage, Parasite *parasite)
{
parasite_list_add(gimage->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite)
&& !parasite_compare(parasite, gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty(gimage);
parasite_list_add(gimage->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -127,6 +127,8 @@ void gimp_image_get_foreground (GimpImage *, GimpDrawable *,
unsigned char *);
void gimp_image_get_background (GimpImage *, GimpDrawable *,
unsigned char *);
unsigned char * gimp_image_get_color_at (GimpImage *, int x, int y);
void gimp_image_get_color (GimpImage *, int,
unsigned char *,
unsigned char *);

View File

@ -773,6 +773,31 @@ gimp_image_get_background (GimpImage *gimage, GimpDrawable *drawable, unsigned c
gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}
unsigned char *
gimp_image_get_color_at (GimpImage *gimage, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
if(TYPE_HAS_ALPHA(gimp_image_composite_type (gimage)))
dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
else
dest[3] = 255;
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
void
gimp_image_get_color (GimpImage *gimage, int d_type,
unsigned char *rgb, unsigned char *src)
@ -945,9 +970,13 @@ gimp_image_parasite_list (GimpImage *image, gint *count)
void
gimp_image_attach_parasite (GimpImage *gimage, Parasite *parasite)
{
parasite_list_add(gimage->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite)
&& !parasite_compare(parasite, gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty(gimage);
parasite_list_add(gimage->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -127,6 +127,8 @@ void gimp_image_get_foreground (GimpImage *, GimpDrawable *,
unsigned char *);
void gimp_image_get_background (GimpImage *, GimpDrawable *,
unsigned char *);
unsigned char * gimp_image_get_color_at (GimpImage *, int x, int y);
void gimp_image_get_color (GimpImage *, int,
unsigned char *,
unsigned char *);

View File

@ -773,6 +773,31 @@ gimp_image_get_background (GimpImage *gimage, GimpDrawable *drawable, unsigned c
gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}
unsigned char *
gimp_image_get_color_at (GimpImage *gimage, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
if(TYPE_HAS_ALPHA(gimp_image_composite_type (gimage)))
dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
else
dest[3] = 255;
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
void
gimp_image_get_color (GimpImage *gimage, int d_type,
unsigned char *rgb, unsigned char *src)
@ -945,9 +970,13 @@ gimp_image_parasite_list (GimpImage *image, gint *count)
void
gimp_image_attach_parasite (GimpImage *gimage, Parasite *parasite)
{
parasite_list_add(gimage->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite)
&& !parasite_compare(parasite, gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty(gimage);
parasite_list_add(gimage->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -127,6 +127,8 @@ void gimp_image_get_foreground (GimpImage *, GimpDrawable *,
unsigned char *);
void gimp_image_get_background (GimpImage *, GimpDrawable *,
unsigned char *);
unsigned char * gimp_image_get_color_at (GimpImage *, int x, int y);
void gimp_image_get_color (GimpImage *, int,
unsigned char *,
unsigned char *);

View File

@ -773,6 +773,31 @@ gimp_image_get_background (GimpImage *gimage, GimpDrawable *drawable, unsigned c
gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}
unsigned char *
gimp_image_get_color_at (GimpImage *gimage, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
if(TYPE_HAS_ALPHA(gimp_image_composite_type (gimage)))
dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
else
dest[3] = 255;
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
void
gimp_image_get_color (GimpImage *gimage, int d_type,
unsigned char *rgb, unsigned char *src)
@ -945,9 +970,13 @@ gimp_image_parasite_list (GimpImage *image, gint *count)
void
gimp_image_attach_parasite (GimpImage *gimage, Parasite *parasite)
{
parasite_list_add(gimage->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite)
&& !parasite_compare(parasite, gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty(gimage);
parasite_list_add(gimage->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -127,6 +127,8 @@ void gimp_image_get_foreground (GimpImage *, GimpDrawable *,
unsigned char *);
void gimp_image_get_background (GimpImage *, GimpDrawable *,
unsigned char *);
unsigned char * gimp_image_get_color_at (GimpImage *, int x, int y);
void gimp_image_get_color (GimpImage *, int,
unsigned char *,
unsigned char *);

View File

@ -773,6 +773,31 @@ gimp_image_get_background (GimpImage *gimage, GimpDrawable *drawable, unsigned c
gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}
unsigned char *
gimp_image_get_color_at (GimpImage *gimage, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
if(TYPE_HAS_ALPHA(gimp_image_composite_type (gimage)))
dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
else
dest[3] = 255;
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
void
gimp_image_get_color (GimpImage *gimage, int d_type,
unsigned char *rgb, unsigned char *src)
@ -945,9 +970,13 @@ gimp_image_parasite_list (GimpImage *image, gint *count)
void
gimp_image_attach_parasite (GimpImage *gimage, Parasite *parasite)
{
parasite_list_add(gimage->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite)
&& !parasite_compare(parasite, gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty(gimage);
parasite_list_add(gimage->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -127,6 +127,8 @@ void gimp_image_get_foreground (GimpImage *, GimpDrawable *,
unsigned char *);
void gimp_image_get_background (GimpImage *, GimpDrawable *,
unsigned char *);
unsigned char * gimp_image_get_color_at (GimpImage *, int x, int y);
void gimp_image_get_color (GimpImage *, int,
unsigned char *,
unsigned char *);

View File

@ -773,6 +773,31 @@ gimp_image_get_background (GimpImage *gimage, GimpDrawable *drawable, unsigned c
gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}
unsigned char *
gimp_image_get_color_at (GimpImage *gimage, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
if(TYPE_HAS_ALPHA(gimp_image_composite_type (gimage)))
dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
else
dest[3] = 255;
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
void
gimp_image_get_color (GimpImage *gimage, int d_type,
unsigned char *rgb, unsigned char *src)
@ -945,9 +970,13 @@ gimp_image_parasite_list (GimpImage *image, gint *count)
void
gimp_image_attach_parasite (GimpImage *gimage, Parasite *parasite)
{
parasite_list_add(gimage->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite)
&& !parasite_compare(parasite, gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty(gimage);
parasite_list_add(gimage->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -127,6 +127,8 @@ void gimp_image_get_foreground (GimpImage *, GimpDrawable *,
unsigned char *);
void gimp_image_get_background (GimpImage *, GimpDrawable *,
unsigned char *);
unsigned char * gimp_image_get_color_at (GimpImage *, int x, int y);
void gimp_image_get_color (GimpImage *, int,
unsigned char *,
unsigned char *);

View File

@ -55,7 +55,7 @@ static void gimp_layer_mask_class_init (GimpLayerMaskClass *klass);
static void gimp_layer_mask_init (GimpLayerMask *layermask);
static void gimp_layer_mask_destroy (GtkObject *object);
static gint layer_signals[LAST_SIGNAL] = { 0 };
static guint layer_signals[LAST_SIGNAL] = { 0 };
/*
static gint layer_mask_signals[LAST_SIGNAL] = { 0 };
*/

View File

@ -773,6 +773,31 @@ gimp_image_get_background (GimpImage *gimage, GimpDrawable *drawable, unsigned c
gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}
unsigned char *
gimp_image_get_color_at (GimpImage *gimage, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
if(TYPE_HAS_ALPHA(gimp_image_composite_type (gimage)))
dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
else
dest[3] = 255;
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
void
gimp_image_get_color (GimpImage *gimage, int d_type,
unsigned char *rgb, unsigned char *src)
@ -945,9 +970,13 @@ gimp_image_parasite_list (GimpImage *image, gint *count)
void
gimp_image_attach_parasite (GimpImage *gimage, Parasite *parasite)
{
parasite_list_add(gimage->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite)
&& !parasite_compare(parasite, gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty(gimage);
parasite_list_add(gimage->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -127,6 +127,8 @@ void gimp_image_get_foreground (GimpImage *, GimpDrawable *,
unsigned char *);
void gimp_image_get_background (GimpImage *, GimpDrawable *,
unsigned char *);
unsigned char * gimp_image_get_color_at (GimpImage *, int x, int y);
void gimp_image_get_color (GimpImage *, int,
unsigned char *,
unsigned char *);

View File

@ -30,6 +30,7 @@
#include "image_map.h"
#include "interface.h"
#include "curves.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -96,6 +97,8 @@ struct _CurvesDialog
int curve_type;
int points[5][17][2];
unsigned char curve[5][256];
GimpLut *lut;
};
typedef double CRMatrix[4][4];
@ -141,65 +144,49 @@ static CRMatrix CR_basis =
};
static void curves (PixelRegion *, PixelRegion *, void *);
static Argument * curves_spline_invoker (Argument *);
static Argument * curves_explicit_invoker (Argument *);
/* curves machinery */
static void
curves (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
curves_lut_func(CurvesDialog *cd,
int nchannels, int channel, float value)
{
CurvesDialog *cd;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h;
float f;
int index;
double inten;
int j;
cd = (CurvesDialog *) user_data;
if (nchannels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
the first time and j = 0 the second time */
/* For bw images this runs through the loop with j = 0 the first and
only time */
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (nchannels == 2 || nchannels == 4)
&& channel == nchannels -1)
return inten;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
while (h--)
if (inten < 0.0)
inten = cd->curve[j][0]/255.0;
else if (inten >= 1.0)
inten = cd->curve[j][255]/255.0;
else /* interpolate the curve */
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (cd->color)
{
/* The contributions from the individual channel level settings */
d[RED_PIX] = cd->curve[HISTOGRAM_RED][s[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_GREEN][s[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_BLUE][s[BLUE_PIX]];
/* The overall changes */
d[RED_PIX] = cd->curve[HISTOGRAM_VALUE][d[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_VALUE][d[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_VALUE][d[BLUE_PIX]];
}
else
d[GRAY_PIX] = cd->curve[HISTOGRAM_VALUE][s[GRAY_PIX]];
if (has_alpha) {
d[alpha] = cd->curve[HISTOGRAM_ALPHA][s[alpha]];
/* d[alpha] = s[alpha]; */
}
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
index = floor(inten * 255.0);
f = inten*255.0 - index;
inten = ((1.0 - f) * cd->curve[j][index ] +
( f) * cd->curve[j][index + 1] ) / 255.0;
}
}
return inten;
}
/* curves action functions */
@ -446,6 +433,7 @@ curves_new_dialog ()
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd->curve[i][j] = j;
cd->lut = gimp_lut_new();
for (i = 0; i < 5; i++)
channel_items [i].user_data = (gpointer) cd;
@ -810,6 +798,9 @@ curves_calculate_curve (CurvesDialog *cd)
}
break;
}
gimp_lut_setup(cd->lut, (GimpLutFunc) curves_lut_func,
(void *) cd, gimp_drawable_bytes(cd->drawable));
}
static void
@ -820,7 +811,8 @@ curves_preview (CurvesDialog *cd)
active_tool->preserve = TRUE; /* Going to dirty the display... */
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
active_tool->preserve = FALSE; /* All done */
}
@ -988,7 +980,8 @@ curves_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE; /* We're about to dirty... */
if (!cd->preview)
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
if (cd->image_map)
image_map_commit (cd->image_map);
@ -1361,6 +1354,7 @@ curves_spline_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
@ -1407,6 +1401,7 @@ curves_spline_invoker (Argument *args)
/* arrange to modify the curves */
if (success)
{
cd.lut = gimp_lut_new();
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd.curve[i][j] = j;
@ -1435,9 +1430,10 @@ curves_spline_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
gimp_lut_free(cd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
@ -1509,6 +1505,7 @@ curves_explicit_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
@ -1564,15 +1561,18 @@ curves_explicit_invoker (Argument *args)
for (j = 0; j < 256; j++)
cd.curve[cd.channel][j] = curve[j];
cd.lut = gimp_lut_new();
gimp_lut_setup(cd.lut, (GimpLutFunc) curves_lut_func,
(void *) &cd, gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

View File

@ -628,27 +628,36 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
data = maskPR.data;
ex = maskPR.x + maskPR.w;
ey = maskPR.y + maskPR.h;
for (y = maskPR.y; y < ey; y++)
{
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++)
if (*data)
{
if (x < *x1)
*x1 = x;
if (x > *x2)
*x2 = x;
found = TRUE;
}
if (found)
/* only check the pixels if this tile is not fully within the currently
computed bounds */
if (maskPR.x < *x1 || ex > *x2 ||
maskPR.y < *y1 || ey > *y2)
{
for (y = maskPR.y; y < ey; y++)
{
if (y < *y1)
*y1 = y;
if (y > *y2)
*y2 = y;
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++)
if (*data)
{
if (x < *x1)
*x1 = x;
else if (x > *x2)
*x2 = x;
found = TRUE;
}
if (found)
{
if (y < *y1)
*y1 = y;
else if (y > *y2)
*y2 = y;
}
}
}
if (x1 > x2)
x2 = x1;
if (y1 > y2)
y2 = y1;
}
*x2 = BOUNDS (*x2 + 1, 0, GIMP_DRAWABLE(mask)->width);

View File

@ -23,6 +23,7 @@
#include "interface.h"
#include "invert.h"
#include "gimage.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -57,54 +58,41 @@ image_invert (GImage *gimage)
}
static float
invert_lut_func(void *unused,
int nchannels, int channel, float value)
{
/* don't invert the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
return 1.0 - value;
}
/* Inverter */
static void
invert (GimpDrawable *drawable)
{
PixelRegion srcPR, destPR;
unsigned char *src, *s;
unsigned char *dest, *d;
int h, j, b;
int has_alpha;
int alpha, bytes;
void *pr;
int x1, y1, x2, y2;
GimpLut *lut;
lut = gimp_lut_new();
gimp_lut_setup_exact(lut, (GimpLutFunc) invert_lut_func,
(void *) NULL, gimp_drawable_bytes(drawable));
bytes = drawable_bytes (drawable);
has_alpha = drawable_has_alpha (drawable);
alpha = has_alpha ? (bytes - 1) : bytes;
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
{
src = srcPR.data;
dest = destPR.data;
h = srcPR.h;
pixel_regions_process_parallel((p_func)gimp_lut_process, lut,
2, &srcPR, &destPR);
while (h--)
{
s = src;
d = dest;
for (j = 0; j < srcPR.w; j++)
{
for (b = 0; b < alpha; b++)
d[b] = 255 - s[b];
if (has_alpha)
d[alpha] = s[alpha];
d += bytes;
s += bytes;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
}
gimp_lut_free(lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

View File

@ -383,6 +383,39 @@ gimp_drawable_set_name (GimpDrawable *drawable, char *name)
drawable->name = g_strdup(name);
}
unsigned char *
gimp_drawable_get_color_at (GimpDrawable *drawable, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (!drawable ||
(!gimp_drawable_gimage(drawable) && gimp_drawable_indexed(drawable))
|| x < 0 || y < 0 ||
x >= drawable->width || y >= drawable->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_drawable_data (drawable), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimp_drawable_gimage(drawable),
gimp_drawable_type (drawable), dest, src);
if(TYPE_HAS_ALPHA(gimp_drawable_type (drawable)))
dest[3] = src[gimp_drawable_bytes (drawable) - 1];
else
dest[3] = 255;
if (gimp_drawable_indexed(drawable))
dest[4] = src[0];
else
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
Parasite *
gimp_drawable_find_parasite (const GimpDrawable *drawable, const char *name)
@ -411,9 +444,13 @@ gimp_drawable_parasite_list (GimpDrawable *drawable, gint *count)
void
gimp_drawable_attach_parasite (GimpDrawable *drawable, Parasite *parasite)
{
parasite_list_add(drawable->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite) &&
!parasite_compare(parasite, gimp_drawable_find_parasite(drawable,
parasite_name(parasite))))
gimp_image_dirty(drawable->gimage);
parasite_list_add(drawable->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -73,6 +73,10 @@ unsigned char * gimp_drawable_cmap (GimpDrawable *);
char * gimp_drawable_get_name (GimpDrawable *);
void gimp_drawable_set_name (GimpDrawable *, char *);
unsigned char * gimp_drawable_get_color_at (GimpDrawable *,
int x, int y);
Parasite * gimp_drawable_find_parasite (const GimpDrawable *,
const char *name);
void gimp_drawable_attach_parasite (GimpDrawable *, Parasite *);

View File

@ -773,6 +773,31 @@ gimp_image_get_background (GimpImage *gimage, GimpDrawable *drawable, unsigned c
gimp_image_transform_color (gimage, drawable, pbg, bg, RGB);
}
unsigned char *
gimp_image_get_color_at (GimpImage *gimage, int x, int y)
{
Tile *tile;
unsigned char *src;
unsigned char *dest;
if (x < 0 || y < 0 || x >= gimage->width || y >= gimage->height)
{
return NULL;
}
dest = g_new(unsigned char, 5);
tile = tile_manager_get_tile (gimp_image_composite (gimage), x, y,
TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimp_image_get_color (gimage, gimp_image_composite_type (gimage), dest, src);
if(TYPE_HAS_ALPHA(gimp_image_composite_type (gimage)))
dest[3] = src[gimp_image_composite_bytes (gimage) - 1];
else
dest[3] = 255;
dest[4] = 0;
tile_release (tile, FALSE);
return dest;
}
void
gimp_image_get_color (GimpImage *gimage, int d_type,
unsigned char *rgb, unsigned char *src)
@ -945,9 +970,13 @@ gimp_image_parasite_list (GimpImage *image, gint *count)
void
gimp_image_attach_parasite (GimpImage *gimage, Parasite *parasite)
{
parasite_list_add(gimage->parasites, parasite);
if (parasite_is_persistent(parasite)) /* make sure we can be saved */
/* only set the dirty bit if we can be saved and the new parasite differs
from the current one */
if (parasite_is_persistent(parasite)
&& !parasite_compare(parasite, gimp_image_find_parasite(gimage,
parasite_name(parasite))))
gimp_image_dirty(gimage);
parasite_list_add(gimage->parasites, parasite);
if (parasite_has_flag(parasite, PARASITE_ATTACH_PARENT))
{
parasite_shift_parent(parasite);

View File

@ -127,6 +127,8 @@ void gimp_image_get_foreground (GimpImage *, GimpDrawable *,
unsigned char *);
void gimp_image_get_background (GimpImage *, GimpDrawable *,
unsigned char *);
unsigned char * gimp_image_get_color_at (GimpImage *, int x, int y);
void gimp_image_get_color (GimpImage *, int,
unsigned char *,
unsigned char *);

View File

@ -55,7 +55,7 @@ static void gimp_layer_mask_class_init (GimpLayerMaskClass *klass);
static void gimp_layer_mask_init (GimpLayerMask *layermask);
static void gimp_layer_mask_destroy (GtkObject *object);
static gint layer_signals[LAST_SIGNAL] = { 0 };
static guint layer_signals[LAST_SIGNAL] = { 0 };
/*
static gint layer_mask_signals[LAST_SIGNAL] = { 0 };
*/

169
app/gimplut.c Normal file
View File

@ -0,0 +1,169 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplut.c: Copyright (C) 1999 Jay Cox <jaycox@earthlink.net>
*
* 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 "gimplutP.h"
#include "gimplut.h"
#include <stdio.h>
GimpLut *
gimp_lut_new()
{
GimpLut *lut;
lut = g_new(GimpLut, 1);
lut->luts = NULL;
lut->nchannels = 0;
return lut;
}
void
gimp_lut_free(GimpLut *lut)
{
int i;
for (i = 0; i < lut->nchannels; i++)
g_free(lut->luts[i]);
if (lut->luts)
g_free(lut->luts);
}
void
gimp_lut_setup (GimpLut *lut, GimpLutFunc func,
void *user_data, int nchannels)
{
int i, v;
double val;
if (lut->luts)
{
for (i = 0; i < lut->nchannels; i++)
g_free(lut->luts[i]);
g_free(lut->luts);
}
lut->nchannels = nchannels;
lut->luts = g_new(unsigned char*, lut->nchannels);
for (i = 0; i < lut->nchannels; i++)
{
lut->luts[i] = g_new(unsigned char, 256);
for (v = 0; v < 256; v++)
{ /* to add gamma correction use func(v ^ g) ^ 1/g instead. */
val = 255.0 * func(user_data, lut->nchannels, i, v/255.0) + 0.5;
if (val < 0.0)
lut->luts[i][v] = 0;
else if (val >= 255.0)
lut->luts[i][v] = 255;
else
lut->luts[i][v] = val;
}
}
}
void
gimp_lut_setup_exact (GimpLut *lut, GimpLutFunc func,
void *user_data, int nchannels)
{
gimp_lut_setup(lut, func, user_data, nchannels);
}
void
gimp_lut_process (GimpLut *lut,
PixelRegion *srcPR,
PixelRegion *destPR)
{
int h, width, src_r_i, dest_r_i;
unsigned char *src, *dest;
unsigned char *lut0, *lut1, *lut2, *lut3;
if (lut->nchannels > 0)
lut0 = lut->luts[0];
if (lut->nchannels > 1)
lut1 = lut->luts[1];
if (lut->nchannels > 2)
lut2 = lut->luts[2];
if (lut->nchannels > 3)
lut3 = lut->luts[3];
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
width = srcPR->w;
src_r_i = srcPR->rowstride - (srcPR->bytes * srcPR->w);
dest_r_i = destPR->rowstride - (destPR->bytes * srcPR->w);
if (src_r_i == 0 && dest_r_i == 0)
{
width *= h;
h = 1;
}
while (h--)
{
switch (lut->nchannels)
{
case 1:
while (width--)
{
*dest = lut0[*src];
src++;
dest++;
}
break;
case 2:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
src += 2;
dest += 2;
}
break;
case 3:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
dest[2] = lut2[src[2]];
src += 3;
dest += 3;
}
break;
case 4:
while (width--)
{
dest[0] = lut0[src[0]];
dest[1] = lut1[src[1]];
dest[2] = lut2[src[2]];
dest[3] = lut3[src[3]];
src += 4;
dest += 4;
}
break;
default:
fprintf(stderr, "gimplut: Error: nchannels = %d\n", lut->nchannels);
}
width = srcPR->w;
src += src_r_i;
dest += dest_r_i;
}
}
void
gimp_lut_process_2 (PixelRegion *srcPR,
PixelRegion *destPR,
GimpLut *lut)
{
gimp_lut_process(lut, srcPR, destPR);
}

61
app/gimplut.h Normal file
View File

@ -0,0 +1,61 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimplut.h: Copyright (C) 1999 Jay Cox <jaycox@earthlink.net>
*
* 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.
*/
#ifndef __GIMP_LUT_H__
#define __GIMP_LUT_H__
#include "gimplutF.h"
#include "pixel_region.h"
/* TODO: the GimpLutFunc should really be passed the ColorModel of the region,
not just the number of channels */
/* GimpLutFuncs should assume that the input and output gamma are 1.0
and do no correction as this will be handled by gimp_lut_setup */
typedef float (*GimpLutFunc)(void *user_data, int nchannels,
int channel, float value);
GimpLut * gimp_lut_new ();
void gimp_lut_free (GimpLut *lut);
void gimp_lut_setup (GimpLut *, GimpLutFunc,
void *user_data,
int nchannels);
/* gimp_lut_setup_exact is currently identical to gimp_lut_setup. It
however is guaranteed to never perform any interpolation or gamma
correction on the lut */
void gimp_lut_setup_exact (GimpLut *, GimpLutFunc,
void *user_data,
int nchannels);
void gimp_lut_process (GimpLut *lut,
PixelRegion *srcPR,
PixelRegion *destPR);
/* gimp_lut_process_2 is the same as gimp_lut_process but the lut
perameter is last instead of first. this is necesary because
pixel_region_process_paralell sends the user_data as the 1st
parameter, and the image_map functions send user_data as the last
parameter */
void gimp_lut_process_2 (PixelRegion *srcPR,
PixelRegion *destPR,
GimpLut *lut);
#endif /* __GIMP_LUT_H__ */

View File

@ -1133,7 +1133,9 @@ image_scale_callback (GtkWidget *w,
image_scale = (ImageResize *) client_data;
if ((gimage = image_scale->gimage) != NULL)
if ((gimage = image_scale->gimage) != NULL &&
(image_scale->resize->width != gimage->width ||
image_scale->resize->height != gimage->height))
{
if (image_scale->resize->width > 0 &&
image_scale->resize->height > 0)

View File

@ -1133,7 +1133,9 @@ image_scale_callback (GtkWidget *w,
image_scale = (ImageResize *) client_data;
if ((gimage = image_scale->gimage) != NULL)
if ((gimage = image_scale->gimage) != NULL &&
(image_scale->resize->width != gimage->width ||
image_scale->resize->height != gimage->height))
{
if (image_scale->resize->width > 0 &&
image_scale->resize->height > 0)

View File

@ -23,6 +23,7 @@
#include "interface.h"
#include "invert.h"
#include "gimage.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -57,54 +58,41 @@ image_invert (GImage *gimage)
}
static float
invert_lut_func(void *unused,
int nchannels, int channel, float value)
{
/* don't invert the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
return 1.0 - value;
}
/* Inverter */
static void
invert (GimpDrawable *drawable)
{
PixelRegion srcPR, destPR;
unsigned char *src, *s;
unsigned char *dest, *d;
int h, j, b;
int has_alpha;
int alpha, bytes;
void *pr;
int x1, y1, x2, y2;
GimpLut *lut;
lut = gimp_lut_new();
gimp_lut_setup_exact(lut, (GimpLutFunc) invert_lut_func,
(void *) NULL, gimp_drawable_bytes(drawable));
bytes = drawable_bytes (drawable);
has_alpha = drawable_has_alpha (drawable);
alpha = has_alpha ? (bytes - 1) : bytes;
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
{
src = srcPR.data;
dest = destPR.data;
h = srcPR.h;
pixel_regions_process_parallel((p_func)gimp_lut_process, lut,
2, &srcPR, &destPR);
while (h--)
{
s = src;
d = dest;
for (j = 0; j < srcPR.w; j++)
{
for (b = 0; b < alpha; b++)
d[b] = 255 - s[b];
if (has_alpha)
d[alpha] = s[alpha];
d += bytes;
s += bytes;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
}
gimp_lut_free(lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

View File

@ -55,7 +55,7 @@ static void gimp_layer_mask_class_init (GimpLayerMaskClass *klass);
static void gimp_layer_mask_init (GimpLayerMask *layermask);
static void gimp_layer_mask_destroy (GtkObject *object);
static gint layer_signals[LAST_SIGNAL] = { 0 };
static guint layer_signals[LAST_SIGNAL] = { 0 };
/*
static gint layer_mask_signals[LAST_SIGNAL] = { 0 };
*/

View File

@ -29,6 +29,7 @@
#include "image_map.h"
#include "interface.h"
#include "levels.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -95,9 +96,9 @@ struct _LevelsDialog
int active_slider;
int slider_pos[5]; /* positions for the five sliders */
unsigned char input[5][256];
unsigned char output[5][256];
unsigned char input[5][256]; /* this is used only by the gui */
GimpLut *lut;
};
/* levels action functions */
@ -133,65 +134,61 @@ static gint levels_output_da_events (GtkWidget *, GdkEvent *,
static void *levels_options = NULL;
static LevelsDialog *levels_dialog = NULL;
static void levels (PixelRegion *, PixelRegion *, void *);
static void levels_histogram_info (PixelRegion *, PixelRegion *, HistogramValues, void *);
static void levels_histogram_range (int, int, HistogramValues, void *);
static Argument * levels_invoker (Argument *);
/* levels machinery */
static void
levels (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
levels_lut_func(LevelsDialog *ld,
int nchannels, int channel, float value)
{
LevelsDialog *ld;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h;
double inten;
int j;
double input, output;
ld = (LevelsDialog *) user_data;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
if (nchannels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
the first time and j = 0 the second time */
/* For bw images this runs through the loop with j = 0 the first and
only time */
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (nchannels == 2 || nchannels == 4)
&& channel == nchannels -1)
return inten;
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (ld->color)
{
/* The contributions from the individual channel level settings */
d[RED_PIX] = ld->output[HISTOGRAM_RED][ld->input[HISTOGRAM_RED][s[RED_PIX]]];
d[GREEN_PIX] = ld->output[HISTOGRAM_GREEN][ld->input[HISTOGRAM_GREEN][s[GREEN_PIX]]];
d[BLUE_PIX] = ld->output[HISTOGRAM_BLUE][ld->input[HISTOGRAM_BLUE][s[BLUE_PIX]]];
/* determine input intensity */
if (ld->high_input[j] != ld->low_input[j])
inten = (double) (255.0*inten - ld->low_input[j]) /
(double) (ld->high_input[j] - ld->low_input[j]);
else
inten = (double) (255.0*inten - ld->low_input[j]);
/* The overall changes */
d[RED_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[RED_PIX]]];
d[GREEN_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[GREEN_PIX]]];
d[BLUE_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[BLUE_PIX]]];
}
else
d[GRAY_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][s[GRAY_PIX]]];;
if (ld->gamma[j] != 0.0)
if (inten >= 0.0)
inten = pow ( inten, (1.0 / ld->gamma[j]));
else
inten = -pow (-inten, (1.0 / ld->gamma[j]));
if (has_alpha)
d[alpha] = ld->output[HISTOGRAM_ALPHA][ld->input[HISTOGRAM_ALPHA][s[alpha]]];
/*d[alpha] = s[alpha];*/
/* determine the output intensity */
if (ld->high_output[j] >= ld->low_output[j])
inten = (double) (inten * (ld->high_output[j] - ld->low_output[j]) +
ld->low_output[j]);
else if (ld->high_output[j] < ld->low_output[j])
inten = (double) (ld->low_output[j] - inten *
(ld->low_output[j] - ld->high_output[j]));
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
inten /= 255.0;
}
return inten;
}
static void
@ -523,6 +520,8 @@ levels_new_dialog ()
ld = g_malloc (sizeof (LevelsDialog));
ld->preview = TRUE;
ld->lut = gimp_lut_new();
for (i = 0; i < 5; i++)
color_option_items [i].user_data = (gpointer) ld;
@ -778,18 +777,6 @@ levels_calculate_transfers (LevelsDialog *ld)
if (ld->gamma[j] != 0.0)
inten = pow (inten, (1.0 / ld->gamma[j]));
ld->input[j][i] = (unsigned char) (inten * 255.0 + 0.5);
/* determine the output intensity */
inten = (double) i / 255.0;
if (ld->high_output[j] >= ld->low_output[j])
inten = (double) (inten * (ld->high_output[j] - ld->low_output[j]) +
ld->low_output[j]);
else if (ld->high_output[j] < ld->low_output[j])
inten = (double) (ld->low_output[j] - inten *
(ld->low_output[j] - ld->high_output[j]));
inten = BOUNDS (inten, 0.0, 255.0);
ld->output[j][i] = (unsigned char) (inten + 0.5);
}
}
}
@ -803,6 +790,9 @@ levels_update (LevelsDialog *ld,
/* Recalculate the transfer arrays */
levels_calculate_transfers (ld);
/* set up the lut */
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func,
(void *) ld, gimp_drawable_bytes(ld->drawable));
if (update & LOW_INPUT)
{
@ -906,7 +896,8 @@ levels_preview (LevelsDialog *ld)
if (!ld->image_map)
g_warning (_("No image map"));
active_tool->preserve = TRUE;
image_map_apply (ld->image_map, levels, (void *) ld);
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut);
active_tool->preserve = FALSE;
}
@ -1089,7 +1080,12 @@ levels_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!ld->preview)
image_map_apply (ld->image_map, levels, (void *) ld);
{
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func,
(void *) ld, gimp_drawable_bytes(ld->drawable));
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut);
}
if (ld->image_map)
image_map_commit (ld->image_map);
@ -1615,6 +1611,7 @@ levels_invoker (Argument *args)
ld.high_output[i] = 255;
}
ld.lut = gimp_lut_new();
ld.channel = channel;
ld.color = drawable_color (drawable);
ld.low_input[channel] = low_input;
@ -1623,8 +1620,9 @@ levels_invoker (Argument *args)
ld.low_output[channel] = low_output;
ld.high_output[channel] = high_output;
/* calculate the transfer arrays */
levels_calculate_transfers (&ld);
/* setup the lut */
gimp_lut_setup(ld.lut, (GimpLutFunc) levels_lut_func,
(void *) &ld, gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -1632,9 +1630,10 @@ levels_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
levels (&srcPR, &destPR, (void *) &ld);
pixel_regions_process_parallel((p_func)gimp_lut_process, ld.lut,
2, &srcPR, &destPR);
gimp_lut_free(ld.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -25,6 +25,7 @@
#include "image_map.h"
#include "interface.h"
#include "posterize.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -49,6 +50,8 @@ struct _PosterizeDialog
int levels;
gint preview;
GimpLut *lut;
};
/* posterize action functions */
@ -70,62 +73,29 @@ static gint posterize_delete_callback (GtkWidget *, GdkEvent *
static void *posterize_options = NULL;
static PosterizeDialog *posterize_dialog = NULL;
static void posterize (PixelRegion *, PixelRegion *, void *);
static Argument * posterize_invoker (Argument *);
/* posterize machinery */
static void
posterize (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
posterize_lut_func(PosterizeDialog *pd,
int nchannels, int channel, float value)
{
PosterizeDialog *pd;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h, b, i;
double interval, half_interval;
unsigned char transfer[256];
int levels;
/* don't posterize the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
pd = (PosterizeDialog *) user_data;
if (pd->levels < 2)
levels = 2;
else
levels = pd->levels;
/* Set the transfer array */
interval = 255.0 / (double) (pd->levels - 1);
half_interval = interval / 2.0;
value = rint(value * (pd->levels - 1.0)) / (pd->levels - 1.0);
for (i = 0; i < 256; i++)
transfer[i] = (unsigned char) ((int) (((double) i + half_interval) / interval) * interval);
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = transfer[s[b]];
if (has_alpha)
d[alpha] = s[alpha];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
return value;
}
/* by_color select action functions */
static void
@ -289,6 +259,7 @@ posterize_new_dialog ()
pd = g_malloc (sizeof (PosterizeDialog));
pd->preview = TRUE;
pd->levels = 3;
pd->lut = gimp_lut_new();
/* The shell and main vbox */
pd->shell = gtk_dialog_new ();
@ -356,7 +327,10 @@ posterize_preview (PosterizeDialog *pd)
if (!pd->image_map)
g_message (_("posterize_preview(): No image map"));
active_tool->preserve = TRUE;
image_map_apply (pd->image_map, posterize, (void *) pd);
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func,
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut);
active_tool->preserve = FALSE;
}
@ -374,8 +348,12 @@ posterize_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!pd->preview)
image_map_apply (pd->image_map, posterize, (void *) pd);
{
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func,
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut);
}
if (pd->image_map)
image_map_commit (pd->image_map);
@ -531,16 +509,17 @@ posterize_invoker (Argument *args)
if (success)
{
pd.levels = levels;
pd.lut = gimp_lut_new();
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
posterize (&srcPR, &destPR, (void *) &pd);
pixel_regions_process_parallel((p_func)gimp_lut_process, pd.lut,
2, &srcPR, &destPR);
gimp_lut_free(pd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -27,6 +27,7 @@
#include "gdisplay.h"
#include "image_map.h"
#include "interface.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -66,6 +67,8 @@ struct _BrightnessContrastDialog
double contrast;
gint preview;
GimpLut *lut;
};
/* brightness contrast action functions */
@ -91,83 +94,58 @@ static void brightness_contrast_contrast_text_update (GtkWidget *, gpointer
static void *brightness_contrast_options = NULL;
static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
static void brightness_contrast (PixelRegion *, PixelRegion *, void *);
static Argument * brightness_contrast_invoker (Argument *);
/* brightness contrast machinery */
static void
brightness_contrast (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
brightness_contrast_lut_func(BrightnessContrastDialog *bcd,
int nchannels, int channel, float value)
{
BrightnessContrastDialog *bcd;
unsigned char *src, *s;
unsigned char *dest, *d;
unsigned char brightness[256];
unsigned char contrast[256];
float nvalue;
double power;
int has_alpha;
int alpha;
int w, h, b;
gint32 value;
int i;
bcd = (BrightnessContrastDialog *) user_data;
/* Set the transfer arrays (for speed) */
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (bcd->brightness < 0)
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) ((i * (255 + bcd->brightness)) / 255);
value = value * (1.0 + bcd->brightness/255.0);
else
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) (i + ((255 - i) * bcd->brightness) / 255);
value = value + ((1.0 - value) * bcd->brightness/255.0);
/* apply contrast */
if (bcd->contrast < 0)
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
value = (int) (127.0 * pow ((double) (value ? value : 1) / 127.0,
(double) (127 + bcd->contrast) / 127.0));
value = CLAMP0255 (value);
contrast[i] = (i > 127) ? (255 - value) : value;
}
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
nvalue = 0.5 * pow (nvalue * 2.0 , (double) (127 + bcd->contrast) / 127.0);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
else
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
value = (int) (127.0 * pow ((double) value / 127.0, power));
value = CLAMP0255 (value);
contrast[i] = (i > 127) ? (255 - value) : value;
}
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = contrast[brightness[s[b]]];
if (has_alpha)
d[alpha] = s[alpha];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
nvalue = 0.5 * pow (2.0 * nvalue, power);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
return value;
}
@ -334,6 +312,8 @@ brightness_contrast_new_dialog ()
bcd = g_malloc (sizeof (BrightnessContrastDialog));
bcd->preview = TRUE;
bcd->lut = gimp_lut_new();
/* The shell and main vbox */
bcd->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (bcd->shell), "brightness_contrast", "Gimp");
@ -483,7 +463,10 @@ brightness_contrast_preview (BrightnessContrastDialog *bcd)
if (!bcd->image_map)
g_message (_("brightness_contrast_preview(): No image map"));
active_tool->preserve = TRUE;
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) bcd, gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut);
active_tool->preserve = FALSE;
}
@ -501,7 +484,12 @@ brightness_contrast_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!bcd->preview)
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
{
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) bcd, gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut);
}
if (bcd->image_map)
image_map_commit (bcd->image_map);
@ -736,6 +724,7 @@ brightness_contrast_invoker (Argument *args)
{
bcd.brightness = brightness;
bcd.contrast = contrast;
bcd.lut = gimp_lut_new();
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -743,9 +732,13 @@ brightness_contrast_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
brightness_contrast (&srcPR, &destPR, (void *) &bcd);
gimp_lut_setup(bcd.lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) &bcd, gimp_drawable_bytes(drawable));
pixel_regions_process_parallel((p_func)gimp_lut_process, bcd.lut,
2, &srcPR, &destPR);
gimp_lut_free(bcd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -340,9 +340,7 @@ by_color_select_button_release (Tool *tool,
GDisplay * gdisp;
int x, y;
GimpDrawable *drawable;
Tile *tile;
unsigned char col[MAX_CHANNELS];
unsigned char *data;
unsigned char *color;
int use_offsets;
gdisp = (GDisplay *) gdisp_ptr;
@ -360,25 +358,17 @@ by_color_select_button_release (Tool *tool,
/* Get the start color */
if (by_color_options->sample_merged)
{
if (x < 0 || y < 0 || x >= gdisp->gimage->width || y >= gdisp->gimage->height)
if (!(color = gimp_image_get_color_at(gdisp->gimage, x, y)))
return;
tile = tile_manager_get_tile (gimage_composite (gdisp->gimage), x, y, TRUE, FALSE);
data = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimage_get_color (gdisp->gimage, gimage_composite_type(gdisp->gimage), col, data);
tile_release (tile, FALSE);
}
else
{
if (x < 0 || y < 0 || x >= drawable_width (drawable) || y >= drawable_height (drawable))
if (!(color = gimp_drawable_get_color_at(drawable, x, y)))
return;
tile = tile_manager_get_tile (drawable_data (drawable), x, y, TRUE, FALSE);
data = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimage_get_color (gdisp->gimage, drawable_type(drawable), col, data);
tile_release (tile, FALSE);
}
/* select the area */
by_color_select (gdisp->gimage, drawable, col,
by_color_select (gdisp->gimage, drawable, color,
by_color_dialog->threshold,
by_color_sel->operation,
by_color_options->antialias,
@ -386,6 +376,8 @@ by_color_select_button_release (Tool *tool,
by_color_options->feather_radius,
by_color_options->sample_merged);
g_free(color);
/* show selection on all views */
gdisplays_flush ();

View File

@ -28,8 +28,6 @@
#include "libgimp/gimpintl.h"
#include "tile.h" /* ick. */
/* maximum information buffer size */
#define MAX_INFO_BUF 8
@ -289,15 +287,14 @@ get_color (GImage *gimage,
int sample_merged,
int final)
{
unsigned char *color;
unsigned char *src, *cmap, alpha;
TileManager *tiles;
Tile *tile;
int offx, offy;
int width, height;
int bytes;
int index;
int has_alpha;
int is_indexed;
if (!drawable && !sample_merged)
return FALSE;
@ -306,73 +303,33 @@ get_color (GImage *gimage,
drawable_offsets (drawable, &offx, &offy);
x -= offx;
y -= offy;
width = drawable_width (drawable);
height = drawable_height (drawable);
tiles = drawable_data (drawable);
bytes = drawable_bytes (drawable);
has_alpha = drawable_has_alpha (drawable);
sample_type = drawable_type (drawable);
cmap = drawable_cmap (drawable);
if (!(color = gimp_drawable_get_color_at(drawable, x, y)))
return FALSE;
sample_type = gimp_drawable_type(drawable);
is_indexed = gimp_drawable_indexed (drawable);
}
else
{
width = gimage->width;
height = gimage->height;
tiles = gimage_composite (gimage);
bytes = gimage_composite_bytes (gimage);
sample_type = gimage_composite_type (gimage);
has_alpha = (sample_type == RGBA_GIMAGE ||
sample_type == GRAYA_GIMAGE ||
sample_type == INDEXEDA_GIMAGE);
cmap = gimage_cmap (gimage);
if (!(color = gimp_image_get_color_at(gimage, x, y)))
return FALSE;
sample_type = gimp_image_composite_type(gimage);
is_indexed = FALSE;
}
if (x >= 0 && y >= 0 && x < width && y < height)
{
tile = tile_manager_get_tile (tiles, x, y, TRUE, FALSE);
src = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
}
else
return FALSE;
has_alpha = TYPE_HAS_ALPHA(sample_type);
/* if the alpha channel (if one exists) is 0, out of bounds */
col_value[RED_PIX] = color[RED_PIX];
col_value[GREEN_PIX] = color[GREEN_PIX];
col_value[BLUE_PIX] = color[BLUE_PIX];
if (has_alpha)
{
alpha = src[bytes - 1];
col_value [ALPHA_PIX] = alpha;
col_value [ALPHA_PIX] = color[3];
}
/* If the image is color, get RGB */
switch (sample_type)
{
case RGB_GIMAGE: case RGBA_GIMAGE:
col_value [RED_PIX] = src [RED_PIX];
col_value [GREEN_PIX] = src [GREEN_PIX];
col_value [BLUE_PIX] = src [BLUE_PIX];
break;
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
col_value [4] = src [0];
index = src [0] * 3;
col_value [RED_PIX] = cmap [index + 0];
col_value [GREEN_PIX] = cmap [index + 1];
col_value [BLUE_PIX] = cmap [index + 2];
break;
case GRAY_GIMAGE: case GRAYA_GIMAGE:
col_value [RED_PIX] = src [GRAY_PIX];
col_value [GREEN_PIX] = src [GRAY_PIX];
col_value [BLUE_PIX] = src [GRAY_PIX];
break;
default :
break;
}
tile_release (tile, FALSE);
if (is_indexed)
col_value [4] = color[4];
palette_set_active_color (col_value [RED_PIX], col_value [GREEN_PIX],
col_value [BLUE_PIX], final);
g_free(color);
return TRUE;
}

View File

@ -30,6 +30,7 @@
#include "image_map.h"
#include "interface.h"
#include "curves.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -96,6 +97,8 @@ struct _CurvesDialog
int curve_type;
int points[5][17][2];
unsigned char curve[5][256];
GimpLut *lut;
};
typedef double CRMatrix[4][4];
@ -141,65 +144,49 @@ static CRMatrix CR_basis =
};
static void curves (PixelRegion *, PixelRegion *, void *);
static Argument * curves_spline_invoker (Argument *);
static Argument * curves_explicit_invoker (Argument *);
/* curves machinery */
static void
curves (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
curves_lut_func(CurvesDialog *cd,
int nchannels, int channel, float value)
{
CurvesDialog *cd;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h;
float f;
int index;
double inten;
int j;
cd = (CurvesDialog *) user_data;
if (nchannels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
the first time and j = 0 the second time */
/* For bw images this runs through the loop with j = 0 the first and
only time */
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (nchannels == 2 || nchannels == 4)
&& channel == nchannels -1)
return inten;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
while (h--)
if (inten < 0.0)
inten = cd->curve[j][0]/255.0;
else if (inten >= 1.0)
inten = cd->curve[j][255]/255.0;
else /* interpolate the curve */
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (cd->color)
{
/* The contributions from the individual channel level settings */
d[RED_PIX] = cd->curve[HISTOGRAM_RED][s[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_GREEN][s[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_BLUE][s[BLUE_PIX]];
/* The overall changes */
d[RED_PIX] = cd->curve[HISTOGRAM_VALUE][d[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_VALUE][d[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_VALUE][d[BLUE_PIX]];
}
else
d[GRAY_PIX] = cd->curve[HISTOGRAM_VALUE][s[GRAY_PIX]];
if (has_alpha) {
d[alpha] = cd->curve[HISTOGRAM_ALPHA][s[alpha]];
/* d[alpha] = s[alpha]; */
}
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
index = floor(inten * 255.0);
f = inten*255.0 - index;
inten = ((1.0 - f) * cd->curve[j][index ] +
( f) * cd->curve[j][index + 1] ) / 255.0;
}
}
return inten;
}
/* curves action functions */
@ -446,6 +433,7 @@ curves_new_dialog ()
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd->curve[i][j] = j;
cd->lut = gimp_lut_new();
for (i = 0; i < 5; i++)
channel_items [i].user_data = (gpointer) cd;
@ -810,6 +798,9 @@ curves_calculate_curve (CurvesDialog *cd)
}
break;
}
gimp_lut_setup(cd->lut, (GimpLutFunc) curves_lut_func,
(void *) cd, gimp_drawable_bytes(cd->drawable));
}
static void
@ -820,7 +811,8 @@ curves_preview (CurvesDialog *cd)
active_tool->preserve = TRUE; /* Going to dirty the display... */
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
active_tool->preserve = FALSE; /* All done */
}
@ -988,7 +980,8 @@ curves_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE; /* We're about to dirty... */
if (!cd->preview)
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
if (cd->image_map)
image_map_commit (cd->image_map);
@ -1361,6 +1354,7 @@ curves_spline_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
@ -1407,6 +1401,7 @@ curves_spline_invoker (Argument *args)
/* arrange to modify the curves */
if (success)
{
cd.lut = gimp_lut_new();
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd.curve[i][j] = j;
@ -1435,9 +1430,10 @@ curves_spline_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
gimp_lut_free(cd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
@ -1509,6 +1505,7 @@ curves_explicit_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
@ -1564,15 +1561,18 @@ curves_explicit_invoker (Argument *args)
for (j = 0; j < 256; j++)
cd.curve[cd.channel][j] = curve[j];
cd.lut = gimp_lut_new();
gimp_lut_setup(cd.lut, (GimpLutFunc) curves_lut_func,
(void *) &cd, gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

View File

@ -27,6 +27,7 @@
#include "gdisplay.h"
#include "image_map.h"
#include "interface.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -66,6 +67,8 @@ struct _BrightnessContrastDialog
double contrast;
gint preview;
GimpLut *lut;
};
/* brightness contrast action functions */
@ -91,83 +94,58 @@ static void brightness_contrast_contrast_text_update (GtkWidget *, gpointer
static void *brightness_contrast_options = NULL;
static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
static void brightness_contrast (PixelRegion *, PixelRegion *, void *);
static Argument * brightness_contrast_invoker (Argument *);
/* brightness contrast machinery */
static void
brightness_contrast (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
brightness_contrast_lut_func(BrightnessContrastDialog *bcd,
int nchannels, int channel, float value)
{
BrightnessContrastDialog *bcd;
unsigned char *src, *s;
unsigned char *dest, *d;
unsigned char brightness[256];
unsigned char contrast[256];
float nvalue;
double power;
int has_alpha;
int alpha;
int w, h, b;
gint32 value;
int i;
bcd = (BrightnessContrastDialog *) user_data;
/* Set the transfer arrays (for speed) */
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (bcd->brightness < 0)
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) ((i * (255 + bcd->brightness)) / 255);
value = value * (1.0 + bcd->brightness/255.0);
else
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) (i + ((255 - i) * bcd->brightness) / 255);
value = value + ((1.0 - value) * bcd->brightness/255.0);
/* apply contrast */
if (bcd->contrast < 0)
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
value = (int) (127.0 * pow ((double) (value ? value : 1) / 127.0,
(double) (127 + bcd->contrast) / 127.0));
value = CLAMP0255 (value);
contrast[i] = (i > 127) ? (255 - value) : value;
}
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
nvalue = 0.5 * pow (nvalue * 2.0 , (double) (127 + bcd->contrast) / 127.0);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
else
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
value = (int) (127.0 * pow ((double) value / 127.0, power));
value = CLAMP0255 (value);
contrast[i] = (i > 127) ? (255 - value) : value;
}
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = contrast[brightness[s[b]]];
if (has_alpha)
d[alpha] = s[alpha];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
nvalue = 0.5 * pow (2.0 * nvalue, power);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
return value;
}
@ -334,6 +312,8 @@ brightness_contrast_new_dialog ()
bcd = g_malloc (sizeof (BrightnessContrastDialog));
bcd->preview = TRUE;
bcd->lut = gimp_lut_new();
/* The shell and main vbox */
bcd->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (bcd->shell), "brightness_contrast", "Gimp");
@ -483,7 +463,10 @@ brightness_contrast_preview (BrightnessContrastDialog *bcd)
if (!bcd->image_map)
g_message (_("brightness_contrast_preview(): No image map"));
active_tool->preserve = TRUE;
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) bcd, gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut);
active_tool->preserve = FALSE;
}
@ -501,7 +484,12 @@ brightness_contrast_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!bcd->preview)
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
{
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) bcd, gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut);
}
if (bcd->image_map)
image_map_commit (bcd->image_map);
@ -736,6 +724,7 @@ brightness_contrast_invoker (Argument *args)
{
bcd.brightness = brightness;
bcd.contrast = contrast;
bcd.lut = gimp_lut_new();
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -743,9 +732,13 @@ brightness_contrast_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
brightness_contrast (&srcPR, &destPR, (void *) &bcd);
gimp_lut_setup(bcd.lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) &bcd, gimp_drawable_bytes(drawable));
pixel_regions_process_parallel((p_func)gimp_lut_process, bcd.lut,
2, &srcPR, &destPR);
gimp_lut_free(bcd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -340,9 +340,7 @@ by_color_select_button_release (Tool *tool,
GDisplay * gdisp;
int x, y;
GimpDrawable *drawable;
Tile *tile;
unsigned char col[MAX_CHANNELS];
unsigned char *data;
unsigned char *color;
int use_offsets;
gdisp = (GDisplay *) gdisp_ptr;
@ -360,25 +358,17 @@ by_color_select_button_release (Tool *tool,
/* Get the start color */
if (by_color_options->sample_merged)
{
if (x < 0 || y < 0 || x >= gdisp->gimage->width || y >= gdisp->gimage->height)
if (!(color = gimp_image_get_color_at(gdisp->gimage, x, y)))
return;
tile = tile_manager_get_tile (gimage_composite (gdisp->gimage), x, y, TRUE, FALSE);
data = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimage_get_color (gdisp->gimage, gimage_composite_type(gdisp->gimage), col, data);
tile_release (tile, FALSE);
}
else
{
if (x < 0 || y < 0 || x >= drawable_width (drawable) || y >= drawable_height (drawable))
if (!(color = gimp_drawable_get_color_at(drawable, x, y)))
return;
tile = tile_manager_get_tile (drawable_data (drawable), x, y, TRUE, FALSE);
data = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
gimage_get_color (gdisp->gimage, drawable_type(drawable), col, data);
tile_release (tile, FALSE);
}
/* select the area */
by_color_select (gdisp->gimage, drawable, col,
by_color_select (gdisp->gimage, drawable, color,
by_color_dialog->threshold,
by_color_sel->operation,
by_color_options->antialias,
@ -386,6 +376,8 @@ by_color_select_button_release (Tool *tool,
by_color_options->feather_radius,
by_color_options->sample_merged);
g_free(color);
/* show selection on all views */
gdisplays_flush ();

View File

@ -30,6 +30,7 @@
#include "image_map.h"
#include "interface.h"
#include "curves.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -96,6 +97,8 @@ struct _CurvesDialog
int curve_type;
int points[5][17][2];
unsigned char curve[5][256];
GimpLut *lut;
};
typedef double CRMatrix[4][4];
@ -141,65 +144,49 @@ static CRMatrix CR_basis =
};
static void curves (PixelRegion *, PixelRegion *, void *);
static Argument * curves_spline_invoker (Argument *);
static Argument * curves_explicit_invoker (Argument *);
/* curves machinery */
static void
curves (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
curves_lut_func(CurvesDialog *cd,
int nchannels, int channel, float value)
{
CurvesDialog *cd;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h;
float f;
int index;
double inten;
int j;
cd = (CurvesDialog *) user_data;
if (nchannels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
the first time and j = 0 the second time */
/* For bw images this runs through the loop with j = 0 the first and
only time */
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (nchannels == 2 || nchannels == 4)
&& channel == nchannels -1)
return inten;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
while (h--)
if (inten < 0.0)
inten = cd->curve[j][0]/255.0;
else if (inten >= 1.0)
inten = cd->curve[j][255]/255.0;
else /* interpolate the curve */
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (cd->color)
{
/* The contributions from the individual channel level settings */
d[RED_PIX] = cd->curve[HISTOGRAM_RED][s[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_GREEN][s[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_BLUE][s[BLUE_PIX]];
/* The overall changes */
d[RED_PIX] = cd->curve[HISTOGRAM_VALUE][d[RED_PIX]];
d[GREEN_PIX] = cd->curve[HISTOGRAM_VALUE][d[GREEN_PIX]];
d[BLUE_PIX] = cd->curve[HISTOGRAM_VALUE][d[BLUE_PIX]];
}
else
d[GRAY_PIX] = cd->curve[HISTOGRAM_VALUE][s[GRAY_PIX]];
if (has_alpha) {
d[alpha] = cd->curve[HISTOGRAM_ALPHA][s[alpha]];
/* d[alpha] = s[alpha]; */
}
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
index = floor(inten * 255.0);
f = inten*255.0 - index;
inten = ((1.0 - f) * cd->curve[j][index ] +
( f) * cd->curve[j][index + 1] ) / 255.0;
}
}
return inten;
}
/* curves action functions */
@ -446,6 +433,7 @@ curves_new_dialog ()
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd->curve[i][j] = j;
cd->lut = gimp_lut_new();
for (i = 0; i < 5; i++)
channel_items [i].user_data = (gpointer) cd;
@ -810,6 +798,9 @@ curves_calculate_curve (CurvesDialog *cd)
}
break;
}
gimp_lut_setup(cd->lut, (GimpLutFunc) curves_lut_func,
(void *) cd, gimp_drawable_bytes(cd->drawable));
}
static void
@ -820,7 +811,8 @@ curves_preview (CurvesDialog *cd)
active_tool->preserve = TRUE; /* Going to dirty the display... */
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
active_tool->preserve = FALSE; /* All done */
}
@ -988,7 +980,8 @@ curves_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE; /* We're about to dirty... */
if (!cd->preview)
image_map_apply (cd->image_map, curves, (void *) cd);
image_map_apply (cd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) cd->lut);
if (cd->image_map)
image_map_commit (cd->image_map);
@ -1361,6 +1354,7 @@ curves_spline_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
@ -1407,6 +1401,7 @@ curves_spline_invoker (Argument *args)
/* arrange to modify the curves */
if (success)
{
cd.lut = gimp_lut_new();
for (i = 0; i < 5; i++)
for (j = 0; j < 256; j++)
cd.curve[i][j] = j;
@ -1435,9 +1430,10 @@ curves_spline_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
gimp_lut_free(cd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
@ -1509,6 +1505,7 @@ curves_explicit_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
cd.drawable = drawable;
if (drawable == NULL)
success = FALSE;
else
@ -1564,15 +1561,18 @@ curves_explicit_invoker (Argument *args)
for (j = 0; j < 256; j++)
cd.curve[cd.channel][j] = curve[j];
cd.lut = gimp_lut_new();
gimp_lut_setup(cd.lut, (GimpLutFunc) curves_lut_func,
(void *) &cd, gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
curves (&srcPR, &destPR, (void *) &cd);
pixel_regions_process_parallel((p_func)gimp_lut_process, cd.lut,
2, &srcPR, &destPR);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

View File

@ -29,6 +29,7 @@
#include "image_map.h"
#include "interface.h"
#include "levels.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -95,9 +96,9 @@ struct _LevelsDialog
int active_slider;
int slider_pos[5]; /* positions for the five sliders */
unsigned char input[5][256];
unsigned char output[5][256];
unsigned char input[5][256]; /* this is used only by the gui */
GimpLut *lut;
};
/* levels action functions */
@ -133,65 +134,61 @@ static gint levels_output_da_events (GtkWidget *, GdkEvent *,
static void *levels_options = NULL;
static LevelsDialog *levels_dialog = NULL;
static void levels (PixelRegion *, PixelRegion *, void *);
static void levels_histogram_info (PixelRegion *, PixelRegion *, HistogramValues, void *);
static void levels_histogram_range (int, int, HistogramValues, void *);
static Argument * levels_invoker (Argument *);
/* levels machinery */
static void
levels (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
levels_lut_func(LevelsDialog *ld,
int nchannels, int channel, float value)
{
LevelsDialog *ld;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h;
double inten;
int j;
double input, output;
ld = (LevelsDialog *) user_data;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
if (nchannels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
the first time and j = 0 the second time */
/* For bw images this runs through the loop with j = 0 the first and
only time */
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (nchannels == 2 || nchannels == 4)
&& channel == nchannels -1)
return inten;
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (ld->color)
{
/* The contributions from the individual channel level settings */
d[RED_PIX] = ld->output[HISTOGRAM_RED][ld->input[HISTOGRAM_RED][s[RED_PIX]]];
d[GREEN_PIX] = ld->output[HISTOGRAM_GREEN][ld->input[HISTOGRAM_GREEN][s[GREEN_PIX]]];
d[BLUE_PIX] = ld->output[HISTOGRAM_BLUE][ld->input[HISTOGRAM_BLUE][s[BLUE_PIX]]];
/* determine input intensity */
if (ld->high_input[j] != ld->low_input[j])
inten = (double) (255.0*inten - ld->low_input[j]) /
(double) (ld->high_input[j] - ld->low_input[j]);
else
inten = (double) (255.0*inten - ld->low_input[j]);
/* The overall changes */
d[RED_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[RED_PIX]]];
d[GREEN_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[GREEN_PIX]]];
d[BLUE_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[BLUE_PIX]]];
}
else
d[GRAY_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][s[GRAY_PIX]]];;
if (ld->gamma[j] != 0.0)
if (inten >= 0.0)
inten = pow ( inten, (1.0 / ld->gamma[j]));
else
inten = -pow (-inten, (1.0 / ld->gamma[j]));
if (has_alpha)
d[alpha] = ld->output[HISTOGRAM_ALPHA][ld->input[HISTOGRAM_ALPHA][s[alpha]]];
/*d[alpha] = s[alpha];*/
/* determine the output intensity */
if (ld->high_output[j] >= ld->low_output[j])
inten = (double) (inten * (ld->high_output[j] - ld->low_output[j]) +
ld->low_output[j]);
else if (ld->high_output[j] < ld->low_output[j])
inten = (double) (ld->low_output[j] - inten *
(ld->low_output[j] - ld->high_output[j]));
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
inten /= 255.0;
}
return inten;
}
static void
@ -523,6 +520,8 @@ levels_new_dialog ()
ld = g_malloc (sizeof (LevelsDialog));
ld->preview = TRUE;
ld->lut = gimp_lut_new();
for (i = 0; i < 5; i++)
color_option_items [i].user_data = (gpointer) ld;
@ -778,18 +777,6 @@ levels_calculate_transfers (LevelsDialog *ld)
if (ld->gamma[j] != 0.0)
inten = pow (inten, (1.0 / ld->gamma[j]));
ld->input[j][i] = (unsigned char) (inten * 255.0 + 0.5);
/* determine the output intensity */
inten = (double) i / 255.0;
if (ld->high_output[j] >= ld->low_output[j])
inten = (double) (inten * (ld->high_output[j] - ld->low_output[j]) +
ld->low_output[j]);
else if (ld->high_output[j] < ld->low_output[j])
inten = (double) (ld->low_output[j] - inten *
(ld->low_output[j] - ld->high_output[j]));
inten = BOUNDS (inten, 0.0, 255.0);
ld->output[j][i] = (unsigned char) (inten + 0.5);
}
}
}
@ -803,6 +790,9 @@ levels_update (LevelsDialog *ld,
/* Recalculate the transfer arrays */
levels_calculate_transfers (ld);
/* set up the lut */
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func,
(void *) ld, gimp_drawable_bytes(ld->drawable));
if (update & LOW_INPUT)
{
@ -906,7 +896,8 @@ levels_preview (LevelsDialog *ld)
if (!ld->image_map)
g_warning (_("No image map"));
active_tool->preserve = TRUE;
image_map_apply (ld->image_map, levels, (void *) ld);
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut);
active_tool->preserve = FALSE;
}
@ -1089,7 +1080,12 @@ levels_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!ld->preview)
image_map_apply (ld->image_map, levels, (void *) ld);
{
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func,
(void *) ld, gimp_drawable_bytes(ld->drawable));
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut);
}
if (ld->image_map)
image_map_commit (ld->image_map);
@ -1615,6 +1611,7 @@ levels_invoker (Argument *args)
ld.high_output[i] = 255;
}
ld.lut = gimp_lut_new();
ld.channel = channel;
ld.color = drawable_color (drawable);
ld.low_input[channel] = low_input;
@ -1623,8 +1620,9 @@ levels_invoker (Argument *args)
ld.low_output[channel] = low_output;
ld.high_output[channel] = high_output;
/* calculate the transfer arrays */
levels_calculate_transfers (&ld);
/* setup the lut */
gimp_lut_setup(ld.lut, (GimpLutFunc) levels_lut_func,
(void *) &ld, gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -1632,9 +1630,10 @@ levels_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
levels (&srcPR, &destPR, (void *) &ld);
pixel_regions_process_parallel((p_func)gimp_lut_process, ld.lut,
2, &srcPR, &destPR);
gimp_lut_free(ld.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -25,6 +25,7 @@
#include "image_map.h"
#include "interface.h"
#include "posterize.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -49,6 +50,8 @@ struct _PosterizeDialog
int levels;
gint preview;
GimpLut *lut;
};
/* posterize action functions */
@ -70,62 +73,29 @@ static gint posterize_delete_callback (GtkWidget *, GdkEvent *
static void *posterize_options = NULL;
static PosterizeDialog *posterize_dialog = NULL;
static void posterize (PixelRegion *, PixelRegion *, void *);
static Argument * posterize_invoker (Argument *);
/* posterize machinery */
static void
posterize (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
posterize_lut_func(PosterizeDialog *pd,
int nchannels, int channel, float value)
{
PosterizeDialog *pd;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h, b, i;
double interval, half_interval;
unsigned char transfer[256];
int levels;
/* don't posterize the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
pd = (PosterizeDialog *) user_data;
if (pd->levels < 2)
levels = 2;
else
levels = pd->levels;
/* Set the transfer array */
interval = 255.0 / (double) (pd->levels - 1);
half_interval = interval / 2.0;
value = rint(value * (pd->levels - 1.0)) / (pd->levels - 1.0);
for (i = 0; i < 256; i++)
transfer[i] = (unsigned char) ((int) (((double) i + half_interval) / interval) * interval);
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = transfer[s[b]];
if (has_alpha)
d[alpha] = s[alpha];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
return value;
}
/* by_color select action functions */
static void
@ -289,6 +259,7 @@ posterize_new_dialog ()
pd = g_malloc (sizeof (PosterizeDialog));
pd->preview = TRUE;
pd->levels = 3;
pd->lut = gimp_lut_new();
/* The shell and main vbox */
pd->shell = gtk_dialog_new ();
@ -356,7 +327,10 @@ posterize_preview (PosterizeDialog *pd)
if (!pd->image_map)
g_message (_("posterize_preview(): No image map"));
active_tool->preserve = TRUE;
image_map_apply (pd->image_map, posterize, (void *) pd);
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func,
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut);
active_tool->preserve = FALSE;
}
@ -374,8 +348,12 @@ posterize_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!pd->preview)
image_map_apply (pd->image_map, posterize, (void *) pd);
{
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func,
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut);
}
if (pd->image_map)
image_map_commit (pd->image_map);
@ -531,16 +509,17 @@ posterize_invoker (Argument *args)
if (success)
{
pd.levels = levels;
pd.lut = gimp_lut_new();
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
posterize (&srcPR, &destPR, (void *) &pd);
pixel_regions_process_parallel((p_func)gimp_lut_process, pd.lut,
2, &srcPR, &destPR);
gimp_lut_free(pd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -29,6 +29,7 @@
#include "image_map.h"
#include "interface.h"
#include "levels.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -95,9 +96,9 @@ struct _LevelsDialog
int active_slider;
int slider_pos[5]; /* positions for the five sliders */
unsigned char input[5][256];
unsigned char output[5][256];
unsigned char input[5][256]; /* this is used only by the gui */
GimpLut *lut;
};
/* levels action functions */
@ -133,65 +134,61 @@ static gint levels_output_da_events (GtkWidget *, GdkEvent *,
static void *levels_options = NULL;
static LevelsDialog *levels_dialog = NULL;
static void levels (PixelRegion *, PixelRegion *, void *);
static void levels_histogram_info (PixelRegion *, PixelRegion *, HistogramValues, void *);
static void levels_histogram_range (int, int, HistogramValues, void *);
static Argument * levels_invoker (Argument *);
/* levels machinery */
static void
levels (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
levels_lut_func(LevelsDialog *ld,
int nchannels, int channel, float value)
{
LevelsDialog *ld;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h;
double inten;
int j;
double input, output;
ld = (LevelsDialog *) user_data;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
if (nchannels == 1)
j = 0;
else
j = channel + 1;
inten = value;
/* For color images this runs through the loop with j = channel +1
the first time and j = 0 the second time */
/* For bw images this runs through the loop with j = 0 the first and
only time */
for (; j >= 0; j -= (channel + 1))
{
/* don't apply the overall curve to the alpha channel */
if (j == 0 && (nchannels == 2 || nchannels == 4)
&& channel == nchannels -1)
return inten;
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (ld->color)
{
/* The contributions from the individual channel level settings */
d[RED_PIX] = ld->output[HISTOGRAM_RED][ld->input[HISTOGRAM_RED][s[RED_PIX]]];
d[GREEN_PIX] = ld->output[HISTOGRAM_GREEN][ld->input[HISTOGRAM_GREEN][s[GREEN_PIX]]];
d[BLUE_PIX] = ld->output[HISTOGRAM_BLUE][ld->input[HISTOGRAM_BLUE][s[BLUE_PIX]]];
/* determine input intensity */
if (ld->high_input[j] != ld->low_input[j])
inten = (double) (255.0*inten - ld->low_input[j]) /
(double) (ld->high_input[j] - ld->low_input[j]);
else
inten = (double) (255.0*inten - ld->low_input[j]);
/* The overall changes */
d[RED_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[RED_PIX]]];
d[GREEN_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[GREEN_PIX]]];
d[BLUE_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][d[BLUE_PIX]]];
}
else
d[GRAY_PIX] = ld->output[HISTOGRAM_VALUE][ld->input[HISTOGRAM_VALUE][s[GRAY_PIX]]];;
if (ld->gamma[j] != 0.0)
if (inten >= 0.0)
inten = pow ( inten, (1.0 / ld->gamma[j]));
else
inten = -pow (-inten, (1.0 / ld->gamma[j]));
if (has_alpha)
d[alpha] = ld->output[HISTOGRAM_ALPHA][ld->input[HISTOGRAM_ALPHA][s[alpha]]];
/*d[alpha] = s[alpha];*/
/* determine the output intensity */
if (ld->high_output[j] >= ld->low_output[j])
inten = (double) (inten * (ld->high_output[j] - ld->low_output[j]) +
ld->low_output[j]);
else if (ld->high_output[j] < ld->low_output[j])
inten = (double) (ld->low_output[j] - inten *
(ld->low_output[j] - ld->high_output[j]));
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
inten /= 255.0;
}
return inten;
}
static void
@ -523,6 +520,8 @@ levels_new_dialog ()
ld = g_malloc (sizeof (LevelsDialog));
ld->preview = TRUE;
ld->lut = gimp_lut_new();
for (i = 0; i < 5; i++)
color_option_items [i].user_data = (gpointer) ld;
@ -778,18 +777,6 @@ levels_calculate_transfers (LevelsDialog *ld)
if (ld->gamma[j] != 0.0)
inten = pow (inten, (1.0 / ld->gamma[j]));
ld->input[j][i] = (unsigned char) (inten * 255.0 + 0.5);
/* determine the output intensity */
inten = (double) i / 255.0;
if (ld->high_output[j] >= ld->low_output[j])
inten = (double) (inten * (ld->high_output[j] - ld->low_output[j]) +
ld->low_output[j]);
else if (ld->high_output[j] < ld->low_output[j])
inten = (double) (ld->low_output[j] - inten *
(ld->low_output[j] - ld->high_output[j]));
inten = BOUNDS (inten, 0.0, 255.0);
ld->output[j][i] = (unsigned char) (inten + 0.5);
}
}
}
@ -803,6 +790,9 @@ levels_update (LevelsDialog *ld,
/* Recalculate the transfer arrays */
levels_calculate_transfers (ld);
/* set up the lut */
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func,
(void *) ld, gimp_drawable_bytes(ld->drawable));
if (update & LOW_INPUT)
{
@ -906,7 +896,8 @@ levels_preview (LevelsDialog *ld)
if (!ld->image_map)
g_warning (_("No image map"));
active_tool->preserve = TRUE;
image_map_apply (ld->image_map, levels, (void *) ld);
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut);
active_tool->preserve = FALSE;
}
@ -1089,7 +1080,12 @@ levels_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!ld->preview)
image_map_apply (ld->image_map, levels, (void *) ld);
{
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func,
(void *) ld, gimp_drawable_bytes(ld->drawable));
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut);
}
if (ld->image_map)
image_map_commit (ld->image_map);
@ -1615,6 +1611,7 @@ levels_invoker (Argument *args)
ld.high_output[i] = 255;
}
ld.lut = gimp_lut_new();
ld.channel = channel;
ld.color = drawable_color (drawable);
ld.low_input[channel] = low_input;
@ -1623,8 +1620,9 @@ levels_invoker (Argument *args)
ld.low_output[channel] = low_output;
ld.high_output[channel] = high_output;
/* calculate the transfer arrays */
levels_calculate_transfers (&ld);
/* setup the lut */
gimp_lut_setup(ld.lut, (GimpLutFunc) levels_lut_func,
(void *) &ld, gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -1632,9 +1630,10 @@ levels_invoker (Argument *args)
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
levels (&srcPR, &destPR, (void *) &ld);
pixel_regions_process_parallel((p_func)gimp_lut_process, ld.lut,
2, &srcPR, &destPR);
gimp_lut_free(ld.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -25,6 +25,7 @@
#include "image_map.h"
#include "interface.h"
#include "posterize.h"
#include "gimplut.h"
#include "libgimp/gimpintl.h"
@ -49,6 +50,8 @@ struct _PosterizeDialog
int levels;
gint preview;
GimpLut *lut;
};
/* posterize action functions */
@ -70,62 +73,29 @@ static gint posterize_delete_callback (GtkWidget *, GdkEvent *
static void *posterize_options = NULL;
static PosterizeDialog *posterize_dialog = NULL;
static void posterize (PixelRegion *, PixelRegion *, void *);
static Argument * posterize_invoker (Argument *);
/* posterize machinery */
static void
posterize (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static float
posterize_lut_func(PosterizeDialog *pd,
int nchannels, int channel, float value)
{
PosterizeDialog *pd;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h, b, i;
double interval, half_interval;
unsigned char transfer[256];
int levels;
/* don't posterize the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
pd = (PosterizeDialog *) user_data;
if (pd->levels < 2)
levels = 2;
else
levels = pd->levels;
/* Set the transfer array */
interval = 255.0 / (double) (pd->levels - 1);
half_interval = interval / 2.0;
value = rint(value * (pd->levels - 1.0)) / (pd->levels - 1.0);
for (i = 0; i < 256; i++)
transfer[i] = (unsigned char) ((int) (((double) i + half_interval) / interval) * interval);
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = transfer[s[b]];
if (has_alpha)
d[alpha] = s[alpha];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
return value;
}
/* by_color select action functions */
static void
@ -289,6 +259,7 @@ posterize_new_dialog ()
pd = g_malloc (sizeof (PosterizeDialog));
pd->preview = TRUE;
pd->levels = 3;
pd->lut = gimp_lut_new();
/* The shell and main vbox */
pd->shell = gtk_dialog_new ();
@ -356,7 +327,10 @@ posterize_preview (PosterizeDialog *pd)
if (!pd->image_map)
g_message (_("posterize_preview(): No image map"));
active_tool->preserve = TRUE;
image_map_apply (pd->image_map, posterize, (void *) pd);
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func,
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut);
active_tool->preserve = FALSE;
}
@ -374,8 +348,12 @@ posterize_ok_callback (GtkWidget *widget,
active_tool->preserve = TRUE;
if (!pd->preview)
image_map_apply (pd->image_map, posterize, (void *) pd);
{
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func,
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut);
}
if (pd->image_map)
image_map_commit (pd->image_map);
@ -531,16 +509,17 @@ posterize_invoker (Argument *args)
if (success)
{
pd.levels = levels;
pd.lut = gimp_lut_new();
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
posterize (&srcPR, &destPR, (void *) &pd);
pixel_regions_process_parallel((p_func)gimp_lut_process, pd.lut,
2, &srcPR, &destPR);
gimp_lut_free(pd.lut);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@ -96,6 +96,18 @@ parasite_copy (const Parasite *parasite)
parasite->size, parasite->data);
}
int
parasite_compare (const Parasite *a, const Parasite *b)
{
if (a && b && a->name && b->name && strcmp(a->name, b->name) == 0 &&
a->flags == b->flags && a->size == b->size )
if (a->data == NULL && b->data == NULL)
return TRUE;
else if (a->data && b->data && memcmp(a->data, b->data, a->size) == 0)
return TRUE;
return FALSE;
}
int
parasite_is_persistent(const Parasite *p)
{
@ -112,6 +124,14 @@ parasite_has_flag(const Parasite *p, gulong flag)
return (p->flags & flag);
}
const char *
parasite_name(const Parasite *p)
{
if (p)
return p->name;
return NULL;
}
void *parasite_data(const Parasite *p)
{
if (p)

View File

@ -35,17 +35,21 @@ extern "C" {
#define PARASITE_ATTACH_GRANDPARENT (0x80 << 16)
#define PARASITE_GRANDPARENT_PERSISTENT (PARASITE_PERSISTENT << 16)
Parasite *parasite_new (const char *name, guint32 flags,
Parasite *parasite_new (const char *name, guint32 flags,
guint32 size, const void *data);
void parasite_free (Parasite *parasite);
void parasite_free (Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite);
int parasite_is_type (const Parasite *parasite, const char *name);
int parasite_is_persistent (const Parasite *p);
int parasite_has_flag (const Parasite *p, gulong flag);
void *parasite_data (const Parasite *p);
long parasite_data_size (const Parasite *p);
int parasite_compare (const Parasite *a, const Parasite *b);
int parasite_is_type (const Parasite *parasite,
const char *name);
int parasite_is_persistent (const Parasite *p);
int parasite_has_flag (const Parasite *p, gulong flag);
const char *parasite_name (const Parasite *p);
void *parasite_data (const Parasite *p);
long parasite_data_size (const Parasite *p);

View File

@ -96,6 +96,18 @@ parasite_copy (const Parasite *parasite)
parasite->size, parasite->data);
}
int
parasite_compare (const Parasite *a, const Parasite *b)
{
if (a && b && a->name && b->name && strcmp(a->name, b->name) == 0 &&
a->flags == b->flags && a->size == b->size )
if (a->data == NULL && b->data == NULL)
return TRUE;
else if (a->data && b->data && memcmp(a->data, b->data, a->size) == 0)
return TRUE;
return FALSE;
}
int
parasite_is_persistent(const Parasite *p)
{
@ -112,6 +124,14 @@ parasite_has_flag(const Parasite *p, gulong flag)
return (p->flags & flag);
}
const char *
parasite_name(const Parasite *p)
{
if (p)
return p->name;
return NULL;
}
void *parasite_data(const Parasite *p)
{
if (p)

View File

@ -35,17 +35,21 @@ extern "C" {
#define PARASITE_ATTACH_GRANDPARENT (0x80 << 16)
#define PARASITE_GRANDPARENT_PERSISTENT (PARASITE_PERSISTENT << 16)
Parasite *parasite_new (const char *name, guint32 flags,
Parasite *parasite_new (const char *name, guint32 flags,
guint32 size, const void *data);
void parasite_free (Parasite *parasite);
void parasite_free (Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite);
int parasite_is_type (const Parasite *parasite, const char *name);
int parasite_is_persistent (const Parasite *p);
int parasite_has_flag (const Parasite *p, gulong flag);
void *parasite_data (const Parasite *p);
long parasite_data_size (const Parasite *p);
int parasite_compare (const Parasite *a, const Parasite *b);
int parasite_is_type (const Parasite *parasite,
const char *name);
int parasite_is_persistent (const Parasite *p);
int parasite_has_flag (const Parasite *p, gulong flag);
const char *parasite_name (const Parasite *p);
void *parasite_data (const Parasite *p);
long parasite_data_size (const Parasite *p);

View File

@ -96,6 +96,18 @@ parasite_copy (const Parasite *parasite)
parasite->size, parasite->data);
}
int
parasite_compare (const Parasite *a, const Parasite *b)
{
if (a && b && a->name && b->name && strcmp(a->name, b->name) == 0 &&
a->flags == b->flags && a->size == b->size )
if (a->data == NULL && b->data == NULL)
return TRUE;
else if (a->data && b->data && memcmp(a->data, b->data, a->size) == 0)
return TRUE;
return FALSE;
}
int
parasite_is_persistent(const Parasite *p)
{
@ -112,6 +124,14 @@ parasite_has_flag(const Parasite *p, gulong flag)
return (p->flags & flag);
}
const char *
parasite_name(const Parasite *p)
{
if (p)
return p->name;
return NULL;
}
void *parasite_data(const Parasite *p)
{
if (p)

View File

@ -35,17 +35,21 @@ extern "C" {
#define PARASITE_ATTACH_GRANDPARENT (0x80 << 16)
#define PARASITE_GRANDPARENT_PERSISTENT (PARASITE_PERSISTENT << 16)
Parasite *parasite_new (const char *name, guint32 flags,
Parasite *parasite_new (const char *name, guint32 flags,
guint32 size, const void *data);
void parasite_free (Parasite *parasite);
void parasite_free (Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite);
int parasite_is_type (const Parasite *parasite, const char *name);
int parasite_is_persistent (const Parasite *p);
int parasite_has_flag (const Parasite *p, gulong flag);
void *parasite_data (const Parasite *p);
long parasite_data_size (const Parasite *p);
int parasite_compare (const Parasite *a, const Parasite *b);
int parasite_is_type (const Parasite *parasite,
const char *name);
int parasite_is_persistent (const Parasite *p);
int parasite_has_flag (const Parasite *p, gulong flag);
const char *parasite_name (const Parasite *p);
void *parasite_data (const Parasite *p);
long parasite_data_size (const Parasite *p);