mirror of https://github.com/GNOME/gimp.git
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:
parent
ed92f2189f
commit
a26f8d3f5c
|
@ -186,6 +186,8 @@ gimp_SOURCES = \
|
|||
gimplist.h \
|
||||
gimplistF.h \
|
||||
gimplistP.h \
|
||||
gimplut.c \
|
||||
gimplut.h \
|
||||
gimpparasite.c \
|
||||
gimpparasite.h \
|
||||
gimpprogress.c \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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 };
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
112
app/curves.c
112
app/curves.c
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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 };
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
56
app/invert.c
56
app/invert.c
|
@ -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));
|
||||
|
|
|
@ -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 };
|
||||
*/
|
||||
|
|
131
app/levels.c
131
app/levels.c
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue