build color_cmds, lut_funcs, and pixel_processor feedback in the splash

* app/Makefile.am: build color_cmds, lut_funcs, and pixel_processor
	* app/app_procs.c: feedback in the splash screen when loading
 	parasites.
	* app/boundary.c: Optimized find_empty_segs.

	* app/brightness_contrast.[ch]
	* app/levels.[ch]
	* app/posterize.[ch]:
 	moved pdb and lut calculation code.  These files now contain only
	GUI functions.

	* app/channel.c: Optimized channel_bounds (fewer compares, better
 	use of registers).  Use color_region instead of channel_*_segment
 	in channel_combine_rect.  Optimized channel_combine_ellipse by
 	skipping pixels inside of the ellipse.  Use
 	pixel_region_process_parallel in channel_combine_mask.  Use a
 	GimpLut in channel_invert, and channel_sharpen.

	* app/invert.c
	* app/equalize.c: moved the lut functions to lut_funcs.c

	* app/gimpdrawable.c, app/gimpdrawableP.h
	* app/gimpimage.c, app/gimpimageP.h: removed unused gimpmatrix
	variables/includes.

	* app/gimplut.[ch]: added new function gimp_lut_process_inline
 	that operates on a single PixelRegion.

	* app/gimpparasite.[ch]: new functions to save/load parasiterc

	* app/parasitelist.[ch]: new functions to save/load ParasiteLists
 	in/from files.

	* libgimp/parasite.[ch]: new functions to load/save parasites.

	* app/internal_procs.c: get some procs from new location in
	color_cmds.h.

	* app/pixel_region.[ch]: moved pixel_regions_process_parallel
 	related functions to a new file.

	* app/color_cmds.[ch]: new files for PDB
 	definitions/implementations of color correction functions.

	* app/lut_funcs.[ch]: new files to hold lut creation functions.

	* app/pixel_processor.[ch]: new files that contain the
 	pixel_regions_process_parallel routines.  Added some new
 	capabilities that are currently unused.
This commit is contained in:
jaycox 1999-04-09 06:00:11 +00:00
parent 8650675f22
commit dde3603123
80 changed files with 3597 additions and 3021 deletions

View File

@ -1,3 +1,55 @@
1999-04-08 Jay Cox <jaycox@earthlink.net>
* app/Makefile.am: build color_cmds, lut_funcs, and pixel_processor
* app/app_procs.c: feedback in the splash screen when loading
parasites.
* app/boundary.c: Optimized find_empty_segs.
* app/brightness_contrast.[ch]
* app/levels.[ch]
* app/posterize.[ch]:
moved pdb and lut calculation code. These files now contain only
GUI functions.
* app/channel.c: Optimized channel_bounds (fewer compares, better
use of registers). Use color_region instead of channel_*_segment
in channel_combine_rect. Optimized channel_combine_ellipse by
skipping pixels inside of the ellipse. Use
pixel_region_process_parallel in channel_combine_mask. Use a
GimpLut in channel_invert, and channel_sharpen.
* app/invert.c
* app/equalize.c: moved the lut functions to lut_funcs.c
* app/gimpdrawable.c, app/gimpdrawableP.h
* app/gimpimage.c, app/gimpimageP.h: removed unused gimpmatrix
variables/includes.
* app/gimplut.[ch]: added new function gimp_lut_process_inline
that operates on a single PixelRegion.
* app/gimpparasite.[ch]: new functions to save/load parasiterc
* app/parasitelist.[ch]: new functions to save/load ParasiteLists
in/from files.
* libgimp/parasite.[ch]: new functions to load/save parasites.
* app/internal_procs.c: get some procs from new location in
color_cmds.h.
* app/pixel_region.[ch]: moved pixel_regions_process_parallel
related functions to a new file.
* app/color_cmds.[ch]: new files for PDB
definitions/implementations of color correction functions.
* app/lut_funcs.[ch]: new files to hold lut creation functions.
* app/pixel_processor.[ch]: new files that contain the
pixel_regions_process_parallel routines. Added some new
capabilities that are currently unused.
Fri Apr 9 01:52:23 MEST 1999 Sven Neumann <sven@gimp.org> Fri Apr 9 01:52:23 MEST 1999 Sven Neumann <sven@gimp.org>
* plug-ins/autocrop/autocrop.c: Fixed a Bad Bug(TM). * plug-ins/autocrop/autocrop.c: Fixed a Bad Bug(TM).

View File

@ -77,6 +77,8 @@ gimp_SOURCES = \
color_area.h \ color_area.h \
color_balance.c \ color_balance.c \
color_balance.h \ color_balance.h \
color_cmds.c \
color_cmds.h \
color_notebook.c \ color_notebook.c \
color_notebook.h \ color_notebook.h \
color_panel.c \ color_panel.c \
@ -245,6 +247,8 @@ gimp_SOURCES = \
layers_dialogP.h \ layers_dialogP.h \
levels.c \ levels.c \
levels.h \ levels.h \
lut_funcs.c \
lut_funcs.h \
magnify.c \ magnify.c \
magnify.h \ magnify.h \
main.c \ main.c \
@ -288,6 +292,8 @@ gimp_SOURCES = \
pencil.h \ pencil.h \
perspective_tool.c \ perspective_tool.c \
perspective_tool.h \ perspective_tool.h \
pixel_processor.c \
pixel_processor.h \
pixel_region.c \ pixel_region.c \
pixel_region.h \ pixel_region.h \
pixmaps.h \ pixmaps.h \

View File

@ -85,6 +85,7 @@
#include "color_notebook.h" #include "color_notebook.h"
#include "color_select.h" #include "color_select.h"
#include "gimpparasite.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -535,15 +536,16 @@ app_init (void)
file_ops_pre_init (); /* pre-initialize the file types */ file_ops_pre_init (); /* pre-initialize the file types */
RESET_BAR(); RESET_BAR();
xcf_init (); /* initialize the xcf file format routines */ xcf_init (); /* initialize the xcf file format routines */
gimp_init_parasites (); /* initialize the parasite table */
app_init_update_status (_("Looking for data files"), _("Brushes"), 0.00); app_init_update_status (_("Looking for data files"), _("Parasites"), 0.00);
gimp_init_parasites (); /* initialize the global parasite table */
app_init_update_status (NULL, _("Brushes"), 0.20);
brushes_init (no_data); /* initialize the list of gimp brushes */ brushes_init (no_data); /* initialize the list of gimp brushes */
app_init_update_status (NULL, _("Patterns"), 0.25); app_init_update_status (NULL, _("Patterns"), 0.40);
patterns_init (no_data); /* initialize the list of gimp patterns */ patterns_init (no_data); /* initialize the list of gimp patterns */
app_init_update_status (NULL, _("Palettes"), 0.50); app_init_update_status (NULL, _("Palettes"), 0.60);
palettes_init (no_data); /* initialize the list of gimp palettes */ palettes_init (no_data); /* initialize the list of gimp palettes */
app_init_update_status (NULL, _("Gradients"), 0.75); app_init_update_status (NULL, _("Gradients"), 0.80);
gradients_init (no_data); /* initialize the list of gimp gradients */ gradients_init (no_data); /* initialize the list of gimp gradients */
app_init_update_status (NULL, NULL, 1.00); app_init_update_status (NULL, NULL, 1.00);
@ -635,6 +637,7 @@ app_exit_finish (void)
menus_quit (); menus_quit ();
tile_swap_exit (); tile_swap_exit ();
save_unitrc (); save_unitrc ();
gimp_parasiterc_save ();
/* Things to do only if there is an interface */ /* Things to do only if there is an interface */
if (no_interface == FALSE) if (no_interface == FALSE)

View File

@ -83,6 +83,8 @@ find_empty_segs (PixelRegion *maskPR,
int val, last; int val, last;
int tilex; int tilex;
Tile *tile = NULL; Tile *tile = NULL;
int endx, l_num_empty, dstep;
data = NULL; data = NULL;
start = 0; start = 0;
@ -121,7 +123,9 @@ find_empty_segs (PixelRegion *maskPR,
empty_segs[(*num_empty)++] = 0; empty_segs[(*num_empty)++] = 0;
last = -1; last = -1;
for (x = start; x < end; x++) l_num_empty = *num_empty;
for (x = start; x < end;)
{ {
/* Check to see if we must advance to next tile */ /* Check to see if we must advance to next tile */
if ((x / TILE_WIDTH) != tilex) if ((x / TILE_WIDTH) != tilex)
@ -132,22 +136,46 @@ find_empty_segs (PixelRegion *maskPR,
data = (unsigned char*)tile_data_pointer (tile, x % TILE_WIDTH, scanline % TILE_HEIGHT) + (tile_bpp(tile) - 1); data = (unsigned char*)tile_data_pointer (tile, x % TILE_WIDTH, scanline % TILE_HEIGHT) + (tile_bpp(tile) - 1);
tilex = x / TILE_WIDTH; tilex = x / TILE_WIDTH;
dstep = tile_bpp(tile);
}
endx = x + (TILE_WIDTH - (x%TILE_WIDTH));
endx = MINIMUM(end, endx);
if (type == IgnoreBounds && (endx > x1 || x < x2))
for (; x < endx; x++)
{
if (*data > HALF_WAY)
if (x >= x1 && x < x2)
val = -1;
else
val = 1;
else
val = -1;
data += dstep;
if (last != val)
empty_segs[l_num_empty++] = x;
last = val;
}
else
for (; x < endx; x++)
{
if (*data > HALF_WAY)
val = 1;
else
val = -1;
data += dstep;
if (last != val)
empty_segs[l_num_empty++] = x;
last = val;
} }
empty_segs[*num_empty] = x;
val = (*data > HALF_WAY) ? 1 : -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
data += tile_bpp(tile);
} }
*num_empty = l_num_empty;
if (last > 0) if (last > 0)
empty_segs[(*num_empty)++] = x; empty_segs[(*num_empty)++] = x;

View File

@ -160,6 +160,79 @@ gimp_lut_process (GimpLut *lut,
} }
} }
void
gimp_lut_process_inline (GimpLut *lut,
PixelRegion *srcPR)
{
int h, width, src_r_i;
unsigned char *src;
unsigned char *lut0 = NULL, *lut1 = NULL, *lut2 = NULL, *lut3 = NULL;
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;
width = srcPR->w;
src_r_i = srcPR->rowstride - (srcPR->bytes * srcPR->w);
if (src_r_i == 0)
{
width *= h;
h = 1;
}
while (h--)
{
switch (lut->nchannels)
{
case 1:
while (width--)
{
*src = lut0[*src];
src++;
}
break;
case 2:
while (width--)
{
src[0] = lut0[src[0]];
src[1] = lut1[src[1]];
src += 2;
}
break;
case 3:
while (width--)
{
src[0] = lut0[src[0]];
src[1] = lut1[src[1]];
src[2] = lut2[src[2]];
src += 3;
}
break;
case 4:
while (width--)
{
src[0] = lut0[src[0]];
src[1] = lut1[src[1]];
src[2] = lut2[src[2]];
src[3] = lut3[src[3]];
src += 4;
}
break;
default:
fprintf(stderr, "gimplut: Error: nchannels = %d\n", lut->nchannels);
}
width = srcPR->w;
src += src_r_i;
}
}
void void
gimp_lut_process_2 (PixelRegion *srcPR, gimp_lut_process_2 (PixelRegion *srcPR,
PixelRegion *destPR, PixelRegion *destPR,

View File

@ -49,6 +49,11 @@ void gimp_lut_process (GimpLut *lut,
PixelRegion *srcPR, PixelRegion *srcPR,
PixelRegion *destPR); PixelRegion *destPR);
/* gimp_lut_process_inline is like gimp_lut_process except it uses a
single PixelRegion as both the source and destination */
void gimp_lut_process_inline(GimpLut *lut,
PixelRegion *src_destPR);
/* gimp_lut_process_2 is the same as gimp_lut_process but the lut /* gimp_lut_process_2 is the same as gimp_lut_process but the lut
perameter is last instead of first. this is necesary because perameter is last instead of first. this is necesary because
pixel_region_process_paralell sends the user_data as the 1st pixel_region_process_paralell sends the user_data as the 1st

417
app/base/lut-funcs.c Normal file
View File

@ -0,0 +1,417 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "gimplut.h"
#include "gimphistogram.h"
#include <stdio.h>
#include <math.h>
#include <glib.h>
/* ---------- Brightness/Contrast -----------*/
typedef struct B_C_struct
{
double brightness;
double contrast;
} B_C_struct;
static float
brightness_contrast_lut_func(B_C_struct *data,
int nchannels, int channel, float value)
{
float nvalue;
double power;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (data->brightness < 0.0)
value = value * (1.0 + data->brightness);
else
value = value + ((1.0 - value) * data->brightness);
/* apply contrast */
if (data->contrast < 0.0)
{
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) (1.0 + data->contrast));
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
else
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
power = (data->contrast == 1.0) ? 127 : 1.0 / (1.0 - data->contrast);
nvalue = 0.5 * pow (2.0 * nvalue, power);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
return value;
}
void
brightness_contrast_lut_setup(GimpLut *lut, double brightness, double contrast,
int nchannels)
{
B_C_struct data;
data.brightness = brightness;
data.contrast = contrast;
gimp_lut_setup(lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) &data, nchannels);
}
GimpLut *
brightness_contrast_lut_new(double brightness, double contrast,
int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
brightness_contrast_lut_setup(lut, brightness, contrast, nchannels);
return lut;
}
/* ---------------- invert ------------------ */
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;
}
void
invert_lut_setup(GimpLut *lut, int nchannels)
{
gimp_lut_setup_exact(lut, (GimpLutFunc) invert_lut_func,
NULL , nchannels);
}
GimpLut *
invert_lut_new(int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
invert_lut_setup(lut, nchannels);
return lut;
}
/* ---------------- add (or subract)------------------ */
static float
add_lut_func(double *ammount,
int nchannels, int channel, float value)
{
/* don't change the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
return (value + *ammount);
}
void
add_lut_setup(GimpLut *lut, double ammount, int nchannels)
{
gimp_lut_setup(lut, (GimpLutFunc) add_lut_func,
(void *) &ammount , nchannels);
}
GimpLut *
add_lut_new(double ammount, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
add_lut_setup(lut, ammount, nchannels);
return lut;
}
/* ---------------- intersect (MINIMUM(pixel, value)) ------------------ */
static float
intersect_lut_func(double *min,
int nchannels, int channel, float value)
{
/* don't change the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
return MIN(value, *min);
}
void
intersect_lut_setup(GimpLut *lut, double value, int nchannels)
{
gimp_lut_setup_exact(lut, (GimpLutFunc) intersect_lut_func,
(void *) &value , nchannels);
}
GimpLut *
intersect_lut_new(double value, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
intersect_lut_setup(lut, value, nchannels);
return lut;
}
/* ---------------- Threshold ------------------ */
static float
threshold_lut_func(double *min,
int nchannels, int channel, float value)
{
/* don't change the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
if (value < *min)
return 0.0;
return 1.0;
}
void
threshold_lut_setup(GimpLut *lut, double value, int nchannels)
{
gimp_lut_setup_exact(lut, (GimpLutFunc) threshold_lut_func,
(void *) &value , nchannels);
}
GimpLut *
threshold_lut_new(double value, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
threshold_lut_setup(lut, value, nchannels);
return lut;
}
/* ------------- levels ------------ */
typedef struct
{
double *gamma;
int *low_input;
int *high_input;
int *low_output;
int *high_output;
} levels_struct;
static float
levels_lut_func(levels_struct *data,
int nchannels, int channel, float value)
{
double inten;
int j;
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;
/* determine input intensity */
if (data->high_input[j] != data->low_input[j])
inten = (double) (255.0*inten - data->low_input[j]) /
(double) (data->high_input[j] - data->low_input[j]);
else
inten = (double) (255.0*inten - data->low_input[j]);
if (data->gamma[j] != 0.0)
{
if (inten >= 0.0)
inten = pow ( inten, (1.0 / data->gamma[j]));
else
inten = -pow (-inten, (1.0 / data->gamma[j]));
}
/* determine the output intensity */
if (data->high_output[j] >= data->low_output[j])
inten = (double) (inten * (data->high_output[j] - data->low_output[j]) +
data->low_output[j]);
else if (data->high_output[j] < data->low_output[j])
inten = (double) (data->low_output[j] - inten *
(data->low_output[j] - data->high_output[j]));
inten /= 255.0;
}
return inten;
}
void
levels_lut_setup(GimpLut *lut, double *gamma, int *low_input, int *high_input,
int *low_output, int *high_output, int nchannels)
{
levels_struct data;
data.gamma = gamma;
data.low_input = low_input;
data.high_input = high_input;
data.low_output = low_output;
data.high_output = high_output;
gimp_lut_setup(lut, (GimpLutFunc) levels_lut_func,
(void *) &data, nchannels);
}
GimpLut *
levels_lut_new(double *gamma, int *low_input, int *high_input,
int *low_output, int *high_output, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
levels_lut_setup(lut, gamma, low_input, high_input,
low_output, high_output, nchannels);
return lut;
}
/* --------------- posterize ---------------- */
static float
posterize_lut_func(int *ilevels,
int nchannels, int channel, float value)
{
int levels;
/* don't posterize the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
if (*ilevels < 2)
levels = 2;
else
levels = *ilevels;
value = rint(value * (levels - 1.0)) / (levels - 1.0);
return value;
}
void
posterize_lut_setup(GimpLut *lut, int levels, int nchannels)
{
gimp_lut_setup_exact(lut, (GimpLutFunc) posterize_lut_func,
(void *) &levels , nchannels);
}
GimpLut *
posterize_lut_new(int levels, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
posterize_lut_setup(lut, levels, nchannels);
return lut;
}
/* --------------- equalize ------------- */
struct hist_lut_struct
{
GimpHistogram *histogram;
int part[5][257];
};
static float
equalize_lut_func(struct hist_lut_struct *hlut,
int nchannels, int channel, float value)
{
int i = 0, j;
j = (int)(value * 255.0 + 0.5);
while (hlut->part[channel][i + 1] <= j)
i++;
return i / 255.0;
}
void
eq_histogram_lut_setup (GimpLut *lut, GimpHistogram *hist, int bytes)
{
int i, k, j;
struct hist_lut_struct hlut;
double pixels_per_value;
double desired;
double sum, dif;
/* Find partition points */
pixels_per_value = gimp_histogram_get_count(hist, 0, 255) / 256.0;
for (k = 0; k < bytes; k++)
{
/* First and last points in partition */
hlut.part[k][0] = 0;
hlut.part[k][256] = 256;
/* Find intermediate points */
j = 0;
sum = gimp_histogram_get_channel(hist, k, 0) +
gimp_histogram_get_channel(hist, k, 1);
for (i = 1; i < 256; i++)
{
desired = i * pixels_per_value;
while (sum <= desired)
{
j++;
sum += gimp_histogram_get_channel(hist, k, j + 1);
}
/* Nearest sum */
dif = sum - gimp_histogram_get_channel(hist, k, j);
if ((sum - desired) > (dif / 2.0))
hlut.part[k][i] = j;
else
hlut.part[k][i] = j + 1;
}
}
gimp_lut_setup(lut, (GimpLutFunc) equalize_lut_func,
(void *) &hlut, bytes);
}
GimpLut *
eq_histogram_lut_new(GimpHistogram *h, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
eq_histogram_lut_setup(lut, h, nchannels);
return lut;
}

62
app/base/lut-funcs.h Normal file
View File

@ -0,0 +1,62 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __LUT_FUNCS_H__
#define __LUT_FUNCS_H__
#include "gimplutF.h"
#include "gimphistogramF.h"
/* brightness contrast */
void brightness_contrast_lut_setup (GimpLut *lut,
double brightness, double contrast,
int nchannels);
GimpLut *brightness_contrast_lut_new (double brightness, double contrast,
int nchannels);
/* invert */
void invert_lut_setup (GimpLut *lut, int nchannels);
GimpLut *invert_lut_new (int nchannels);
/* add (or subtract) */
void add_lut_setup (GimpLut *lut, double ammount, int nchannels);
GimpLut *add_lut_new (double ammount, int nchannels);
/* intersect (MINIMUM(pixel, value)) */
void intersect_lut_setup (GimpLut *lut, double value, int nchannels);
GimpLut *intersect_lut_new (double value, int nchannels);
/* threshold */
void threshold_lut_setup (GimpLut *lut, double value, int nchannels);
GimpLut *threshold_lut_new (double value, int nchannels);
/* levels */
void levels_lut_setup (GimpLut *lut, double *gamma,
int *low_input, int *high_input,
int *low_output, int *high_output, int nchannels);
GimpLut *levels_lut_new (double *gamma, int *low_input, int *high_input,
int *low_output, int *high_output, int nchannels);
/* posterize */
void posterize_lut_setup (GimpLut *lut, int levels, int nchannels);
GimpLut *posterize_lut_new (int levels, int nchannels);
/* equalize histogram */
void eq_histogram_lut_setup (GimpLut *lut, GimpHistogram *hist, int bytes);
GimpLut *eq_histogram_lut_new (GimpHistogram *h, int nchannels);
#endif /* __LUT_FUNCS_H__ */

292
app/base/pixel-processor.c Normal file
View File

@ -0,0 +1,292 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* pixel_processor.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 "../config.h"
#include "pixel_processor.h"
#include "pixel_region.h"
#include "gimprc.h"
#include <stdarg.h>
#include <stdio.h>
#ifdef ENABLE_MP
#include <pthread.h>
#define IF_THREAD(statement) statement
#else /* !USE_PTHREADS */
#define IF_THREAD(statement)
#endif /* !USE_PTHREADS */
typedef void (*p1_func)(void *, PixelRegion *);
typedef void (*p2_func)(void *, PixelRegion * ,PixelRegion *);
typedef void (*p3_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *);
typedef void (*p4_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *,
PixelRegion *);
typedef struct _PixelRegionIterator PixelRegionIterator;
struct _PixelProcessor
{
void *data;
p_func f;
PixelRegionIterator *PRI;
IF_THREAD(pthread_mutex_t mutex;)
int nthreads;
int n_regions;
PixelRegion *r[4];
void *progress_report_data;
ProgressReportFunc progress_report_func;
};
static void *
do_parallel_regions(PixelProcessor *p_s)
{
PixelRegion tr[4];
int ntiles = 0;
int i;
int cont = 1;
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
if (p_s->nthreads != 0 && p_s->PRI)
p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI);
if (p_s->PRI == NULL)
{
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
p_s->nthreads++;
do
{
for (i = 0; i < p_s->n_regions; i++)
if (p_s->r[i])
memcpy(&tr[i], p_s->r[i], sizeof(PixelRegion));
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
ntiles++;
switch(p_s->n_regions)
{
case 1:
((p1_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL);
break;
case 2:
((p2_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL);
break;
case 3:
((p3_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL);
break;
case 4:
((p4_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL,
p_s->r[3] ? &tr[3] : NULL);
break;
default:
g_message("do_parallel_regions: Bad number of regions %d\n",
p_s->n_regions);
}
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
if (p_s->progress_report_func)
if (!p_s->progress_report_func(p_s->progress_report_data,
p_s->r[0]->x, p_s->r[0]->y,
p_s->r[0]->w, p_s->r[0]->h))
cont = 0;
} while (cont && p_s->PRI &&
(p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI)));
p_s->nthreads--;
/* fprintf(stderr, "processed %d tiles\n", ntiles); */
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
#define MAX_THREADS 30
static void
pixel_regions_do_parallel(PixelProcessor *p_s)
{
int i;
IF_THREAD(int nthreads;)
IF_THREAD(pthread_t threads[MAX_THREADS];)
IF_THREAD(pthread_attr_t pthread_attr;)
/* (p_s->PRI->region_width * p_s->PRI->region_height) /(64*64)); */
IF_THREAD(
nthreads = MIN(num_processors, 5);
if (nthreads > 1)
{
pthread_attr_init (&pthread_attr);
for (i = 0; i < nthreads; i++)
{
pthread_create (&threads[i], &pthread_attr,
(void *(*)(void *)) do_parallel_regions,
p_s);
}
for (i = 0; i < nthreads; i++)
{
pthread_join(threads[i], NULL);
}
}
else
)
do_parallel_regions(p_s);
if (p_s->nthreads != 0)
fprintf(stderr, "Ack, we lost a thread\n");
}
static PixelProcessor *
pixel_regions_real_process_parallel(p_func f, void *data,
ProgressReportFunc report_func,
void *report_data,
int num_regions, va_list ap)
{
int i;
PixelProcessor *p_s;
p_s = g_new(PixelProcessor, 200);
for (i = 0; i < num_regions; i++)
p_s->r[i] = va_arg (ap, PixelRegion *);
switch(num_regions)
{
case 1:
p_s->PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s->r[0]);
break;
case 2:
p_s->PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s->r[0],
p_s->r[1]);
break;
case 3:
p_s->PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s->r[0],
p_s->r[1],
p_s->r[2]);
break;
case 4:
p_s->PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s->r[0],
p_s->r[1],
p_s->r[2],
p_s->r[3]);
break;
default:
g_message("pixel_regions_real_process_parallel: Bad number of regions %d\n",
p_s->n_regions);
}
if (!p_s->PRI)
{
pixel_processor_free(p_s);
return NULL;
}
p_s->f = f;
p_s->data = data;
p_s->n_regions = num_regions;
IF_THREAD(pthread_mutex_init(&(p_s->mutex), NULL);)
p_s->nthreads = 0;
p_s->progress_report_data = report_data;
p_s->progress_report_func = report_func;
pixel_regions_do_parallel(p_s);
if (p_s->PRI)
return p_s;
pixel_processor_free (p_s);
return NULL;
}
void
pixel_regions_process_parallel(p_func f, void *data, int num_regions, ...)
{
va_list va;
va_start (va, num_regions);
pixel_regions_real_process_parallel(f, data, NULL, NULL, num_regions, va);
va_end (va);
}
PixelProcessor *
pixel_regions_process_parallel_progress(p_func f, void *data,
ProgressReportFunc progress_func,
void *progress_data, int num_regions,
...)
{
PixelProcessor *ret;
va_list va;
va_start (va, num_regions);
ret = pixel_regions_real_process_parallel(f, data,
progress_func, progress_data,
num_regions, va);
va_end (va);
return ret;
}
void
pixel_processor_stop(PixelProcessor *pp)
{
if (!pp)
return;
if (pp->PRI)
{
pixel_regions_process_stop (pp->PRI);
pp->PRI = NULL;
}
pixel_processor_free(pp);
}
PixelProcessor *
pixel_processor_cont(PixelProcessor *pp)
{
pixel_regions_do_parallel(pp);
if (pp->PRI)
return pp;
pixel_processor_free (pp);
return NULL;
}
void
pixel_processor_free (PixelProcessor *pp)
{
if (pp->PRI)
pixel_processor_stop(pp);
else
g_free(pp);
}

View File

@ -0,0 +1,40 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* pixel_processor.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 __PIXEL_PROCESSOR_H__
#define __PIXEL_PROCESSOR_H__
typedef struct _PixelProcessor PixelProcessor;
typedef void (*p_func)(void);
typedef int (*ProgressReportFunc)(void *, int, int, int, int);
void pixel_regions_process_parallel (p_func f, void *data, int num_regions,
...);
PixelProcessor *pixel_process_progress (p_func f, void *data,
ProgressReportFunc progress_func,
void *progress_data,
int num_regions, ...);
void pixel_processor_free (PixelProcessor *);
void pixel_processor_stop (PixelProcessor *);
PixelProcessor *pixel_processor_cont (PixelProcessor *);
#endif /* __PIXEL_PROCESSOR_H__ */

View File

@ -26,18 +26,6 @@
#include "tile_manager_pvt.h" #include "tile_manager_pvt.h"
#include "tile.h" /* ick. */ #include "tile.h" /* ick. */
#ifdef ENABLE_MP
#include <pthread.h>
#define IF_THREAD(statement) statement
#else /* !USE_PTHREADS */
#define IF_THREAD(statement)
#endif /* !USE_PTHREADS */
typedef struct _PixelRegionHolder PixelRegionHolder; typedef struct _PixelRegionHolder PixelRegionHolder;
@ -303,159 +291,6 @@ pixel_region_set_col (PR, x, y, h, data)
} }
} }
typedef void (*p1_func)(void *, PixelRegion *);
typedef void (*p2_func)(void *, PixelRegion * ,PixelRegion *);
typedef void (*p3_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *);
typedef void (*p4_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *,
PixelRegion *);
struct parallel_struct
{
void *data;
p_func f;
PixelRegionIterator *PRI;
IF_THREAD(pthread_mutex_t mutex;)
int nthreads;
int n_regions;
PixelRegion *r[4];
};
static void *
do_parallel_regions(struct parallel_struct *p_s)
{
PixelRegion tr[4];
int ntiles = 0;
int i;
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
if (p_s->nthreads != 0 && p_s->PRI)
p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI);
if (p_s->PRI == NULL)
{
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
p_s->nthreads++;
do
{
for (i = 0; i < p_s->n_regions; i++)
if (p_s->r[i])
memcpy(&tr[i], p_s->r[i], sizeof(PixelRegion));
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
ntiles++;
switch(p_s->n_regions)
{
case 1:
((p1_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL);
break;
case 2:
((p2_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL);
break;
case 3:
((p3_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL);
break;
case 4:
((p4_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL,
p_s->r[3] ? &tr[3] : NULL);
break;
default:
g_message("do_parallel_regions: Bad number of regions %d\n",
p_s->n_regions);
}
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
} while (p_s->PRI && (p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI)));
p_s->nthreads--;
/* fprintf(stderr, "processed %d tiles\n", ntiles); */
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
#define MAX_THREADS 30
void pixel_regions_process_parallel(p_func f, void *data, int num_regions, ...)
{
int i;
struct parallel_struct p_s;
IF_THREAD(pthread_t threads[MAX_THREADS];)
IF_THREAD(pthread_attr_t pthread_attr;)
IF_THREAD(int nthreads;)
va_list ap;
va_start (ap, num_regions);
for (i = 0; i < num_regions; i++)
p_s.r[i] = va_arg (ap, PixelRegion *);
va_end (ap);
switch(num_regions)
{
case 1:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0]);
break;
case 2:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1]);
break;
case 3:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1],
p_s.r[2]);
break;
case 4:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1],
p_s.r[2],
p_s.r[3]);
break;
default:
g_message("pixel_regions_process_parallel: Bad number of regions %d\n",
p_s.n_regions);
}
if (!p_s.PRI)
return;
p_s.f = f;
p_s.data = data;
p_s.n_regions = num_regions;
IF_THREAD(pthread_mutex_init(&p_s.mutex, NULL);)
p_s.nthreads = 0;
IF_THREAD(
nthreads = MIN(num_processors,
(p_s.PRI->region_width * p_s.PRI->region_height) /(64*64));
if (nthreads > 1)
{
pthread_attr_init (&pthread_attr);
for (i = 0; i < nthreads; i++)
{
pthread_create (&threads[i], &pthread_attr,
(void *(*)(void *)) do_parallel_regions,
&p_s);
}
for (i = 0; i < nthreads; i++)
{
pthread_join(threads[i], NULL);
}
}
else
)
do_parallel_regions(&p_s);
if (p_s.nthreads != 0)
fprintf(stderr, "Ack, we've lost a thread.");
}
void * void *
pixel_regions_register (int num_regions, ...) pixel_regions_register (int num_regions, ...)
{ {

View File

@ -19,6 +19,7 @@
#define __PIXEL_REGION_H__ #define __PIXEL_REGION_H__
#include "tile_manager.h" #include "tile_manager.h"
#include "pixel_processor.h" /* this is temporary, */
typedef struct _PixelRegion PixelRegion; typedef struct _PixelRegion PixelRegion;
@ -36,7 +37,6 @@ struct _PixelRegion
int process_count; /* used internally */ int process_count; /* used internally */
}; };
typedef void (*p_func)(void);
/* PixelRegion functions */ /* PixelRegion functions */
void pixel_region_init (PixelRegion *, TileManager *, int, int, int, int, int); void pixel_region_init (PixelRegion *, TileManager *, int, int, int, int, int);
@ -48,8 +48,6 @@ void pixel_region_set_row (PixelRegion *, int, int, int, unsigned char *)
void pixel_region_get_col (PixelRegion *, int, int, int, unsigned char *, int); void pixel_region_get_col (PixelRegion *, int, int, int, unsigned char *, int);
void pixel_region_set_col (PixelRegion *, int, int, int, unsigned char *); void pixel_region_set_col (PixelRegion *, int, int, int, unsigned char *);
void *pixel_regions_register (int, ...); void *pixel_regions_register (int, ...);
void pixel_regions_process_parallel (p_func f, void *data, int num_regions,
...);
void *pixel_regions_process (void *); void *pixel_regions_process (void *);
void pixel_regions_process_stop (void *); void pixel_regions_process_stop (void *);

View File

@ -83,6 +83,8 @@ find_empty_segs (PixelRegion *maskPR,
int val, last; int val, last;
int tilex; int tilex;
Tile *tile = NULL; Tile *tile = NULL;
int endx, l_num_empty, dstep;
data = NULL; data = NULL;
start = 0; start = 0;
@ -121,7 +123,9 @@ find_empty_segs (PixelRegion *maskPR,
empty_segs[(*num_empty)++] = 0; empty_segs[(*num_empty)++] = 0;
last = -1; last = -1;
for (x = start; x < end; x++) l_num_empty = *num_empty;
for (x = start; x < end;)
{ {
/* Check to see if we must advance to next tile */ /* Check to see if we must advance to next tile */
if ((x / TILE_WIDTH) != tilex) if ((x / TILE_WIDTH) != tilex)
@ -132,22 +136,46 @@ find_empty_segs (PixelRegion *maskPR,
data = (unsigned char*)tile_data_pointer (tile, x % TILE_WIDTH, scanline % TILE_HEIGHT) + (tile_bpp(tile) - 1); data = (unsigned char*)tile_data_pointer (tile, x % TILE_WIDTH, scanline % TILE_HEIGHT) + (tile_bpp(tile) - 1);
tilex = x / TILE_WIDTH; tilex = x / TILE_WIDTH;
dstep = tile_bpp(tile);
}
endx = x + (TILE_WIDTH - (x%TILE_WIDTH));
endx = MINIMUM(end, endx);
if (type == IgnoreBounds && (endx > x1 || x < x2))
for (; x < endx; x++)
{
if (*data > HALF_WAY)
if (x >= x1 && x < x2)
val = -1;
else
val = 1;
else
val = -1;
data += dstep;
if (last != val)
empty_segs[l_num_empty++] = x;
last = val;
}
else
for (; x < endx; x++)
{
if (*data > HALF_WAY)
val = 1;
else
val = -1;
data += dstep;
if (last != val)
empty_segs[l_num_empty++] = x;
last = val;
} }
empty_segs[*num_empty] = x;
val = (*data > HALF_WAY) ? 1 : -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
data += tile_bpp(tile);
} }
*num_empty = l_num_empty;
if (last > 0) if (last > 0)
empty_segs[(*num_empty)++] = x; empty_segs[(*num_empty)++] = x;

View File

@ -28,6 +28,7 @@
#include "image_map.h" #include "image_map.h"
#include "interface.h" #include "interface.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -94,59 +95,6 @@ static void brightness_contrast_contrast_text_update (GtkWidget *, gpointer
static void *brightness_contrast_options = NULL; static void *brightness_contrast_options = NULL;
static BrightnessContrastDialog *brightness_contrast_dialog = NULL; static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
static Argument * brightness_contrast_invoker (Argument *);
/* brightness contrast machinery */
static float
brightness_contrast_lut_func(BrightnessContrastDialog *bcd,
int nchannels, int channel, float value)
{
float nvalue;
double power;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (bcd->brightness < 0)
value = value * (1.0 + bcd->brightness/255.0);
else
value = value + ((1.0 - value) * bcd->brightness/255.0);
/* apply contrast */
if (bcd->contrast < 0)
{
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
{
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;
}
/* by_color select action functions */ /* by_color select action functions */
@ -467,8 +415,9 @@ brightness_contrast_preview (BrightnessContrastDialog *bcd)
if (!bcd->image_map) if (!bcd->image_map)
g_message (_("brightness_contrast_preview(): No image map")); g_message (_("brightness_contrast_preview(): No image map"));
active_tool->preserve = TRUE; active_tool->preserve = TRUE;
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func, brightness_contrast_lut_setup(bcd->lut, bcd->brightness / 255.0,
(void *) bcd, gimp_drawable_bytes(bcd->drawable)); bcd->contrast / 127.0,
gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut); (void *) bcd->lut);
active_tool->preserve = FALSE; active_tool->preserve = FALSE;
@ -489,8 +438,9 @@ brightness_contrast_ok_callback (GtkWidget *widget,
if (!bcd->preview) if (!bcd->preview)
{ {
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func, brightness_contrast_lut_setup(bcd->lut, bcd->brightness / 255.0,
(void *) bcd, gimp_drawable_bytes(bcd->drawable)); bcd->contrast / 127.0,
gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut); (void *) bcd->lut);
} }
@ -632,119 +582,3 @@ brightness_contrast_contrast_text_update (GtkWidget *w,
} }
/* The brightness_contrast procedure definition */
ProcArg brightness_contrast_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"brightness",
"brightness adjustment: (-127 <= brightness <= 127)"
},
{ PDB_INT32,
"contrast",
"constrast adjustment: (-127 <= contrast <= 127)"
}
};
ProcRecord brightness_contrast_proc =
{
"gimp_brightness_contrast",
"Modify brightness/contrast in the specified drawable",
"This procedures allows the brightness and contrast of the specified drawable to be modified. Both 'brightness' and 'contrast' parameters are defined between -127 and 127.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997",
PDB_INTERNAL,
/* Input arguments */
3,
brightness_contrast_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { brightness_contrast_invoker } },
};
static Argument *
brightness_contrast_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
int int_value;
BrightnessContrastDialog bcd;
GImage *gimage;
int brightness;
int contrast;
int x1, y1, x2, y2;
GimpDrawable *drawable;
drawable = NULL;
brightness = 0;
contrast = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
else
gimage = drawable_gimage (drawable);
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* brightness */
if (success)
{
int_value = args[1].value.pdb_int;
if (int_value < -127 || int_value > 127)
success = FALSE;
else
brightness = int_value;
}
/* contrast */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value < -127 || int_value > 127)
success = FALSE;
else
contrast = int_value;
}
/* arrange to modify the brightness/contrast */
if (success)
{
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);
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);
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));
}
return procedural_db_return_args (&brightness_contrast_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __BRIGHTNESS_CONTRAST_H__ #define __BRIGHTNESS_CONTRAST_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* by_color select functions */ /* by_color select functions */
Tool * tools_new_brightness_contrast (void); Tool * tools_new_brightness_contrast (void);
@ -27,7 +26,4 @@ void tools_free_brightness_contrast (Tool *);
void brightness_contrast_initialize (GDisplay *); void brightness_contrast_initialize (GDisplay *);
/* Procedure definition and marshalling function */
extern ProcRecord brightness_contrast_proc;
#endif /* __BRIGHTNESS_CONTRAST_H__ */ #endif /* __BRIGHTNESS_CONTRAST_H__ */

View File

@ -36,6 +36,9 @@
#include "channel_pvt.h" #include "channel_pvt.h"
#include "tile.h" #include "tile.h"
#include "gimplut.h"
#include "lut_funcs.h"
/* /*
enum { enum {
LAST_SIGNAL LAST_SIGNAL
@ -602,9 +605,9 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
unsigned char * data; unsigned char * data;
int x, y; int x, y;
int ex, ey; int ex, ey;
int found;
void *pr; void *pr;
int tx1, tx2, ty1, ty2;
int minx, maxx;
/* if the mask's bounds have already been reliably calculated... */ /* if the mask's bounds have already been reliably calculated... */
if (mask->bounds_known) if (mask->bounds_known)
{ {
@ -617,10 +620,10 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
} }
/* go through and calculate the bounds */ /* go through and calculate the bounds */
*x1 = GIMP_DRAWABLE(mask)->width; tx1 = GIMP_DRAWABLE(mask)->width;
*y1 = GIMP_DRAWABLE(mask)->height; ty1 = GIMP_DRAWABLE(mask)->height;
*x2 = 0; tx2 = 0;
*y2 = 0; ty2 = 0;
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, FALSE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, FALSE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr)) for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
@ -630,36 +633,50 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
ey = maskPR.y + maskPR.h; ey = maskPR.y + maskPR.h;
/* only check the pixels if this tile is not fully within the currently /* only check the pixels if this tile is not fully within the currently
computed bounds */ computed bounds */
if (maskPR.x < *x1 || ex > *x2 || if (maskPR.x < tx1 || ex > tx2 ||
maskPR.y < *y1 || ey > *y2) maskPR.y < ty1 || ey > ty2)
{ {
for (y = maskPR.y; y < ey; y++) /* Check upper left and lower right corners to see if we can
avoid checking the rest of the pixels in this tile */
if (data[0] && data[maskPR.rowstride*(maskPR.h - 1) + maskPR.w - 1])
{
if (maskPR.x < tx1)
tx1 = maskPR.x;
if (ex > tx2)
tx2 = ex;
if (maskPR.y < ty1)
ty1 = maskPR.y;
if (ey > ty2)
ty2 = ey;
}
else
for (y = maskPR.y; y < ey; y++)
{ {
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++) for (x = maskPR.x; x < ex; x++, data++)
if (*data) if (*data)
{ {
if (x < *x1) minx = x;
*x1 = x; maxx = x;
if (x > *x2) for (; x < ex; x++, data++)
*x2 = x; if (*data)
found = TRUE; maxx = x;
} if (minx < tx1)
if (found) tx1 = minx;
{ if (maxx > tx2)
if (y < *y1) tx2 = maxx;
*y1 = y; if (y < ty1)
if (y > *y2) ty1 = y;
*y2 = y; if (y > ty2)
} ty2 = y;
}
} }
} }
} }
*x2 = BOUNDS (*x2 + 1, 0, GIMP_DRAWABLE(mask)->width); tx2 = BOUNDS (tx2 + 1, 0, GIMP_DRAWABLE(mask)->width);
*y2 = BOUNDS (*y2 + 1, 0, GIMP_DRAWABLE(mask)->height); ty2 = BOUNDS (ty2 + 1, 0, GIMP_DRAWABLE(mask)->height);
if (*x1 == GIMP_DRAWABLE(mask)->width && *y1 == GIMP_DRAWABLE(mask)->height) if (tx1 == GIMP_DRAWABLE(mask)->width && ty1 == GIMP_DRAWABLE(mask)->height)
{ {
mask->empty = TRUE; mask->empty = TRUE;
mask->x1 = 0; mask->y1 = 0; mask->x1 = 0; mask->y1 = 0;
@ -669,13 +686,18 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
else else
{ {
mask->empty = FALSE; mask->empty = FALSE;
mask->x1 = *x1; mask->x1 = tx1;
mask->y1 = *y1; mask->y1 = ty1;
mask->x2 = *x2; mask->x2 = tx2;
mask->y2 = *y2; mask->y2 = ty2;
} }
mask->bounds_known = TRUE; mask->bounds_known = TRUE;
*x1 = tx1;
*x2 = tx2;
*y1 = ty1;
*y2 = ty2;
return (mask->empty) ? FALSE : TRUE; return (mask->empty) ? FALSE : TRUE;
} }
@ -800,61 +822,31 @@ channel_sub_segment (Channel *mask, int x, int y, int width, int value)
} }
void
channel_inter_segment (Channel *mask, int x, int y, int width, int value)
{
PixelRegion maskPR;
unsigned char *data;
int val;
int x2;
void * pr;
/* check horizontal extents... */
x2 = x + width;
if (x2 < 0) x2 = 0;
if (x2 > GIMP_DRAWABLE(mask)->width) x2 = GIMP_DRAWABLE(mask)->width;
if (x < 0) x = 0;
if (x > GIMP_DRAWABLE(mask)->width) x = GIMP_DRAWABLE(mask)->width;
width = x2 - x;
if (!width) return;
if (y < 0 || y > GIMP_DRAWABLE(mask)->height)
return;
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, x, y, width, 1, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{
data = maskPR.data;
width = maskPR.w;
while (width--)
{
val = MINIMUM(*data, value);
*data++ = val;
}
}
}
void void
channel_combine_rect (Channel *mask, int op, int x, int y, int w, int h) channel_combine_rect (Channel *mask, int op, int x, int y, int w, int h)
{ {
int i; int i;
int x2, y2;
PixelRegion maskPR;
unsigned char color;
y2 = y + h;
x2 = x + w;
for (i = y; i < y + h; i++) x = BOUNDS (x, 0, GIMP_DRAWABLE(mask)->width);
{ y = BOUNDS (y, 0, GIMP_DRAWABLE(mask)->height);
if (i >= 0 && i < GIMP_DRAWABLE(mask)->height) x2 = BOUNDS (x2, 0, GIMP_DRAWABLE(mask)->width);
switch (op) y2 = BOUNDS (y2, 0, GIMP_DRAWABLE(mask)->height);
{
case ADD: case REPLACE: if (x2 - x <= 0 || y2 - y <= 0)
channel_add_segment (mask, x, i, w, 255); return;
break;
case SUB: pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, x, y,
channel_sub_segment (mask, x, i, w, 255); x2 - x, y2 - y, TRUE);
break; if (op == ADD || op == REPLACE)
case INTERSECT: color = 255;
channel_inter_segment (mask, x, i, w, 255); else
break; color = 0;
} color_region(&maskPR, &color);
}
/* Determine new boundary */ /* Determine new boundary */
if (mask->bounds_known && (op == ADD) && !mask->empty) if (mask->bounds_known && (op == ADD) && !mask->empty)
@ -933,9 +925,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
case SUB : case SUB :
channel_sub_segment (mask, x1, i, (x2 - x1), 255); channel_sub_segment (mask, x1, i, (x2 - x1), 255);
break; break;
case INTERSECT:
channel_inter_segment (mask, x1, i, (x2 - x1), 255);
break;
} }
} }
/* antialiasing */ /* antialiasing */
@ -965,7 +954,7 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
val = (int) (255 * (1 - (dist + 0.5))); val = (int) (255 * (1 - (dist + 0.5)));
else else
val = 0; val = 0;
if (last != val && last) if (last != val && last)
{ {
switch (op) switch (op)
@ -976,8 +965,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
case SUB: case SUB:
channel_sub_segment (mask, x0, i, j - x0, last); channel_sub_segment (mask, x0, i, j - x0, last);
break; break;
case INTERSECT:
channel_inter_segment (mask, x0, i, j - x0, last);
} }
} }
@ -985,6 +972,10 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
{ {
x0 = j; x0 = j;
last = val; last = val;
/* because we are symetric accross the y axis we can
skip ahead a bit if we are inside the ellipse*/
if (val == 255 && j < cx)
j = cx + (cx - j) - 1;
} }
} }
@ -994,8 +985,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
channel_add_segment (mask, x0, i, j - x0, last); channel_add_segment (mask, x0, i, j - x0, last);
else if (op == SUB) else if (op == SUB)
channel_sub_segment (mask, x0, i, j - x0, last); channel_sub_segment (mask, x0, i, j - x0, last);
else if (op == INTERSECT)
channel_inter_segment (mask, x0, i, j - x0, last);
} }
} }
@ -1032,18 +1021,81 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
} }
static void
channel_combine_sub_region_add (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y, val;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
val = dest[x] + src[x];
if (val > 255)
dest[x] = 255;
else
dest[x] = val;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
static void
channel_combine_sub_region_sub (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
if (src[x] > dest[x])
dest[x] = 0;
else
dest[x]-= src[x];
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
static void
channel_combine_sub_region_intersect (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
dest[x] = MINIMUM(dest[x], src[x]);
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
void void
channel_combine_mask (Channel *mask, Channel *add_on, int op, channel_combine_mask (Channel *mask, Channel *add_on, int op,
int off_x, int off_y) int off_x, int off_y)
{ {
PixelRegion srcPR, destPR; PixelRegion srcPR, destPR;
unsigned char *src;
unsigned char *dest;
int val;
int x1, y1, x2, y2; int x1, y1, x2, y2;
int x, y;
int w, h; int w, h;
void * pr;
x1 = BOUNDS (off_x, 0, GIMP_DRAWABLE(mask)->width); x1 = BOUNDS (off_x, 0, GIMP_DRAWABLE(mask)->width);
y1 = BOUNDS (off_y, 0, GIMP_DRAWABLE(mask)->height); y1 = BOUNDS (off_y, 0, GIMP_DRAWABLE(mask)->height);
@ -1056,39 +1108,25 @@ channel_combine_mask (Channel *mask, Channel *add_on, int op,
pixel_region_init (&srcPR, GIMP_DRAWABLE(add_on)->tiles, (x1 - off_x), (y1 - off_y), w, h, FALSE); pixel_region_init (&srcPR, GIMP_DRAWABLE(add_on)->tiles, (x1 - off_x), (y1 - off_y), w, h, FALSE);
pixel_region_init (&destPR, GIMP_DRAWABLE(mask)->tiles, x1, y1, w, h, TRUE); pixel_region_init (&destPR, GIMP_DRAWABLE(mask)->tiles, x1, y1, w, h, TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) switch (op)
{ {
src = srcPR.data; case ADD: case REPLACE:
dest = destPR.data; pixel_regions_process_parallel ((p_func)channel_combine_sub_region_add,
NULL, 2, &srcPR, &destPR);
for (y = 0; y < srcPR.h; y++) break;
{ case SUB:
for (x = 0; x < srcPR.w; x++) pixel_regions_process_parallel ((p_func)channel_combine_sub_region_sub,
{ NULL, 2, &srcPR, &destPR);
switch (op) break;
{ case INTERSECT:
case ADD: case REPLACE: pixel_regions_process_parallel ((p_func)
val = dest[x] + src[x]; channel_combine_sub_region_intersect,
if (val > 255) val = 255; NULL, 2, &srcPR, &destPR);
break; break;
case SUB: default:
val = dest[x] - src[x]; g_message("Error: unknown opperation type in channel_combine_mask\n");
if (val < 0) val = 0; break;
break; }
case INTERSECT:
val = MINIMUM(dest[x], src[x]);
break;
default:
val = 0;
break;
}
dest[x] = val;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
}
mask->bounds_known = FALSE; mask->bounds_known = FALSE;
} }
@ -1184,57 +1222,35 @@ void
channel_invert (Channel *mask) channel_invert (Channel *mask)
{ {
PixelRegion maskPR; PixelRegion maskPR;
unsigned char *data; GimpLut *lut;
int size;
void * pr;
/* push the current channel onto the undo stack */ /* push the current channel onto the undo stack */
channel_push_undo (mask); channel_push_undo (mask);
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{ lut = invert_lut_new(1);
/* subtract each pixel in the mask from 255 */
data = maskPR.data;
size = maskPR.w * maskPR.h;
while (size --)
{
*data = 255 - *data;
data++;
}
}
pixel_regions_process_parallel ((p_func)gimp_lut_process_inline,
lut, 1, &maskPR);
gimp_lut_free(lut);
mask->bounds_known = FALSE; mask->bounds_known = FALSE;
} }
void void
channel_sharpen (Channel *mask) channel_sharpen (Channel *mask)
{ {
PixelRegion maskPR; PixelRegion maskPR;
unsigned char *data; GimpLut *lut;
int size;
void * pr;
/* push the current channel onto the undo stack */ /* push the current channel onto the undo stack */
channel_push_undo (mask); channel_push_undo (mask);
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr)) lut = threshold_lut_new(0.5, 1);
{
/* if a pixel in the mask has a non-zero value, make it 255 */
data = maskPR.data;
size = maskPR.w * maskPR.h;
while (size--)
{
if (*data > HALF_WAY)
*data++ = 255;
else
*data++ = 0;
}
}
mask->bounds_known = FALSE; pixel_regions_process_parallel ((p_func)gimp_lut_process_inline,
lut, 1, &maskPR);
gimp_lut_free(lut);
} }

457
app/color_cmds.c Normal file
View File

@ -0,0 +1,457 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "color_cmds.h"
#include "gimpimage.h"
#include "gimpdrawable.h"
#include "gimplut.h"
#include "lut_funcs.h"
static Argument * brightness_contrast_invoker (Argument *);
static Argument * levels_invoker (Argument *);
static Argument * posterize_invoker (Argument *);
/* ------------------------------------------------------------------ */
/* --------- The brightness_contrast procedure definition ---------- */
/* ------------------------------------------------------------------ */
ProcArg brightness_contrast_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"brightness",
"brightness adjustment: (-127 <= brightness <= 127)"
},
{ PDB_INT32,
"contrast",
"constrast adjustment: (-127 <= contrast <= 127)"
}
};
ProcRecord brightness_contrast_proc =
{
"gimp_brightness_contrast",
"Modify brightness/contrast in the specified drawable",
"This procedures allows the brightness and contrast of the specified drawable to be modified. Both 'brightness' and 'contrast' parameters are defined between -127 and 127.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997",
PDB_INTERNAL,
/* Input arguments */
3,
brightness_contrast_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { brightness_contrast_invoker } },
};
static Argument *
brightness_contrast_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
int int_value;
GimpImage *gimage;
int brightness;
int contrast;
int x1, y1, x2, y2;
GimpDrawable *drawable;
drawable = NULL;
brightness = 0;
contrast = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = gimp_drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
else
gimage = gimp_drawable_gimage (drawable);
}
/* make sure the drawable is not indexed color */
if (success)
success = ! gimp_drawable_indexed (drawable);
/* brightness */
if (success)
{
int_value = args[1].value.pdb_int;
if (int_value < -127 || int_value > 127)
success = FALSE;
else
brightness = int_value;
}
/* contrast */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value < -127 || int_value > 127)
success = FALSE;
else
contrast = int_value;
}
/* arrange to modify the brightness/contrast */
if (success)
{
GimpLut *lut;
lut = brightness_contrast_lut_new(brightness / 255.0, contrast / 127.0,
gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, gimp_drawable_data (drawable),
x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
pixel_regions_process_parallel((p_func)gimp_lut_process, lut,
2, &srcPR, &destPR);
gimp_lut_free(lut);
gimp_drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
return procedural_db_return_args (&brightness_contrast_proc, success);
}
/* ------------------------------------------------------------------ */
/* ---------------- The levels procedure definition ----------------- */
/* ------------------------------------------------------------------ */
ProcArg levels_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"channel",
"the channel to modify: { VALUE (0), RED (1), GREEN (2), BLUE (3), GRAY (0) }"
},
{ PDB_INT32,
"low_input",
"intensity of lowest input: (0 <= low_input <= 255)"
},
{ PDB_INT32,
"high_input",
"intensity of highest input: (0 <= high_input <= 255)"
},
{ PDB_FLOAT,
"gamma",
"gamma correction factor: (0.1 <= gamma <= 10)"
},
{ PDB_INT32,
"low_output",
"intensity of lowest output: (0 <= low_input <= 255)"
},
{ PDB_INT32,
"high_output",
"intensity of highest output: (0 <= high_input <= 255)"
}
};
ProcRecord levels_proc =
{
"gimp_levels",
"Modifies intensity levels in the specified drawable",
"This tool allows intensity levels in the specified drawable to be remapped according to a set of parameters. The low/high input levels specify an initial mapping from the source intensities. The gamma value determines how intensities between the low and high input intensities are interpolated. A gamma value of 1.0 results in a linear interpolation. Higher gamma values result in more high-level intensities. Lower gamma values result in more low-level intensities. The low/high output levels constrain the final intensity mapping--that is, no final intensity will be lower than the low output level and no final intensity will be higher than the high output level. This tool is only valid on RGB color and grayscale images. It will not operate on indexed drawables.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1995-1996",
PDB_INTERNAL,
/* Input arguments */
7,
levels_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { levels_invoker } },
};
static Argument *
levels_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
GimpDrawable *drawable;
int channel;
int low_inputv;
int high_inputv;
double gammav;
int low_outputv;
int high_outputv;
int int_value;
double fp_value;
int x1, y1, x2, y2;
int i;
int low_input[5];
double gamma[5];
int high_input[5];
int low_output[5];
int high_output[5];
drawable = NULL;
low_inputv = 0;
high_inputv = 0;
gammav = 1.0;
low_outputv = 0;
high_outputv = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = gimp_drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
}
/* make sure the drawable is not indexed color */
if (success)
success = ! gimp_drawable_indexed (drawable);
/* channel */
if (success)
{
int_value = args[1].value.pdb_int;
if (success)
{
if (gimp_drawable_gray (drawable))
{
if (int_value != 0)
success = FALSE;
}
else if (gimp_drawable_color (drawable))
{
if (int_value < 0 || int_value > 3)
success = FALSE;
}
else
success = FALSE;
}
channel = int_value;
}
/* low input */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value >= 0 && int_value < 256)
low_inputv = int_value;
else
success = FALSE;
}
/* high input */
if (success)
{
int_value = args[3].value.pdb_int;
if (int_value >= 0 && int_value < 256)
high_inputv = int_value;
else
success = FALSE;
}
/* gamma */
if (success)
{
fp_value = args[4].value.pdb_float;
if (fp_value >= 0.1 && fp_value <= 10.0)
gammav = fp_value;
else
success = FALSE;
}
/* low output */
if (success)
{
int_value = args[5].value.pdb_int;
if (int_value >= 0 && int_value < 256)
low_outputv = int_value;
else
success = FALSE;
}
/* high output */
if (success)
{
int_value = args[6].value.pdb_int;
if (int_value >= 0 && int_value < 256)
high_outputv = int_value;
else
success = FALSE;
}
/* arrange to modify the levels */
if (success)
{
GimpLut *lut;
for (i = 0; i < 5; i++)
{
low_input[i] = 0;
gamma[i] = 1.0;
high_input[i] = 255;
low_output[i] = 0;
high_output[i] = 255;
}
low_input[channel] = low_inputv;
high_input[channel] = high_inputv;
gamma[channel] = gammav;
low_output[channel] = low_outputv;
high_output[channel] = high_outputv;
/* setup the lut */
lut = levels_lut_new(gamma, low_input, high_input,
low_output, high_output,
gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, gimp_drawable_data (drawable),
x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
pixel_regions_process_parallel((p_func)gimp_lut_process, lut,
2, &srcPR, &destPR);
gimp_lut_free(lut);
gimp_drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
return procedural_db_return_args (&levels_proc, success);
}
/* ------------------------------------------------------------------ */
/* ---------------- The posterize procedure definition -------------- */
/* ------------------------------------------------------------------ */
ProcArg posterize_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"levels",
"levels of posterization: (2 <= levels <= 255)"
}
};
ProcRecord posterize_proc =
{
"gimp_posterize",
"Posterize the specified drawable",
"This procedures reduces the number of shades allows in each intensity channel to the specified 'levels' parameter.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997",
PDB_INTERNAL,
/* Input arguments */
2,
posterize_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { posterize_invoker } },
};
static Argument *
posterize_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
GimpImage *gimage;
GimpDrawable *drawable;
int levels;
int int_value;
int x1, y1, x2, y2;
drawable = NULL;
levels = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = gimp_drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
else
gimage = gimp_drawable_gimage (drawable);
}
/* make sure the drawable is not indexed color */
if (success)
success = ! gimp_drawable_indexed (drawable);
/* levels */
if (success)
{
int_value = args[1].value.pdb_int;
if (int_value >= 2 && int_value < 256)
levels = int_value;
else
success = FALSE;
}
/* arrange to modify the levels */
if (success)
{
GimpLut *lut;
lut = posterize_lut_new(levels, gimp_drawable_bytes(drawable));
/* The application should occur only within selection bounds */
gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, gimp_drawable_data (drawable),
x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
pixel_regions_process_parallel((p_func)gimp_lut_process, lut,
2, &srcPR, &destPR);
gimp_lut_free(lut);
gimp_drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
return procedural_db_return_args (&posterize_proc, success);
}

28
app/color_cmds.h Normal file
View File

@ -0,0 +1,28 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_CMDS_H__
#define __COLOR_CMDS_H__
#include "procedural_db.h"
extern ProcRecord brightness_contrast_proc;
extern ProcRecord levels_proc;
extern ProcRecord posterize_proc;
#endif /* __COLOR_CMDS_H__ */

View File

@ -16,8 +16,12 @@
*/ */
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include <unistd.h>
#include "parasitelist.h" #include "parasitelist.h"
#include "gimpparasite.h" #include "gimpparasite.h"
#include "libgimp/parasite.h"
#include "libgimp/gimpenv.h"
static ParasiteList *parasites = NULL; static ParasiteList *parasites = NULL;
@ -26,6 +30,7 @@ gimp_init_parasites()
{ {
g_return_if_fail(parasites == NULL); g_return_if_fail(parasites == NULL);
parasites = parasite_list_new(); parasites = parasite_list_new();
gimp_parasiterc_load();
} }
void void
@ -64,5 +69,40 @@ gimp_parasite_list (gint *count)
return list; return list;
} }
void
gimp_parasiterc_save()
{
FILE *fp;
guint32 num, version = 1;
if (!(fp = fopen(gimp_personal_rc_file ("#parasiterc.tmp"), "w")))
return;
version = GINT32_TO_BE(version);
fwrite(&version, 4, 1, fp);
parasite_list_save(parasites, fp);
fclose(fp);
if (rename(gimp_personal_rc_file ("#parasiterc.tmp"),
gimp_personal_rc_file("parasiterc")) != 0)
unlink(gimp_personal_rc_file ("#parasiterc.tmp"));
}
void
gimp_parasiterc_load()
{
FILE *fp;
guint32 num, version;
if (!(fp = fopen(gimp_personal_rc_file ("parasiterc"), "r")))
return;
fread(&version, 4, 1, fp);
version = GINT32_FROM_BE(version);
if (version != 1)
{
fclose(fp);
return;
}
parasite_list_load(parasites, fp);
fclose(fp);
}

View File

@ -25,5 +25,7 @@ void gimp_attach_parasite (Parasite *p);
void gimp_detach_parasite (char *name); void gimp_detach_parasite (char *name);
Parasite * gimp_find_parasite (char *name); Parasite * gimp_find_parasite (char *name);
char ** gimp_parasite_list (gint *count); char ** gimp_parasite_list (gint *count);
void gimp_parasiterc_save (void);
void gimp_parasiterc_load (void);
#endif /* __GIMP_PARASITE_H__ */ #endif /* __GIMP_PARASITE_H__ */

View File

@ -36,6 +36,9 @@
#include "channel_pvt.h" #include "channel_pvt.h"
#include "tile.h" #include "tile.h"
#include "gimplut.h"
#include "lut_funcs.h"
/* /*
enum { enum {
LAST_SIGNAL LAST_SIGNAL
@ -602,9 +605,9 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
unsigned char * data; unsigned char * data;
int x, y; int x, y;
int ex, ey; int ex, ey;
int found;
void *pr; void *pr;
int tx1, tx2, ty1, ty2;
int minx, maxx;
/* if the mask's bounds have already been reliably calculated... */ /* if the mask's bounds have already been reliably calculated... */
if (mask->bounds_known) if (mask->bounds_known)
{ {
@ -617,10 +620,10 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
} }
/* go through and calculate the bounds */ /* go through and calculate the bounds */
*x1 = GIMP_DRAWABLE(mask)->width; tx1 = GIMP_DRAWABLE(mask)->width;
*y1 = GIMP_DRAWABLE(mask)->height; ty1 = GIMP_DRAWABLE(mask)->height;
*x2 = 0; tx2 = 0;
*y2 = 0; ty2 = 0;
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, FALSE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, FALSE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr)) for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
@ -630,36 +633,50 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
ey = maskPR.y + maskPR.h; ey = maskPR.y + maskPR.h;
/* only check the pixels if this tile is not fully within the currently /* only check the pixels if this tile is not fully within the currently
computed bounds */ computed bounds */
if (maskPR.x < *x1 || ex > *x2 || if (maskPR.x < tx1 || ex > tx2 ||
maskPR.y < *y1 || ey > *y2) maskPR.y < ty1 || ey > ty2)
{ {
for (y = maskPR.y; y < ey; y++) /* Check upper left and lower right corners to see if we can
avoid checking the rest of the pixels in this tile */
if (data[0] && data[maskPR.rowstride*(maskPR.h - 1) + maskPR.w - 1])
{
if (maskPR.x < tx1)
tx1 = maskPR.x;
if (ex > tx2)
tx2 = ex;
if (maskPR.y < ty1)
ty1 = maskPR.y;
if (ey > ty2)
ty2 = ey;
}
else
for (y = maskPR.y; y < ey; y++)
{ {
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++) for (x = maskPR.x; x < ex; x++, data++)
if (*data) if (*data)
{ {
if (x < *x1) minx = x;
*x1 = x; maxx = x;
if (x > *x2) for (; x < ex; x++, data++)
*x2 = x; if (*data)
found = TRUE; maxx = x;
} if (minx < tx1)
if (found) tx1 = minx;
{ if (maxx > tx2)
if (y < *y1) tx2 = maxx;
*y1 = y; if (y < ty1)
if (y > *y2) ty1 = y;
*y2 = y; if (y > ty2)
} ty2 = y;
}
} }
} }
} }
*x2 = BOUNDS (*x2 + 1, 0, GIMP_DRAWABLE(mask)->width); tx2 = BOUNDS (tx2 + 1, 0, GIMP_DRAWABLE(mask)->width);
*y2 = BOUNDS (*y2 + 1, 0, GIMP_DRAWABLE(mask)->height); ty2 = BOUNDS (ty2 + 1, 0, GIMP_DRAWABLE(mask)->height);
if (*x1 == GIMP_DRAWABLE(mask)->width && *y1 == GIMP_DRAWABLE(mask)->height) if (tx1 == GIMP_DRAWABLE(mask)->width && ty1 == GIMP_DRAWABLE(mask)->height)
{ {
mask->empty = TRUE; mask->empty = TRUE;
mask->x1 = 0; mask->y1 = 0; mask->x1 = 0; mask->y1 = 0;
@ -669,13 +686,18 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
else else
{ {
mask->empty = FALSE; mask->empty = FALSE;
mask->x1 = *x1; mask->x1 = tx1;
mask->y1 = *y1; mask->y1 = ty1;
mask->x2 = *x2; mask->x2 = tx2;
mask->y2 = *y2; mask->y2 = ty2;
} }
mask->bounds_known = TRUE; mask->bounds_known = TRUE;
*x1 = tx1;
*x2 = tx2;
*y1 = ty1;
*y2 = ty2;
return (mask->empty) ? FALSE : TRUE; return (mask->empty) ? FALSE : TRUE;
} }
@ -800,61 +822,31 @@ channel_sub_segment (Channel *mask, int x, int y, int width, int value)
} }
void
channel_inter_segment (Channel *mask, int x, int y, int width, int value)
{
PixelRegion maskPR;
unsigned char *data;
int val;
int x2;
void * pr;
/* check horizontal extents... */
x2 = x + width;
if (x2 < 0) x2 = 0;
if (x2 > GIMP_DRAWABLE(mask)->width) x2 = GIMP_DRAWABLE(mask)->width;
if (x < 0) x = 0;
if (x > GIMP_DRAWABLE(mask)->width) x = GIMP_DRAWABLE(mask)->width;
width = x2 - x;
if (!width) return;
if (y < 0 || y > GIMP_DRAWABLE(mask)->height)
return;
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, x, y, width, 1, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{
data = maskPR.data;
width = maskPR.w;
while (width--)
{
val = MINIMUM(*data, value);
*data++ = val;
}
}
}
void void
channel_combine_rect (Channel *mask, int op, int x, int y, int w, int h) channel_combine_rect (Channel *mask, int op, int x, int y, int w, int h)
{ {
int i; int i;
int x2, y2;
PixelRegion maskPR;
unsigned char color;
y2 = y + h;
x2 = x + w;
for (i = y; i < y + h; i++) x = BOUNDS (x, 0, GIMP_DRAWABLE(mask)->width);
{ y = BOUNDS (y, 0, GIMP_DRAWABLE(mask)->height);
if (i >= 0 && i < GIMP_DRAWABLE(mask)->height) x2 = BOUNDS (x2, 0, GIMP_DRAWABLE(mask)->width);
switch (op) y2 = BOUNDS (y2, 0, GIMP_DRAWABLE(mask)->height);
{
case ADD: case REPLACE: if (x2 - x <= 0 || y2 - y <= 0)
channel_add_segment (mask, x, i, w, 255); return;
break;
case SUB: pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, x, y,
channel_sub_segment (mask, x, i, w, 255); x2 - x, y2 - y, TRUE);
break; if (op == ADD || op == REPLACE)
case INTERSECT: color = 255;
channel_inter_segment (mask, x, i, w, 255); else
break; color = 0;
} color_region(&maskPR, &color);
}
/* Determine new boundary */ /* Determine new boundary */
if (mask->bounds_known && (op == ADD) && !mask->empty) if (mask->bounds_known && (op == ADD) && !mask->empty)
@ -933,9 +925,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
case SUB : case SUB :
channel_sub_segment (mask, x1, i, (x2 - x1), 255); channel_sub_segment (mask, x1, i, (x2 - x1), 255);
break; break;
case INTERSECT:
channel_inter_segment (mask, x1, i, (x2 - x1), 255);
break;
} }
} }
/* antialiasing */ /* antialiasing */
@ -965,7 +954,7 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
val = (int) (255 * (1 - (dist + 0.5))); val = (int) (255 * (1 - (dist + 0.5)));
else else
val = 0; val = 0;
if (last != val && last) if (last != val && last)
{ {
switch (op) switch (op)
@ -976,8 +965,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
case SUB: case SUB:
channel_sub_segment (mask, x0, i, j - x0, last); channel_sub_segment (mask, x0, i, j - x0, last);
break; break;
case INTERSECT:
channel_inter_segment (mask, x0, i, j - x0, last);
} }
} }
@ -985,6 +972,10 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
{ {
x0 = j; x0 = j;
last = val; last = val;
/* because we are symetric accross the y axis we can
skip ahead a bit if we are inside the ellipse*/
if (val == 255 && j < cx)
j = cx + (cx - j) - 1;
} }
} }
@ -994,8 +985,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
channel_add_segment (mask, x0, i, j - x0, last); channel_add_segment (mask, x0, i, j - x0, last);
else if (op == SUB) else if (op == SUB)
channel_sub_segment (mask, x0, i, j - x0, last); channel_sub_segment (mask, x0, i, j - x0, last);
else if (op == INTERSECT)
channel_inter_segment (mask, x0, i, j - x0, last);
} }
} }
@ -1032,18 +1021,81 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
} }
static void
channel_combine_sub_region_add (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y, val;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
val = dest[x] + src[x];
if (val > 255)
dest[x] = 255;
else
dest[x] = val;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
static void
channel_combine_sub_region_sub (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
if (src[x] > dest[x])
dest[x] = 0;
else
dest[x]-= src[x];
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
static void
channel_combine_sub_region_intersect (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
dest[x] = MINIMUM(dest[x], src[x]);
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
void void
channel_combine_mask (Channel *mask, Channel *add_on, int op, channel_combine_mask (Channel *mask, Channel *add_on, int op,
int off_x, int off_y) int off_x, int off_y)
{ {
PixelRegion srcPR, destPR; PixelRegion srcPR, destPR;
unsigned char *src;
unsigned char *dest;
int val;
int x1, y1, x2, y2; int x1, y1, x2, y2;
int x, y;
int w, h; int w, h;
void * pr;
x1 = BOUNDS (off_x, 0, GIMP_DRAWABLE(mask)->width); x1 = BOUNDS (off_x, 0, GIMP_DRAWABLE(mask)->width);
y1 = BOUNDS (off_y, 0, GIMP_DRAWABLE(mask)->height); y1 = BOUNDS (off_y, 0, GIMP_DRAWABLE(mask)->height);
@ -1056,39 +1108,25 @@ channel_combine_mask (Channel *mask, Channel *add_on, int op,
pixel_region_init (&srcPR, GIMP_DRAWABLE(add_on)->tiles, (x1 - off_x), (y1 - off_y), w, h, FALSE); pixel_region_init (&srcPR, GIMP_DRAWABLE(add_on)->tiles, (x1 - off_x), (y1 - off_y), w, h, FALSE);
pixel_region_init (&destPR, GIMP_DRAWABLE(mask)->tiles, x1, y1, w, h, TRUE); pixel_region_init (&destPR, GIMP_DRAWABLE(mask)->tiles, x1, y1, w, h, TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) switch (op)
{ {
src = srcPR.data; case ADD: case REPLACE:
dest = destPR.data; pixel_regions_process_parallel ((p_func)channel_combine_sub_region_add,
NULL, 2, &srcPR, &destPR);
for (y = 0; y < srcPR.h; y++) break;
{ case SUB:
for (x = 0; x < srcPR.w; x++) pixel_regions_process_parallel ((p_func)channel_combine_sub_region_sub,
{ NULL, 2, &srcPR, &destPR);
switch (op) break;
{ case INTERSECT:
case ADD: case REPLACE: pixel_regions_process_parallel ((p_func)
val = dest[x] + src[x]; channel_combine_sub_region_intersect,
if (val > 255) val = 255; NULL, 2, &srcPR, &destPR);
break; break;
case SUB: default:
val = dest[x] - src[x]; g_message("Error: unknown opperation type in channel_combine_mask\n");
if (val < 0) val = 0; break;
break; }
case INTERSECT:
val = MINIMUM(dest[x], src[x]);
break;
default:
val = 0;
break;
}
dest[x] = val;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
}
mask->bounds_known = FALSE; mask->bounds_known = FALSE;
} }
@ -1184,57 +1222,35 @@ void
channel_invert (Channel *mask) channel_invert (Channel *mask)
{ {
PixelRegion maskPR; PixelRegion maskPR;
unsigned char *data; GimpLut *lut;
int size;
void * pr;
/* push the current channel onto the undo stack */ /* push the current channel onto the undo stack */
channel_push_undo (mask); channel_push_undo (mask);
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{ lut = invert_lut_new(1);
/* subtract each pixel in the mask from 255 */
data = maskPR.data;
size = maskPR.w * maskPR.h;
while (size --)
{
*data = 255 - *data;
data++;
}
}
pixel_regions_process_parallel ((p_func)gimp_lut_process_inline,
lut, 1, &maskPR);
gimp_lut_free(lut);
mask->bounds_known = FALSE; mask->bounds_known = FALSE;
} }
void void
channel_sharpen (Channel *mask) channel_sharpen (Channel *mask)
{ {
PixelRegion maskPR; PixelRegion maskPR;
unsigned char *data; GimpLut *lut;
int size;
void * pr;
/* push the current channel onto the undo stack */ /* push the current channel onto the undo stack */
channel_push_undo (mask); channel_push_undo (mask);
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr)) lut = threshold_lut_new(0.5, 1);
{
/* if a pixel in the mask has a non-zero value, make it 255 */
data = maskPR.data;
size = maskPR.w * maskPR.h;
while (size--)
{
if (*data > HALF_WAY)
*data++ = 255;
else
*data++ = 0;
}
}
mask->bounds_known = FALSE; pixel_regions_process_parallel ((p_func)gimp_lut_process_inline,
lut, 1, &maskPR);
gimp_lut_free(lut);
} }

View File

@ -36,6 +36,9 @@
#include "channel_pvt.h" #include "channel_pvt.h"
#include "tile.h" #include "tile.h"
#include "gimplut.h"
#include "lut_funcs.h"
/* /*
enum { enum {
LAST_SIGNAL LAST_SIGNAL
@ -602,9 +605,9 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
unsigned char * data; unsigned char * data;
int x, y; int x, y;
int ex, ey; int ex, ey;
int found;
void *pr; void *pr;
int tx1, tx2, ty1, ty2;
int minx, maxx;
/* if the mask's bounds have already been reliably calculated... */ /* if the mask's bounds have already been reliably calculated... */
if (mask->bounds_known) if (mask->bounds_known)
{ {
@ -617,10 +620,10 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
} }
/* go through and calculate the bounds */ /* go through and calculate the bounds */
*x1 = GIMP_DRAWABLE(mask)->width; tx1 = GIMP_DRAWABLE(mask)->width;
*y1 = GIMP_DRAWABLE(mask)->height; ty1 = GIMP_DRAWABLE(mask)->height;
*x2 = 0; tx2 = 0;
*y2 = 0; ty2 = 0;
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, FALSE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, FALSE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr)) for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
@ -630,36 +633,50 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
ey = maskPR.y + maskPR.h; ey = maskPR.y + maskPR.h;
/* only check the pixels if this tile is not fully within the currently /* only check the pixels if this tile is not fully within the currently
computed bounds */ computed bounds */
if (maskPR.x < *x1 || ex > *x2 || if (maskPR.x < tx1 || ex > tx2 ||
maskPR.y < *y1 || ey > *y2) maskPR.y < ty1 || ey > ty2)
{ {
for (y = maskPR.y; y < ey; y++) /* Check upper left and lower right corners to see if we can
avoid checking the rest of the pixels in this tile */
if (data[0] && data[maskPR.rowstride*(maskPR.h - 1) + maskPR.w - 1])
{
if (maskPR.x < tx1)
tx1 = maskPR.x;
if (ex > tx2)
tx2 = ex;
if (maskPR.y < ty1)
ty1 = maskPR.y;
if (ey > ty2)
ty2 = ey;
}
else
for (y = maskPR.y; y < ey; y++)
{ {
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++) for (x = maskPR.x; x < ex; x++, data++)
if (*data) if (*data)
{ {
if (x < *x1) minx = x;
*x1 = x; maxx = x;
if (x > *x2) for (; x < ex; x++, data++)
*x2 = x; if (*data)
found = TRUE; maxx = x;
} if (minx < tx1)
if (found) tx1 = minx;
{ if (maxx > tx2)
if (y < *y1) tx2 = maxx;
*y1 = y; if (y < ty1)
if (y > *y2) ty1 = y;
*y2 = y; if (y > ty2)
} ty2 = y;
}
} }
} }
} }
*x2 = BOUNDS (*x2 + 1, 0, GIMP_DRAWABLE(mask)->width); tx2 = BOUNDS (tx2 + 1, 0, GIMP_DRAWABLE(mask)->width);
*y2 = BOUNDS (*y2 + 1, 0, GIMP_DRAWABLE(mask)->height); ty2 = BOUNDS (ty2 + 1, 0, GIMP_DRAWABLE(mask)->height);
if (*x1 == GIMP_DRAWABLE(mask)->width && *y1 == GIMP_DRAWABLE(mask)->height) if (tx1 == GIMP_DRAWABLE(mask)->width && ty1 == GIMP_DRAWABLE(mask)->height)
{ {
mask->empty = TRUE; mask->empty = TRUE;
mask->x1 = 0; mask->y1 = 0; mask->x1 = 0; mask->y1 = 0;
@ -669,13 +686,18 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
else else
{ {
mask->empty = FALSE; mask->empty = FALSE;
mask->x1 = *x1; mask->x1 = tx1;
mask->y1 = *y1; mask->y1 = ty1;
mask->x2 = *x2; mask->x2 = tx2;
mask->y2 = *y2; mask->y2 = ty2;
} }
mask->bounds_known = TRUE; mask->bounds_known = TRUE;
*x1 = tx1;
*x2 = tx2;
*y1 = ty1;
*y2 = ty2;
return (mask->empty) ? FALSE : TRUE; return (mask->empty) ? FALSE : TRUE;
} }
@ -800,61 +822,31 @@ channel_sub_segment (Channel *mask, int x, int y, int width, int value)
} }
void
channel_inter_segment (Channel *mask, int x, int y, int width, int value)
{
PixelRegion maskPR;
unsigned char *data;
int val;
int x2;
void * pr;
/* check horizontal extents... */
x2 = x + width;
if (x2 < 0) x2 = 0;
if (x2 > GIMP_DRAWABLE(mask)->width) x2 = GIMP_DRAWABLE(mask)->width;
if (x < 0) x = 0;
if (x > GIMP_DRAWABLE(mask)->width) x = GIMP_DRAWABLE(mask)->width;
width = x2 - x;
if (!width) return;
if (y < 0 || y > GIMP_DRAWABLE(mask)->height)
return;
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, x, y, width, 1, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{
data = maskPR.data;
width = maskPR.w;
while (width--)
{
val = MINIMUM(*data, value);
*data++ = val;
}
}
}
void void
channel_combine_rect (Channel *mask, int op, int x, int y, int w, int h) channel_combine_rect (Channel *mask, int op, int x, int y, int w, int h)
{ {
int i; int i;
int x2, y2;
PixelRegion maskPR;
unsigned char color;
y2 = y + h;
x2 = x + w;
for (i = y; i < y + h; i++) x = BOUNDS (x, 0, GIMP_DRAWABLE(mask)->width);
{ y = BOUNDS (y, 0, GIMP_DRAWABLE(mask)->height);
if (i >= 0 && i < GIMP_DRAWABLE(mask)->height) x2 = BOUNDS (x2, 0, GIMP_DRAWABLE(mask)->width);
switch (op) y2 = BOUNDS (y2, 0, GIMP_DRAWABLE(mask)->height);
{
case ADD: case REPLACE: if (x2 - x <= 0 || y2 - y <= 0)
channel_add_segment (mask, x, i, w, 255); return;
break;
case SUB: pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, x, y,
channel_sub_segment (mask, x, i, w, 255); x2 - x, y2 - y, TRUE);
break; if (op == ADD || op == REPLACE)
case INTERSECT: color = 255;
channel_inter_segment (mask, x, i, w, 255); else
break; color = 0;
} color_region(&maskPR, &color);
}
/* Determine new boundary */ /* Determine new boundary */
if (mask->bounds_known && (op == ADD) && !mask->empty) if (mask->bounds_known && (op == ADD) && !mask->empty)
@ -933,9 +925,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
case SUB : case SUB :
channel_sub_segment (mask, x1, i, (x2 - x1), 255); channel_sub_segment (mask, x1, i, (x2 - x1), 255);
break; break;
case INTERSECT:
channel_inter_segment (mask, x1, i, (x2 - x1), 255);
break;
} }
} }
/* antialiasing */ /* antialiasing */
@ -965,7 +954,7 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
val = (int) (255 * (1 - (dist + 0.5))); val = (int) (255 * (1 - (dist + 0.5)));
else else
val = 0; val = 0;
if (last != val && last) if (last != val && last)
{ {
switch (op) switch (op)
@ -976,8 +965,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
case SUB: case SUB:
channel_sub_segment (mask, x0, i, j - x0, last); channel_sub_segment (mask, x0, i, j - x0, last);
break; break;
case INTERSECT:
channel_inter_segment (mask, x0, i, j - x0, last);
} }
} }
@ -985,6 +972,10 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
{ {
x0 = j; x0 = j;
last = val; last = val;
/* because we are symetric accross the y axis we can
skip ahead a bit if we are inside the ellipse*/
if (val == 255 && j < cx)
j = cx + (cx - j) - 1;
} }
} }
@ -994,8 +985,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
channel_add_segment (mask, x0, i, j - x0, last); channel_add_segment (mask, x0, i, j - x0, last);
else if (op == SUB) else if (op == SUB)
channel_sub_segment (mask, x0, i, j - x0, last); channel_sub_segment (mask, x0, i, j - x0, last);
else if (op == INTERSECT)
channel_inter_segment (mask, x0, i, j - x0, last);
} }
} }
@ -1032,18 +1021,81 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
} }
static void
channel_combine_sub_region_add (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y, val;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
val = dest[x] + src[x];
if (val > 255)
dest[x] = 255;
else
dest[x] = val;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
static void
channel_combine_sub_region_sub (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
if (src[x] > dest[x])
dest[x] = 0;
else
dest[x]-= src[x];
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
static void
channel_combine_sub_region_intersect (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
dest[x] = MINIMUM(dest[x], src[x]);
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
void void
channel_combine_mask (Channel *mask, Channel *add_on, int op, channel_combine_mask (Channel *mask, Channel *add_on, int op,
int off_x, int off_y) int off_x, int off_y)
{ {
PixelRegion srcPR, destPR; PixelRegion srcPR, destPR;
unsigned char *src;
unsigned char *dest;
int val;
int x1, y1, x2, y2; int x1, y1, x2, y2;
int x, y;
int w, h; int w, h;
void * pr;
x1 = BOUNDS (off_x, 0, GIMP_DRAWABLE(mask)->width); x1 = BOUNDS (off_x, 0, GIMP_DRAWABLE(mask)->width);
y1 = BOUNDS (off_y, 0, GIMP_DRAWABLE(mask)->height); y1 = BOUNDS (off_y, 0, GIMP_DRAWABLE(mask)->height);
@ -1056,39 +1108,25 @@ channel_combine_mask (Channel *mask, Channel *add_on, int op,
pixel_region_init (&srcPR, GIMP_DRAWABLE(add_on)->tiles, (x1 - off_x), (y1 - off_y), w, h, FALSE); pixel_region_init (&srcPR, GIMP_DRAWABLE(add_on)->tiles, (x1 - off_x), (y1 - off_y), w, h, FALSE);
pixel_region_init (&destPR, GIMP_DRAWABLE(mask)->tiles, x1, y1, w, h, TRUE); pixel_region_init (&destPR, GIMP_DRAWABLE(mask)->tiles, x1, y1, w, h, TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) switch (op)
{ {
src = srcPR.data; case ADD: case REPLACE:
dest = destPR.data; pixel_regions_process_parallel ((p_func)channel_combine_sub_region_add,
NULL, 2, &srcPR, &destPR);
for (y = 0; y < srcPR.h; y++) break;
{ case SUB:
for (x = 0; x < srcPR.w; x++) pixel_regions_process_parallel ((p_func)channel_combine_sub_region_sub,
{ NULL, 2, &srcPR, &destPR);
switch (op) break;
{ case INTERSECT:
case ADD: case REPLACE: pixel_regions_process_parallel ((p_func)
val = dest[x] + src[x]; channel_combine_sub_region_intersect,
if (val > 255) val = 255; NULL, 2, &srcPR, &destPR);
break; break;
case SUB: default:
val = dest[x] - src[x]; g_message("Error: unknown opperation type in channel_combine_mask\n");
if (val < 0) val = 0; break;
break; }
case INTERSECT:
val = MINIMUM(dest[x], src[x]);
break;
default:
val = 0;
break;
}
dest[x] = val;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
}
mask->bounds_known = FALSE; mask->bounds_known = FALSE;
} }
@ -1184,57 +1222,35 @@ void
channel_invert (Channel *mask) channel_invert (Channel *mask)
{ {
PixelRegion maskPR; PixelRegion maskPR;
unsigned char *data; GimpLut *lut;
int size;
void * pr;
/* push the current channel onto the undo stack */ /* push the current channel onto the undo stack */
channel_push_undo (mask); channel_push_undo (mask);
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{ lut = invert_lut_new(1);
/* subtract each pixel in the mask from 255 */
data = maskPR.data;
size = maskPR.w * maskPR.h;
while (size --)
{
*data = 255 - *data;
data++;
}
}
pixel_regions_process_parallel ((p_func)gimp_lut_process_inline,
lut, 1, &maskPR);
gimp_lut_free(lut);
mask->bounds_known = FALSE; mask->bounds_known = FALSE;
} }
void void
channel_sharpen (Channel *mask) channel_sharpen (Channel *mask)
{ {
PixelRegion maskPR; PixelRegion maskPR;
unsigned char *data; GimpLut *lut;
int size;
void * pr;
/* push the current channel onto the undo stack */ /* push the current channel onto the undo stack */
channel_push_undo (mask); channel_push_undo (mask);
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr)) lut = threshold_lut_new(0.5, 1);
{
/* if a pixel in the mask has a non-zero value, make it 255 */
data = maskPR.data;
size = maskPR.w * maskPR.h;
while (size--)
{
if (*data > HALF_WAY)
*data++ = 255;
else
*data++ = 0;
}
}
mask->bounds_known = FALSE; pixel_regions_process_parallel ((p_func)gimp_lut_process_inline,
lut, 1, &maskPR);
gimp_lut_free(lut);
} }

View File

@ -19,27 +19,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "appenv.h"
#include "drawable.h" #include "drawable.h"
#include "equalize.h" #include "equalize.h"
#include "interface.h"
#include "gimage.h" #include "gimage.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "gimphistogram.h" #include "gimphistogram.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
struct hist_lut_struct
{
GimpHistogram *histogram;
int part[5][257];
};
static float equalize_lut_func(struct hist_lut_struct *hlut,
int nchannels, int channel, float value);
static void equalize (GImage *, GimpDrawable *, int); static void equalize (GImage *, GimpDrawable *, int);
static Argument * equalize_invoker (Argument *); static Argument * equalize_invoker (Argument *);
static GimpLut * eq_histogram_lut (GimpHistogram *hist, int bytes);
void void
@ -87,7 +77,7 @@ equalize(gimage, drawable, mask_only)
/* Build equalization LUT */ /* Build equalization LUT */
lut = eq_histogram_lut (hist, bytes); lut = eq_histogram_lut_new (hist, bytes);
/* Apply the histogram */ /* Apply the histogram */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -105,71 +95,10 @@ equalize(gimage, drawable, mask_only)
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
} }
/* ------------------------------------------------------------------ */
/* --------------- The equalize procedure definition ---------------- */
/* ------------------------------------------------------------------ */
/*****/
static GimpLut *
eq_histogram_lut (GimpHistogram *hist, int bytes)
{
int i, k, j;
struct hist_lut_struct hlut;
double pixels_per_value;
double desired;
GimpLut *lut;
double sum, dif;
/* Find partition points */
pixels_per_value = gimp_histogram_get_count(hist, 0, 255) / 256.0;
for (k = 0; k < bytes; k++)
{
/* First and last points in partition */
hlut.part[k][0] = 0;
hlut.part[k][256] = 256;
/* Find intermediate points */
j = 0;
sum = gimp_histogram_get_channel(hist, k, 0) +
gimp_histogram_get_channel(hist, k, 1);
for (i = 1; i < 256; i++)
{
desired = i * pixels_per_value;
while (sum <= desired)
{
j++;
sum += gimp_histogram_get_channel(hist, k, j + 1);
}
/* Nearest sum */
dif = sum - gimp_histogram_get_channel(hist, k, j);
if ((sum - desired) > (dif / 2.0))
hlut.part[k][i] = j;
else
hlut.part[k][i] = j + 1;
}
}
lut = gimp_lut_new();
gimp_lut_setup(lut, (GimpLutFunc) equalize_lut_func,
(void *) &hlut, bytes);
return lut;
}
static float
equalize_lut_func(struct hist_lut_struct *hlut,
int nchannels, int channel, float value)
{
int i = 0, j;
j = (int)(value * 255.0 + 0.5);
while (hlut->part[channel][i + 1] <= j)
i++;
return i / 255.0;
}
/* The equalize procedure definition */
ProcArg equalize_args[] = ProcArg equalize_args[] =
{ {
{ PDB_DRAWABLE, { PDB_DRAWABLE,

View File

@ -24,6 +24,7 @@
#include "invert.h" #include "invert.h"
#include "gimage.h" #include "gimage.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -58,18 +59,6 @@ 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 */ /* Inverter */
static void static void
@ -79,10 +68,7 @@ invert (GimpDrawable *drawable)
int x1, y1, x2, y2; int x1, y1, x2, y2;
GimpLut *lut; GimpLut *lut;
lut = gimp_lut_new(); lut = invert_lut_new(gimp_drawable_bytes(drawable));
gimp_lut_setup_exact(lut, (GimpLutFunc) invert_lut_func,
(void *) NULL, gimp_drawable_bytes(drawable));
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); 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 (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
@ -97,8 +83,10 @@ invert (GimpDrawable *drawable)
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
} }
/* ------------------------------------------------------------------ */
/* ----------------- The invert procedure definition ---------------- */
/* ------------------------------------------------------------------ */
/* The invert procedure definition */
ProcArg invert_args[] = ProcArg invert_args[] =
{ {
{ PDB_DRAWABLE, { PDB_DRAWABLE,

View File

@ -640,7 +640,6 @@ gimp_drawable_init (GimpDrawable *drawable)
drawable->preview_valid = FALSE; drawable->preview_valid = FALSE;
drawable->parasites = parasite_list_new(); drawable->parasites = parasite_list_new();
drawable->tattoo = 0; drawable->tattoo = 0;
gimp_matrix_identity(drawable->transform);
drawable->ID = global_drawable_ID++; drawable->ID = global_drawable_ID++;
if (gimp_drawable_table == NULL) if (gimp_drawable_table == NULL)

View File

@ -169,7 +169,6 @@ static void gimp_image_init (GimpImage *gimage)
gimage->comp_preview_valid[2] = FALSE; gimage->comp_preview_valid[2] = FALSE;
gimage->comp_preview = NULL; gimage->comp_preview = NULL;
gimage->parasites = parasite_list_new(); gimage->parasites = parasite_list_new();
gimp_matrix_identity(gimage->transform);
gimage->xresolution = default_xresolution; gimage->xresolution = default_xresolution;
gimage->yresolution = default_yresolution; gimage->yresolution = default_yresolution;
gimage->unit = default_units; gimage->unit = default_units;

View File

@ -169,7 +169,6 @@ static void gimp_image_init (GimpImage *gimage)
gimage->comp_preview_valid[2] = FALSE; gimage->comp_preview_valid[2] = FALSE;
gimage->comp_preview = NULL; gimage->comp_preview = NULL;
gimage->parasites = parasite_list_new(); gimage->parasites = parasite_list_new();
gimp_matrix_identity(gimage->transform);
gimage->xresolution = default_xresolution; gimage->xresolution = default_xresolution;
gimage->yresolution = default_yresolution; gimage->yresolution = default_yresolution;
gimage->unit = default_units; gimage->unit = default_units;

View File

@ -169,7 +169,6 @@ static void gimp_image_init (GimpImage *gimage)
gimage->comp_preview_valid[2] = FALSE; gimage->comp_preview_valid[2] = FALSE;
gimage->comp_preview = NULL; gimage->comp_preview = NULL;
gimage->parasites = parasite_list_new(); gimage->parasites = parasite_list_new();
gimp_matrix_identity(gimage->transform);
gimage->xresolution = default_xresolution; gimage->xresolution = default_xresolution;
gimage->yresolution = default_yresolution; gimage->yresolution = default_yresolution;
gimage->unit = default_units; gimage->unit = default_units;

View File

@ -169,7 +169,6 @@ static void gimp_image_init (GimpImage *gimage)
gimage->comp_preview_valid[2] = FALSE; gimage->comp_preview_valid[2] = FALSE;
gimage->comp_preview = NULL; gimage->comp_preview = NULL;
gimage->parasites = parasite_list_new(); gimage->parasites = parasite_list_new();
gimp_matrix_identity(gimage->transform);
gimage->xresolution = default_xresolution; gimage->xresolution = default_xresolution;
gimage->yresolution = default_yresolution; gimage->yresolution = default_yresolution;
gimage->unit = default_units; gimage->unit = default_units;

View File

@ -169,7 +169,6 @@ static void gimp_image_init (GimpImage *gimage)
gimage->comp_preview_valid[2] = FALSE; gimage->comp_preview_valid[2] = FALSE;
gimage->comp_preview = NULL; gimage->comp_preview = NULL;
gimage->parasites = parasite_list_new(); gimage->parasites = parasite_list_new();
gimp_matrix_identity(gimage->transform);
gimage->xresolution = default_xresolution; gimage->xresolution = default_xresolution;
gimage->yresolution = default_yresolution; gimage->yresolution = default_yresolution;
gimage->unit = default_units; gimage->unit = default_units;

View File

@ -169,7 +169,6 @@ static void gimp_image_init (GimpImage *gimage)
gimage->comp_preview_valid[2] = FALSE; gimage->comp_preview_valid[2] = FALSE;
gimage->comp_preview = NULL; gimage->comp_preview = NULL;
gimage->parasites = parasite_list_new(); gimage->parasites = parasite_list_new();
gimp_matrix_identity(gimage->transform);
gimage->xresolution = default_xresolution; gimage->xresolution = default_xresolution;
gimage->yresolution = default_yresolution; gimage->yresolution = default_yresolution;
gimage->unit = default_units; gimage->unit = default_units;

View File

@ -16,8 +16,12 @@
*/ */
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include <unistd.h>
#include "parasitelist.h" #include "parasitelist.h"
#include "gimpparasite.h" #include "gimpparasite.h"
#include "libgimp/parasite.h"
#include "libgimp/gimpenv.h"
static ParasiteList *parasites = NULL; static ParasiteList *parasites = NULL;
@ -26,6 +30,7 @@ gimp_init_parasites()
{ {
g_return_if_fail(parasites == NULL); g_return_if_fail(parasites == NULL);
parasites = parasite_list_new(); parasites = parasite_list_new();
gimp_parasiterc_load();
} }
void void
@ -64,5 +69,40 @@ gimp_parasite_list (gint *count)
return list; return list;
} }
void
gimp_parasiterc_save()
{
FILE *fp;
guint32 num, version = 1;
if (!(fp = fopen(gimp_personal_rc_file ("#parasiterc.tmp"), "w")))
return;
version = GINT32_TO_BE(version);
fwrite(&version, 4, 1, fp);
parasite_list_save(parasites, fp);
fclose(fp);
if (rename(gimp_personal_rc_file ("#parasiterc.tmp"),
gimp_personal_rc_file("parasiterc")) != 0)
unlink(gimp_personal_rc_file ("#parasiterc.tmp"));
}
void
gimp_parasiterc_load()
{
FILE *fp;
guint32 num, version;
if (!(fp = fopen(gimp_personal_rc_file ("parasiterc"), "r")))
return;
fread(&version, 4, 1, fp);
version = GINT32_FROM_BE(version);
if (version != 1)
{
fclose(fp);
return;
}
parasite_list_load(parasites, fp);
fclose(fp);
}

View File

@ -25,5 +25,7 @@ void gimp_attach_parasite (Parasite *p);
void gimp_detach_parasite (char *name); void gimp_detach_parasite (char *name);
Parasite * gimp_find_parasite (char *name); Parasite * gimp_find_parasite (char *name);
char ** gimp_parasite_list (gint *count); char ** gimp_parasite_list (gint *count);
void gimp_parasiterc_save (void);
void gimp_parasiterc_load (void);
#endif /* __GIMP_PARASITE_H__ */ #endif /* __GIMP_PARASITE_H__ */

View File

@ -214,6 +214,42 @@ parasite_list_find(ParasiteList *list, const char *name)
return NULL; return NULL;
} }
static int saved_bytes;
static void
save_a_parasite(char *key, Parasite *p, FILE *fp)
{
if (parasite_is_persistent(p))
saved_bytes += parasite_save(p, fp);
}
int
parasite_list_save(ParasiteList *list, FILE *fp)
{
guint32 num;
num = parasite_list_persistent_length (list);
num = GINT32_TO_BE(num);
fwrite(&num, 4, 1, fp);
saved_bytes = 4;
parasite_list_foreach(list, (GHFunc)save_a_parasite, fp);
return saved_bytes;
}
void
parasite_list_load(ParasiteList *list, FILE *fp)
{
Parasite *p;
guint32 num, version;
num = 0;
fread(&num, 4, 1, fp);
num = GINT32_FROM_BE(num);
while (num--)
{
p = parasite_load(fp);
parasite_list_add(list, p);
parasite_free(p);
}
}
void void
parasite_shift_parent(Parasite *p) parasite_shift_parent(Parasite *p)

View File

@ -19,6 +19,7 @@
#define __PARASITE_LIST_H__ #define __PARASITE_LIST_H__
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include "libgimp/parasiteF.h" #include "libgimp/parasiteF.h"
#include "parasitelistF.h" #include "parasitelistF.h"
#include "gimpobject.h" #include "gimpobject.h"
@ -46,6 +47,8 @@ void parasite_list_foreach (ParasiteList *list, GHFunc function,
gpointer user_data); gpointer user_data);
Parasite *parasite_list_find (ParasiteList *list, const char *name); Parasite *parasite_list_find (ParasiteList *list, const char *name);
int parasite_list_save (ParasiteList *list, FILE *fp);
void parasite_list_load (ParasiteList *list, FILE *fp);
void parasite_shift_parent (Parasite *p); void parasite_shift_parent (Parasite *p);
#endif /* __GIMP_PARASITE_H__ */ #endif /* __GIMP_PARASITE_H__ */

View File

@ -169,7 +169,6 @@ static void gimp_image_init (GimpImage *gimage)
gimage->comp_preview_valid[2] = FALSE; gimage->comp_preview_valid[2] = FALSE;
gimage->comp_preview = NULL; gimage->comp_preview = NULL;
gimage->parasites = parasite_list_new(); gimage->parasites = parasite_list_new();
gimp_matrix_identity(gimage->transform);
gimage->xresolution = default_xresolution; gimage->xresolution = default_xresolution;
gimage->yresolution = default_yresolution; gimage->yresolution = default_yresolution;
gimage->unit = default_units; gimage->unit = default_units;

View File

@ -19,27 +19,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "appenv.h"
#include "drawable.h" #include "drawable.h"
#include "equalize.h" #include "equalize.h"
#include "interface.h"
#include "gimage.h" #include "gimage.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "gimphistogram.h" #include "gimphistogram.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
struct hist_lut_struct
{
GimpHistogram *histogram;
int part[5][257];
};
static float equalize_lut_func(struct hist_lut_struct *hlut,
int nchannels, int channel, float value);
static void equalize (GImage *, GimpDrawable *, int); static void equalize (GImage *, GimpDrawable *, int);
static Argument * equalize_invoker (Argument *); static Argument * equalize_invoker (Argument *);
static GimpLut * eq_histogram_lut (GimpHistogram *hist, int bytes);
void void
@ -87,7 +77,7 @@ equalize(gimage, drawable, mask_only)
/* Build equalization LUT */ /* Build equalization LUT */
lut = eq_histogram_lut (hist, bytes); lut = eq_histogram_lut_new (hist, bytes);
/* Apply the histogram */ /* Apply the histogram */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -105,71 +95,10 @@ equalize(gimage, drawable, mask_only)
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
} }
/* ------------------------------------------------------------------ */
/* --------------- The equalize procedure definition ---------------- */
/* ------------------------------------------------------------------ */
/*****/
static GimpLut *
eq_histogram_lut (GimpHistogram *hist, int bytes)
{
int i, k, j;
struct hist_lut_struct hlut;
double pixels_per_value;
double desired;
GimpLut *lut;
double sum, dif;
/* Find partition points */
pixels_per_value = gimp_histogram_get_count(hist, 0, 255) / 256.0;
for (k = 0; k < bytes; k++)
{
/* First and last points in partition */
hlut.part[k][0] = 0;
hlut.part[k][256] = 256;
/* Find intermediate points */
j = 0;
sum = gimp_histogram_get_channel(hist, k, 0) +
gimp_histogram_get_channel(hist, k, 1);
for (i = 1; i < 256; i++)
{
desired = i * pixels_per_value;
while (sum <= desired)
{
j++;
sum += gimp_histogram_get_channel(hist, k, j + 1);
}
/* Nearest sum */
dif = sum - gimp_histogram_get_channel(hist, k, j);
if ((sum - desired) > (dif / 2.0))
hlut.part[k][i] = j;
else
hlut.part[k][i] = j + 1;
}
}
lut = gimp_lut_new();
gimp_lut_setup(lut, (GimpLutFunc) equalize_lut_func,
(void *) &hlut, bytes);
return lut;
}
static float
equalize_lut_func(struct hist_lut_struct *hlut,
int nchannels, int channel, float value)
{
int i = 0, j;
j = (int)(value * 255.0 + 0.5);
while (hlut->part[channel][i + 1] <= j)
i++;
return i / 255.0;
}
/* The equalize procedure definition */
ProcArg equalize_args[] = ProcArg equalize_args[] =
{ {
{ PDB_DRAWABLE, { PDB_DRAWABLE,

View File

@ -36,6 +36,9 @@
#include "channel_pvt.h" #include "channel_pvt.h"
#include "tile.h" #include "tile.h"
#include "gimplut.h"
#include "lut_funcs.h"
/* /*
enum { enum {
LAST_SIGNAL LAST_SIGNAL
@ -602,9 +605,9 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
unsigned char * data; unsigned char * data;
int x, y; int x, y;
int ex, ey; int ex, ey;
int found;
void *pr; void *pr;
int tx1, tx2, ty1, ty2;
int minx, maxx;
/* if the mask's bounds have already been reliably calculated... */ /* if the mask's bounds have already been reliably calculated... */
if (mask->bounds_known) if (mask->bounds_known)
{ {
@ -617,10 +620,10 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
} }
/* go through and calculate the bounds */ /* go through and calculate the bounds */
*x1 = GIMP_DRAWABLE(mask)->width; tx1 = GIMP_DRAWABLE(mask)->width;
*y1 = GIMP_DRAWABLE(mask)->height; ty1 = GIMP_DRAWABLE(mask)->height;
*x2 = 0; tx2 = 0;
*y2 = 0; ty2 = 0;
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, FALSE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, FALSE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr)) for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
@ -630,36 +633,50 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
ey = maskPR.y + maskPR.h; ey = maskPR.y + maskPR.h;
/* only check the pixels if this tile is not fully within the currently /* only check the pixels if this tile is not fully within the currently
computed bounds */ computed bounds */
if (maskPR.x < *x1 || ex > *x2 || if (maskPR.x < tx1 || ex > tx2 ||
maskPR.y < *y1 || ey > *y2) maskPR.y < ty1 || ey > ty2)
{ {
for (y = maskPR.y; y < ey; y++) /* Check upper left and lower right corners to see if we can
avoid checking the rest of the pixels in this tile */
if (data[0] && data[maskPR.rowstride*(maskPR.h - 1) + maskPR.w - 1])
{
if (maskPR.x < tx1)
tx1 = maskPR.x;
if (ex > tx2)
tx2 = ex;
if (maskPR.y < ty1)
ty1 = maskPR.y;
if (ey > ty2)
ty2 = ey;
}
else
for (y = maskPR.y; y < ey; y++)
{ {
found = FALSE;
for (x = maskPR.x; x < ex; x++, data++) for (x = maskPR.x; x < ex; x++, data++)
if (*data) if (*data)
{ {
if (x < *x1) minx = x;
*x1 = x; maxx = x;
if (x > *x2) for (; x < ex; x++, data++)
*x2 = x; if (*data)
found = TRUE; maxx = x;
} if (minx < tx1)
if (found) tx1 = minx;
{ if (maxx > tx2)
if (y < *y1) tx2 = maxx;
*y1 = y; if (y < ty1)
if (y > *y2) ty1 = y;
*y2 = y; if (y > ty2)
} ty2 = y;
}
} }
} }
} }
*x2 = BOUNDS (*x2 + 1, 0, GIMP_DRAWABLE(mask)->width); tx2 = BOUNDS (tx2 + 1, 0, GIMP_DRAWABLE(mask)->width);
*y2 = BOUNDS (*y2 + 1, 0, GIMP_DRAWABLE(mask)->height); ty2 = BOUNDS (ty2 + 1, 0, GIMP_DRAWABLE(mask)->height);
if (*x1 == GIMP_DRAWABLE(mask)->width && *y1 == GIMP_DRAWABLE(mask)->height) if (tx1 == GIMP_DRAWABLE(mask)->width && ty1 == GIMP_DRAWABLE(mask)->height)
{ {
mask->empty = TRUE; mask->empty = TRUE;
mask->x1 = 0; mask->y1 = 0; mask->x1 = 0; mask->y1 = 0;
@ -669,13 +686,18 @@ channel_bounds (Channel *mask, int *x1, int *y1, int *x2, int *y2)
else else
{ {
mask->empty = FALSE; mask->empty = FALSE;
mask->x1 = *x1; mask->x1 = tx1;
mask->y1 = *y1; mask->y1 = ty1;
mask->x2 = *x2; mask->x2 = tx2;
mask->y2 = *y2; mask->y2 = ty2;
} }
mask->bounds_known = TRUE; mask->bounds_known = TRUE;
*x1 = tx1;
*x2 = tx2;
*y1 = ty1;
*y2 = ty2;
return (mask->empty) ? FALSE : TRUE; return (mask->empty) ? FALSE : TRUE;
} }
@ -800,61 +822,31 @@ channel_sub_segment (Channel *mask, int x, int y, int width, int value)
} }
void
channel_inter_segment (Channel *mask, int x, int y, int width, int value)
{
PixelRegion maskPR;
unsigned char *data;
int val;
int x2;
void * pr;
/* check horizontal extents... */
x2 = x + width;
if (x2 < 0) x2 = 0;
if (x2 > GIMP_DRAWABLE(mask)->width) x2 = GIMP_DRAWABLE(mask)->width;
if (x < 0) x = 0;
if (x > GIMP_DRAWABLE(mask)->width) x = GIMP_DRAWABLE(mask)->width;
width = x2 - x;
if (!width) return;
if (y < 0 || y > GIMP_DRAWABLE(mask)->height)
return;
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, x, y, width, 1, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{
data = maskPR.data;
width = maskPR.w;
while (width--)
{
val = MINIMUM(*data, value);
*data++ = val;
}
}
}
void void
channel_combine_rect (Channel *mask, int op, int x, int y, int w, int h) channel_combine_rect (Channel *mask, int op, int x, int y, int w, int h)
{ {
int i; int i;
int x2, y2;
PixelRegion maskPR;
unsigned char color;
y2 = y + h;
x2 = x + w;
for (i = y; i < y + h; i++) x = BOUNDS (x, 0, GIMP_DRAWABLE(mask)->width);
{ y = BOUNDS (y, 0, GIMP_DRAWABLE(mask)->height);
if (i >= 0 && i < GIMP_DRAWABLE(mask)->height) x2 = BOUNDS (x2, 0, GIMP_DRAWABLE(mask)->width);
switch (op) y2 = BOUNDS (y2, 0, GIMP_DRAWABLE(mask)->height);
{
case ADD: case REPLACE: if (x2 - x <= 0 || y2 - y <= 0)
channel_add_segment (mask, x, i, w, 255); return;
break;
case SUB: pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, x, y,
channel_sub_segment (mask, x, i, w, 255); x2 - x, y2 - y, TRUE);
break; if (op == ADD || op == REPLACE)
case INTERSECT: color = 255;
channel_inter_segment (mask, x, i, w, 255); else
break; color = 0;
} color_region(&maskPR, &color);
}
/* Determine new boundary */ /* Determine new boundary */
if (mask->bounds_known && (op == ADD) && !mask->empty) if (mask->bounds_known && (op == ADD) && !mask->empty)
@ -933,9 +925,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
case SUB : case SUB :
channel_sub_segment (mask, x1, i, (x2 - x1), 255); channel_sub_segment (mask, x1, i, (x2 - x1), 255);
break; break;
case INTERSECT:
channel_inter_segment (mask, x1, i, (x2 - x1), 255);
break;
} }
} }
/* antialiasing */ /* antialiasing */
@ -965,7 +954,7 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
val = (int) (255 * (1 - (dist + 0.5))); val = (int) (255 * (1 - (dist + 0.5)));
else else
val = 0; val = 0;
if (last != val && last) if (last != val && last)
{ {
switch (op) switch (op)
@ -976,8 +965,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
case SUB: case SUB:
channel_sub_segment (mask, x0, i, j - x0, last); channel_sub_segment (mask, x0, i, j - x0, last);
break; break;
case INTERSECT:
channel_inter_segment (mask, x0, i, j - x0, last);
} }
} }
@ -985,6 +972,10 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
{ {
x0 = j; x0 = j;
last = val; last = val;
/* because we are symetric accross the y axis we can
skip ahead a bit if we are inside the ellipse*/
if (val == 255 && j < cx)
j = cx + (cx - j) - 1;
} }
} }
@ -994,8 +985,6 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
channel_add_segment (mask, x0, i, j - x0, last); channel_add_segment (mask, x0, i, j - x0, last);
else if (op == SUB) else if (op == SUB)
channel_sub_segment (mask, x0, i, j - x0, last); channel_sub_segment (mask, x0, i, j - x0, last);
else if (op == INTERSECT)
channel_inter_segment (mask, x0, i, j - x0, last);
} }
} }
@ -1032,18 +1021,81 @@ channel_combine_ellipse (Channel *mask, int op, int x, int y, int w, int h,
} }
static void
channel_combine_sub_region_add (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y, val;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
val = dest[x] + src[x];
if (val > 255)
dest[x] = 255;
else
dest[x] = val;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
static void
channel_combine_sub_region_sub (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
if (src[x] > dest[x])
dest[x] = 0;
else
dest[x]-= src[x];
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
static void
channel_combine_sub_region_intersect (void *unused,
PixelRegion *srcPR,
PixelRegion *destPR)
{
unsigned char *src, *dest;
int x, y;
src = srcPR->data;
dest = destPR->data;
for (y = 0; y < srcPR->h; y++)
{
for (x = 0; x < srcPR->w; x++)
{
dest[x] = MINIMUM(dest[x], src[x]);
}
src += srcPR->rowstride;
dest += destPR->rowstride;
}
}
void void
channel_combine_mask (Channel *mask, Channel *add_on, int op, channel_combine_mask (Channel *mask, Channel *add_on, int op,
int off_x, int off_y) int off_x, int off_y)
{ {
PixelRegion srcPR, destPR; PixelRegion srcPR, destPR;
unsigned char *src;
unsigned char *dest;
int val;
int x1, y1, x2, y2; int x1, y1, x2, y2;
int x, y;
int w, h; int w, h;
void * pr;
x1 = BOUNDS (off_x, 0, GIMP_DRAWABLE(mask)->width); x1 = BOUNDS (off_x, 0, GIMP_DRAWABLE(mask)->width);
y1 = BOUNDS (off_y, 0, GIMP_DRAWABLE(mask)->height); y1 = BOUNDS (off_y, 0, GIMP_DRAWABLE(mask)->height);
@ -1056,39 +1108,25 @@ channel_combine_mask (Channel *mask, Channel *add_on, int op,
pixel_region_init (&srcPR, GIMP_DRAWABLE(add_on)->tiles, (x1 - off_x), (y1 - off_y), w, h, FALSE); pixel_region_init (&srcPR, GIMP_DRAWABLE(add_on)->tiles, (x1 - off_x), (y1 - off_y), w, h, FALSE);
pixel_region_init (&destPR, GIMP_DRAWABLE(mask)->tiles, x1, y1, w, h, TRUE); pixel_region_init (&destPR, GIMP_DRAWABLE(mask)->tiles, x1, y1, w, h, TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) switch (op)
{ {
src = srcPR.data; case ADD: case REPLACE:
dest = destPR.data; pixel_regions_process_parallel ((p_func)channel_combine_sub_region_add,
NULL, 2, &srcPR, &destPR);
for (y = 0; y < srcPR.h; y++) break;
{ case SUB:
for (x = 0; x < srcPR.w; x++) pixel_regions_process_parallel ((p_func)channel_combine_sub_region_sub,
{ NULL, 2, &srcPR, &destPR);
switch (op) break;
{ case INTERSECT:
case ADD: case REPLACE: pixel_regions_process_parallel ((p_func)
val = dest[x] + src[x]; channel_combine_sub_region_intersect,
if (val > 255) val = 255; NULL, 2, &srcPR, &destPR);
break; break;
case SUB: default:
val = dest[x] - src[x]; g_message("Error: unknown opperation type in channel_combine_mask\n");
if (val < 0) val = 0; break;
break; }
case INTERSECT:
val = MINIMUM(dest[x], src[x]);
break;
default:
val = 0;
break;
}
dest[x] = val;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
}
mask->bounds_known = FALSE; mask->bounds_known = FALSE;
} }
@ -1184,57 +1222,35 @@ void
channel_invert (Channel *mask) channel_invert (Channel *mask)
{ {
PixelRegion maskPR; PixelRegion maskPR;
unsigned char *data; GimpLut *lut;
int size;
void * pr;
/* push the current channel onto the undo stack */ /* push the current channel onto the undo stack */
channel_push_undo (mask); channel_push_undo (mask);
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{ lut = invert_lut_new(1);
/* subtract each pixel in the mask from 255 */
data = maskPR.data;
size = maskPR.w * maskPR.h;
while (size --)
{
*data = 255 - *data;
data++;
}
}
pixel_regions_process_parallel ((p_func)gimp_lut_process_inline,
lut, 1, &maskPR);
gimp_lut_free(lut);
mask->bounds_known = FALSE; mask->bounds_known = FALSE;
} }
void void
channel_sharpen (Channel *mask) channel_sharpen (Channel *mask)
{ {
PixelRegion maskPR; PixelRegion maskPR;
unsigned char *data; GimpLut *lut;
int size;
void * pr;
/* push the current channel onto the undo stack */ /* push the current channel onto the undo stack */
channel_push_undo (mask); channel_push_undo (mask);
pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE); pixel_region_init (&maskPR, GIMP_DRAWABLE(mask)->tiles, 0, 0, GIMP_DRAWABLE(mask)->width, GIMP_DRAWABLE(mask)->height, TRUE);
for (pr = pixel_regions_register (1, &maskPR); pr != NULL; pr = pixel_regions_process (pr)) lut = threshold_lut_new(0.5, 1);
{
/* if a pixel in the mask has a non-zero value, make it 255 */
data = maskPR.data;
size = maskPR.w * maskPR.h;
while (size--)
{
if (*data > HALF_WAY)
*data++ = 255;
else
*data++ = 0;
}
}
mask->bounds_known = FALSE; pixel_regions_process_parallel ((p_func)gimp_lut_process_inline,
lut, 1, &maskPR);
gimp_lut_free(lut);
} }

View File

@ -19,27 +19,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "appenv.h"
#include "drawable.h" #include "drawable.h"
#include "equalize.h" #include "equalize.h"
#include "interface.h"
#include "gimage.h" #include "gimage.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "gimphistogram.h" #include "gimphistogram.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
struct hist_lut_struct
{
GimpHistogram *histogram;
int part[5][257];
};
static float equalize_lut_func(struct hist_lut_struct *hlut,
int nchannels, int channel, float value);
static void equalize (GImage *, GimpDrawable *, int); static void equalize (GImage *, GimpDrawable *, int);
static Argument * equalize_invoker (Argument *); static Argument * equalize_invoker (Argument *);
static GimpLut * eq_histogram_lut (GimpHistogram *hist, int bytes);
void void
@ -87,7 +77,7 @@ equalize(gimage, drawable, mask_only)
/* Build equalization LUT */ /* Build equalization LUT */
lut = eq_histogram_lut (hist, bytes); lut = eq_histogram_lut_new (hist, bytes);
/* Apply the histogram */ /* Apply the histogram */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
@ -105,71 +95,10 @@ equalize(gimage, drawable, mask_only)
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
} }
/* ------------------------------------------------------------------ */
/* --------------- The equalize procedure definition ---------------- */
/* ------------------------------------------------------------------ */
/*****/
static GimpLut *
eq_histogram_lut (GimpHistogram *hist, int bytes)
{
int i, k, j;
struct hist_lut_struct hlut;
double pixels_per_value;
double desired;
GimpLut *lut;
double sum, dif;
/* Find partition points */
pixels_per_value = gimp_histogram_get_count(hist, 0, 255) / 256.0;
for (k = 0; k < bytes; k++)
{
/* First and last points in partition */
hlut.part[k][0] = 0;
hlut.part[k][256] = 256;
/* Find intermediate points */
j = 0;
sum = gimp_histogram_get_channel(hist, k, 0) +
gimp_histogram_get_channel(hist, k, 1);
for (i = 1; i < 256; i++)
{
desired = i * pixels_per_value;
while (sum <= desired)
{
j++;
sum += gimp_histogram_get_channel(hist, k, j + 1);
}
/* Nearest sum */
dif = sum - gimp_histogram_get_channel(hist, k, j);
if ((sum - desired) > (dif / 2.0))
hlut.part[k][i] = j;
else
hlut.part[k][i] = j + 1;
}
}
lut = gimp_lut_new();
gimp_lut_setup(lut, (GimpLutFunc) equalize_lut_func,
(void *) &hlut, bytes);
return lut;
}
static float
equalize_lut_func(struct hist_lut_struct *hlut,
int nchannels, int channel, float value)
{
int i = 0, j;
j = (int)(value * 255.0 + 0.5);
while (hlut->part[channel][i + 1] <= j)
i++;
return i / 255.0;
}
/* The equalize procedure definition */
ProcArg equalize_args[] = ProcArg equalize_args[] =
{ {
{ PDB_DRAWABLE, { PDB_DRAWABLE,

View File

@ -24,6 +24,7 @@
#include "invert.h" #include "invert.h"
#include "gimage.h" #include "gimage.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -58,18 +59,6 @@ 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 */ /* Inverter */
static void static void
@ -79,10 +68,7 @@ invert (GimpDrawable *drawable)
int x1, y1, x2, y2; int x1, y1, x2, y2;
GimpLut *lut; GimpLut *lut;
lut = gimp_lut_new(); lut = invert_lut_new(gimp_drawable_bytes(drawable));
gimp_lut_setup_exact(lut, (GimpLutFunc) invert_lut_func,
(void *) NULL, gimp_drawable_bytes(drawable));
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); 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 (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
@ -97,8 +83,10 @@ invert (GimpDrawable *drawable)
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
} }
/* ------------------------------------------------------------------ */
/* ----------------- The invert procedure definition ---------------- */
/* ------------------------------------------------------------------ */
/* The invert procedure definition */
ProcArg invert_args[] = ProcArg invert_args[] =
{ {
{ PDB_DRAWABLE, { PDB_DRAWABLE,

View File

@ -640,7 +640,6 @@ gimp_drawable_init (GimpDrawable *drawable)
drawable->preview_valid = FALSE; drawable->preview_valid = FALSE;
drawable->parasites = parasite_list_new(); drawable->parasites = parasite_list_new();
drawable->tattoo = 0; drawable->tattoo = 0;
gimp_matrix_identity(drawable->transform);
drawable->ID = global_drawable_ID++; drawable->ID = global_drawable_ID++;
if (gimp_drawable_table == NULL) if (gimp_drawable_table == NULL)

View File

@ -21,7 +21,6 @@
#include "gimpobjectP.h" #include "gimpobjectP.h"
#include "gimpdrawable.h" #include "gimpdrawable.h"
#include "parasitelistF.h" #include "parasitelistF.h"
#include "libgimp/gimpmatrix.h"
struct _GimpDrawable struct _GimpDrawable
{ {
@ -43,10 +42,6 @@ struct _GimpDrawable
ParasiteList *parasites; /* Plug-in parasite data */ ParasiteList *parasites; /* Plug-in parasite data */
GimpMatrix transform; /* a matrix describing all of the
transformations this drawable
has undergone */
/* Preview variables */ /* Preview variables */
TempBuf *preview; /* preview of the channel */ TempBuf *preview; /* preview of the channel */
int preview_valid; /* is the preview valid? */ int preview_valid; /* is the preview valid? */

View File

@ -169,7 +169,6 @@ static void gimp_image_init (GimpImage *gimage)
gimage->comp_preview_valid[2] = FALSE; gimage->comp_preview_valid[2] = FALSE;
gimage->comp_preview = NULL; gimage->comp_preview = NULL;
gimage->parasites = parasite_list_new(); gimage->parasites = parasite_list_new();
gimp_matrix_identity(gimage->transform);
gimage->xresolution = default_xresolution; gimage->xresolution = default_xresolution;
gimage->yresolution = default_yresolution; gimage->yresolution = default_yresolution;
gimage->unit = default_units; gimage->unit = default_units;

View File

@ -10,7 +10,6 @@
#include "layer.h" #include "layer.h"
#include "parasitelistF.h" #include "parasitelistF.h"
#include "pathsP.h" #include "pathsP.h"
#include "libgimp/gimpmatrix.h"
#define MAX_CHANNELS 4 #define MAX_CHANNELS 4
@ -65,10 +64,6 @@ struct _GimpImage
PathsList *paths; /* Paths data for this image */ PathsList *paths; /* Paths data for this image */
GimpMatrix transform; /* a matrix describing all of the
transformations this image
has undergone */
int visible [MAX_CHANNELS]; /* visible channels */ int visible [MAX_CHANNELS]; /* visible channels */
int active [MAX_CHANNELS]; /* active channels */ int active [MAX_CHANNELS]; /* active channels */

View File

@ -160,6 +160,79 @@ gimp_lut_process (GimpLut *lut,
} }
} }
void
gimp_lut_process_inline (GimpLut *lut,
PixelRegion *srcPR)
{
int h, width, src_r_i;
unsigned char *src;
unsigned char *lut0 = NULL, *lut1 = NULL, *lut2 = NULL, *lut3 = NULL;
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;
width = srcPR->w;
src_r_i = srcPR->rowstride - (srcPR->bytes * srcPR->w);
if (src_r_i == 0)
{
width *= h;
h = 1;
}
while (h--)
{
switch (lut->nchannels)
{
case 1:
while (width--)
{
*src = lut0[*src];
src++;
}
break;
case 2:
while (width--)
{
src[0] = lut0[src[0]];
src[1] = lut1[src[1]];
src += 2;
}
break;
case 3:
while (width--)
{
src[0] = lut0[src[0]];
src[1] = lut1[src[1]];
src[2] = lut2[src[2]];
src += 3;
}
break;
case 4:
while (width--)
{
src[0] = lut0[src[0]];
src[1] = lut1[src[1]];
src[2] = lut2[src[2]];
src[3] = lut3[src[3]];
src += 4;
}
break;
default:
fprintf(stderr, "gimplut: Error: nchannels = %d\n", lut->nchannels);
}
width = srcPR->w;
src += src_r_i;
}
}
void void
gimp_lut_process_2 (PixelRegion *srcPR, gimp_lut_process_2 (PixelRegion *srcPR,
PixelRegion *destPR, PixelRegion *destPR,

View File

@ -49,6 +49,11 @@ void gimp_lut_process (GimpLut *lut,
PixelRegion *srcPR, PixelRegion *srcPR,
PixelRegion *destPR); PixelRegion *destPR);
/* gimp_lut_process_inline is like gimp_lut_process except it uses a
single PixelRegion as both the source and destination */
void gimp_lut_process_inline(GimpLut *lut,
PixelRegion *src_destPR);
/* gimp_lut_process_2 is the same as gimp_lut_process but the lut /* gimp_lut_process_2 is the same as gimp_lut_process but the lut
perameter is last instead of first. this is necesary because perameter is last instead of first. this is necesary because
pixel_region_process_paralell sends the user_data as the 1st pixel_region_process_paralell sends the user_data as the 1st

View File

@ -16,8 +16,12 @@
*/ */
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include <unistd.h>
#include "parasitelist.h" #include "parasitelist.h"
#include "gimpparasite.h" #include "gimpparasite.h"
#include "libgimp/parasite.h"
#include "libgimp/gimpenv.h"
static ParasiteList *parasites = NULL; static ParasiteList *parasites = NULL;
@ -26,6 +30,7 @@ gimp_init_parasites()
{ {
g_return_if_fail(parasites == NULL); g_return_if_fail(parasites == NULL);
parasites = parasite_list_new(); parasites = parasite_list_new();
gimp_parasiterc_load();
} }
void void
@ -64,5 +69,40 @@ gimp_parasite_list (gint *count)
return list; return list;
} }
void
gimp_parasiterc_save()
{
FILE *fp;
guint32 num, version = 1;
if (!(fp = fopen(gimp_personal_rc_file ("#parasiterc.tmp"), "w")))
return;
version = GINT32_TO_BE(version);
fwrite(&version, 4, 1, fp);
parasite_list_save(parasites, fp);
fclose(fp);
if (rename(gimp_personal_rc_file ("#parasiterc.tmp"),
gimp_personal_rc_file("parasiterc")) != 0)
unlink(gimp_personal_rc_file ("#parasiterc.tmp"));
}
void
gimp_parasiterc_load()
{
FILE *fp;
guint32 num, version;
if (!(fp = fopen(gimp_personal_rc_file ("parasiterc"), "r")))
return;
fread(&version, 4, 1, fp);
version = GINT32_FROM_BE(version);
if (version != 1)
{
fclose(fp);
return;
}
parasite_list_load(parasites, fp);
fclose(fp);
}

View File

@ -25,5 +25,7 @@ void gimp_attach_parasite (Parasite *p);
void gimp_detach_parasite (char *name); void gimp_detach_parasite (char *name);
Parasite * gimp_find_parasite (char *name); Parasite * gimp_find_parasite (char *name);
char ** gimp_parasite_list (gint *count); char ** gimp_parasite_list (gint *count);
void gimp_parasiterc_save (void);
void gimp_parasiterc_load (void);
#endif /* __GIMP_PARASITE_H__ */ #endif /* __GIMP_PARASITE_H__ */

View File

@ -22,7 +22,6 @@
#include "app_procs.h" #include "app_procs.h"
#include "airbrush.h" #include "airbrush.h"
#include "blend.h" #include "blend.h"
#include "brightness_contrast.h"
#include "brush_select.h" #include "brush_select.h"
#include "bucket_fill.h" #include "bucket_fill.h"
#include "gimpbrushlist.h" #include "gimpbrushlist.h"
@ -31,6 +30,7 @@
#include "channel_ops.h" #include "channel_ops.h"
#include "clone.h" #include "clone.h"
#include "color_balance.h" #include "color_balance.h"
#include "color_cmds.h"
#include "color_picker.h" #include "color_picker.h"
#include "convolve.h" #include "convolve.h"
#include "crop.h" #include "crop.h"
@ -51,14 +51,12 @@
#include "hue_saturation.h" #include "hue_saturation.h"
#include "invert.h" #include "invert.h"
#include "layer_cmds.h" #include "layer_cmds.h"
#include "levels.h"
#include "internal_procs.h" #include "internal_procs.h"
#include "paintbrush.h" #include "paintbrush.h"
#include "patterns.h" #include "patterns.h"
#include "pattern_select.h" #include "pattern_select.h"
#include "pencil.h" #include "pencil.h"
#include "perspective_tool.h" #include "perspective_tool.h"
#include "posterize.h"
#include "rect_select.h" #include "rect_select.h"
#include "rotate_tool.h" #include "rotate_tool.h"
#include "scale_tool.h" #include "scale_tool.h"

View File

@ -24,6 +24,7 @@
#include "invert.h" #include "invert.h"
#include "gimage.h" #include "gimage.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -58,18 +59,6 @@ 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 */ /* Inverter */
static void static void
@ -79,10 +68,7 @@ invert (GimpDrawable *drawable)
int x1, y1, x2, y2; int x1, y1, x2, y2;
GimpLut *lut; GimpLut *lut;
lut = gimp_lut_new(); lut = invert_lut_new(gimp_drawable_bytes(drawable));
gimp_lut_setup_exact(lut, (GimpLutFunc) invert_lut_func,
(void *) NULL, gimp_drawable_bytes(drawable));
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2); 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 (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
@ -97,8 +83,10 @@ invert (GimpDrawable *drawable)
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1)); drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
} }
/* ------------------------------------------------------------------ */
/* ----------------- The invert procedure definition ---------------- */
/* ------------------------------------------------------------------ */
/* The invert procedure definition */
ProcArg invert_args[] = ProcArg invert_args[] =
{ {
{ PDB_DRAWABLE, { PDB_DRAWABLE,

View File

@ -31,6 +31,7 @@
#include "interface.h" #include "interface.h"
#include "levels.h" #include "levels.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -141,61 +142,6 @@ static gint levels_output_da_events (GtkWidget *, GdkEvent *,
static void levels_histogram_range (HistogramWidget *, int, int, static void levels_histogram_range (HistogramWidget *, int, int,
void *); void *);
static Argument * levels_invoker (Argument *);
/* levels machinery */
static float
levels_lut_func(LevelsDialog *ld,
int nchannels, int channel, float value)
{
double inten;
int j;
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;
/* 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]);
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]));
}
/* 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]));
inten /= 255.0;
}
return inten;
}
static void static void
levels_histogram_range (HistogramWidget *h, levels_histogram_range (HistogramWidget *h,
@ -715,8 +661,9 @@ levels_update (LevelsDialog *ld,
/* Recalculate the transfer arrays */ /* Recalculate the transfer arrays */
levels_calculate_transfers (ld); levels_calculate_transfers (ld);
/* set up the lut */ /* set up the lut */
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func, levels_lut_setup(ld->lut, ld->gamma, ld->low_input, ld->high_input,
(void *) ld, gimp_drawable_bytes(ld->drawable)); ld->low_output, ld->high_output,
gimp_drawable_bytes(ld->drawable));
if (update & LOW_INPUT) if (update & LOW_INPUT)
{ {
@ -1005,8 +952,9 @@ levels_ok_callback (GtkWidget *widget,
if (!ld->preview) if (!ld->preview)
{ {
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func, levels_lut_setup(ld->lut, ld->gamma, ld->low_input, ld->high_input,
(void *) ld, gimp_drawable_bytes(ld->drawable)); ld->low_output, ld->high_output,
gimp_drawable_bytes(ld->drawable));
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut); (void *) ld->lut);
} }
@ -1359,204 +1307,3 @@ levels_output_da_events (GtkWidget *widget,
} }
/* The levels procedure definition */
ProcArg levels_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"channel",
"the channel to modify: { VALUE (0), RED (1), GREEN (2), BLUE (3), GRAY (0) }"
},
{ PDB_INT32,
"low_input",
"intensity of lowest input: (0 <= low_input <= 255)"
},
{ PDB_INT32,
"high_input",
"intensity of highest input: (0 <= high_input <= 255)"
},
{ PDB_FLOAT,
"gamma",
"gamma correction factor: (0.1 <= gamma <= 10)"
},
{ PDB_INT32,
"low_output",
"intensity of lowest output: (0 <= low_input <= 255)"
},
{ PDB_INT32,
"high_output",
"intensity of highest output: (0 <= high_input <= 255)"
}
};
ProcRecord levels_proc =
{
"gimp_levels",
"Modifies intensity levels in the specified drawable",
"This tool allows intensity levels in the specified drawable to be remapped according to a set of parameters. The low/high input levels specify an initial mapping from the source intensities. The gamma value determines how intensities between the low and high input intensities are interpolated. A gamma value of 1.0 results in a linear interpolation. Higher gamma values result in more high-level intensities. Lower gamma values result in more low-level intensities. The low/high output levels constrain the final intensity mapping--that is, no final intensity will be lower than the low output level and no final intensity will be higher than the high output level. This tool is only valid on RGB color and grayscale images. It will not operate on indexed drawables.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1995-1996",
PDB_INTERNAL,
/* Input arguments */
7,
levels_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { levels_invoker } },
};
static Argument *
levels_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
LevelsDialog ld;
GimpDrawable *drawable;
int channel;
int low_input;
int high_input;
double gamma;
int low_output;
int high_output;
int int_value;
double fp_value;
int x1, y1, x2, y2;
int i;
drawable = NULL;
low_input = 0;
high_input = 0;
gamma = 1.0;
low_output = 0;
high_output = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* channel */
if (success)
{
int_value = args[1].value.pdb_int;
if (success)
{
if (drawable_gray (drawable))
{
if (int_value != 0)
success = FALSE;
}
else if (drawable_color (drawable))
{
if (int_value < 0 || int_value > 3)
success = FALSE;
}
else
success = FALSE;
}
channel = int_value;
}
/* low input */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value >= 0 && int_value < 256)
low_input = int_value;
else
success = FALSE;
}
/* high input */
if (success)
{
int_value = args[3].value.pdb_int;
if (int_value >= 0 && int_value < 256)
high_input = int_value;
else
success = FALSE;
}
/* gamma */
if (success)
{
fp_value = args[4].value.pdb_float;
if (fp_value >= 0.1 && fp_value <= 10.0)
gamma = fp_value;
else
success = FALSE;
}
/* low output */
if (success)
{
int_value = args[5].value.pdb_int;
if (int_value >= 0 && int_value < 256)
low_output = int_value;
else
success = FALSE;
}
/* high output */
if (success)
{
int_value = args[6].value.pdb_int;
if (int_value >= 0 && int_value < 256)
high_output = int_value;
else
success = FALSE;
}
/* arrange to modify the levels */
if (success)
{
for (i = 0; i < 5; i++)
{
ld.low_input[i] = 0;
ld.gamma[i] = 1.0;
ld.high_input[i] = 255;
ld.low_output[i] = 0;
ld.high_output[i] = 255;
}
ld.lut = gimp_lut_new();
ld.channel = channel;
ld.color = drawable_color (drawable);
ld.low_input[channel] = low_input;
ld.high_input[channel] = high_input;
ld.gamma[channel] = gamma;
ld.low_output[channel] = low_output;
ld.high_output[channel] = high_output;
/* 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);
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);
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));
}
return procedural_db_return_args (&levels_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __LEVELS_H__ #define __LEVELS_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* hue-saturation functions */ /* hue-saturation functions */
Tool * tools_new_levels (void); Tool * tools_new_levels (void);
@ -28,7 +27,4 @@ void tools_free_levels (Tool *);
void levels_initialize (GDisplay *); void levels_initialize (GDisplay *);
void levels_free (void); void levels_free (void);
/* Procedure definition and marshalling function */
extern ProcRecord levels_proc;
#endif /* __LEVELS_H__ */ #endif /* __LEVELS_H__ */

417
app/lut_funcs.c Normal file
View File

@ -0,0 +1,417 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "gimplut.h"
#include "gimphistogram.h"
#include <stdio.h>
#include <math.h>
#include <glib.h>
/* ---------- Brightness/Contrast -----------*/
typedef struct B_C_struct
{
double brightness;
double contrast;
} B_C_struct;
static float
brightness_contrast_lut_func(B_C_struct *data,
int nchannels, int channel, float value)
{
float nvalue;
double power;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (data->brightness < 0.0)
value = value * (1.0 + data->brightness);
else
value = value + ((1.0 - value) * data->brightness);
/* apply contrast */
if (data->contrast < 0.0)
{
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) (1.0 + data->contrast));
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
else
{
if (value > 0.5)
nvalue = 1.0 - value;
else
nvalue = value;
if (nvalue < 0.0)
nvalue = 0.0;
power = (data->contrast == 1.0) ? 127 : 1.0 / (1.0 - data->contrast);
nvalue = 0.5 * pow (2.0 * nvalue, power);
if (value > 0.5)
value = 1.0 - nvalue;
else
value = nvalue;
}
return value;
}
void
brightness_contrast_lut_setup(GimpLut *lut, double brightness, double contrast,
int nchannels)
{
B_C_struct data;
data.brightness = brightness;
data.contrast = contrast;
gimp_lut_setup(lut, (GimpLutFunc) brightness_contrast_lut_func,
(void *) &data, nchannels);
}
GimpLut *
brightness_contrast_lut_new(double brightness, double contrast,
int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
brightness_contrast_lut_setup(lut, brightness, contrast, nchannels);
return lut;
}
/* ---------------- invert ------------------ */
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;
}
void
invert_lut_setup(GimpLut *lut, int nchannels)
{
gimp_lut_setup_exact(lut, (GimpLutFunc) invert_lut_func,
NULL , nchannels);
}
GimpLut *
invert_lut_new(int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
invert_lut_setup(lut, nchannels);
return lut;
}
/* ---------------- add (or subract)------------------ */
static float
add_lut_func(double *ammount,
int nchannels, int channel, float value)
{
/* don't change the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
return (value + *ammount);
}
void
add_lut_setup(GimpLut *lut, double ammount, int nchannels)
{
gimp_lut_setup(lut, (GimpLutFunc) add_lut_func,
(void *) &ammount , nchannels);
}
GimpLut *
add_lut_new(double ammount, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
add_lut_setup(lut, ammount, nchannels);
return lut;
}
/* ---------------- intersect (MINIMUM(pixel, value)) ------------------ */
static float
intersect_lut_func(double *min,
int nchannels, int channel, float value)
{
/* don't change the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
return MIN(value, *min);
}
void
intersect_lut_setup(GimpLut *lut, double value, int nchannels)
{
gimp_lut_setup_exact(lut, (GimpLutFunc) intersect_lut_func,
(void *) &value , nchannels);
}
GimpLut *
intersect_lut_new(double value, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
intersect_lut_setup(lut, value, nchannels);
return lut;
}
/* ---------------- Threshold ------------------ */
static float
threshold_lut_func(double *min,
int nchannels, int channel, float value)
{
/* don't change the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
if (value < *min)
return 0.0;
return 1.0;
}
void
threshold_lut_setup(GimpLut *lut, double value, int nchannels)
{
gimp_lut_setup_exact(lut, (GimpLutFunc) threshold_lut_func,
(void *) &value , nchannels);
}
GimpLut *
threshold_lut_new(double value, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
threshold_lut_setup(lut, value, nchannels);
return lut;
}
/* ------------- levels ------------ */
typedef struct
{
double *gamma;
int *low_input;
int *high_input;
int *low_output;
int *high_output;
} levels_struct;
static float
levels_lut_func(levels_struct *data,
int nchannels, int channel, float value)
{
double inten;
int j;
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;
/* determine input intensity */
if (data->high_input[j] != data->low_input[j])
inten = (double) (255.0*inten - data->low_input[j]) /
(double) (data->high_input[j] - data->low_input[j]);
else
inten = (double) (255.0*inten - data->low_input[j]);
if (data->gamma[j] != 0.0)
{
if (inten >= 0.0)
inten = pow ( inten, (1.0 / data->gamma[j]));
else
inten = -pow (-inten, (1.0 / data->gamma[j]));
}
/* determine the output intensity */
if (data->high_output[j] >= data->low_output[j])
inten = (double) (inten * (data->high_output[j] - data->low_output[j]) +
data->low_output[j]);
else if (data->high_output[j] < data->low_output[j])
inten = (double) (data->low_output[j] - inten *
(data->low_output[j] - data->high_output[j]));
inten /= 255.0;
}
return inten;
}
void
levels_lut_setup(GimpLut *lut, double *gamma, int *low_input, int *high_input,
int *low_output, int *high_output, int nchannels)
{
levels_struct data;
data.gamma = gamma;
data.low_input = low_input;
data.high_input = high_input;
data.low_output = low_output;
data.high_output = high_output;
gimp_lut_setup(lut, (GimpLutFunc) levels_lut_func,
(void *) &data, nchannels);
}
GimpLut *
levels_lut_new(double *gamma, int *low_input, int *high_input,
int *low_output, int *high_output, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
levels_lut_setup(lut, gamma, low_input, high_input,
low_output, high_output, nchannels);
return lut;
}
/* --------------- posterize ---------------- */
static float
posterize_lut_func(int *ilevels,
int nchannels, int channel, float value)
{
int levels;
/* don't posterize the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
if (*ilevels < 2)
levels = 2;
else
levels = *ilevels;
value = rint(value * (levels - 1.0)) / (levels - 1.0);
return value;
}
void
posterize_lut_setup(GimpLut *lut, int levels, int nchannels)
{
gimp_lut_setup_exact(lut, (GimpLutFunc) posterize_lut_func,
(void *) &levels , nchannels);
}
GimpLut *
posterize_lut_new(int levels, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
posterize_lut_setup(lut, levels, nchannels);
return lut;
}
/* --------------- equalize ------------- */
struct hist_lut_struct
{
GimpHistogram *histogram;
int part[5][257];
};
static float
equalize_lut_func(struct hist_lut_struct *hlut,
int nchannels, int channel, float value)
{
int i = 0, j;
j = (int)(value * 255.0 + 0.5);
while (hlut->part[channel][i + 1] <= j)
i++;
return i / 255.0;
}
void
eq_histogram_lut_setup (GimpLut *lut, GimpHistogram *hist, int bytes)
{
int i, k, j;
struct hist_lut_struct hlut;
double pixels_per_value;
double desired;
double sum, dif;
/* Find partition points */
pixels_per_value = gimp_histogram_get_count(hist, 0, 255) / 256.0;
for (k = 0; k < bytes; k++)
{
/* First and last points in partition */
hlut.part[k][0] = 0;
hlut.part[k][256] = 256;
/* Find intermediate points */
j = 0;
sum = gimp_histogram_get_channel(hist, k, 0) +
gimp_histogram_get_channel(hist, k, 1);
for (i = 1; i < 256; i++)
{
desired = i * pixels_per_value;
while (sum <= desired)
{
j++;
sum += gimp_histogram_get_channel(hist, k, j + 1);
}
/* Nearest sum */
dif = sum - gimp_histogram_get_channel(hist, k, j);
if ((sum - desired) > (dif / 2.0))
hlut.part[k][i] = j;
else
hlut.part[k][i] = j + 1;
}
}
gimp_lut_setup(lut, (GimpLutFunc) equalize_lut_func,
(void *) &hlut, bytes);
}
GimpLut *
eq_histogram_lut_new(GimpHistogram *h, int nchannels)
{
GimpLut *lut;
lut = gimp_lut_new();
eq_histogram_lut_setup(lut, h, nchannels);
return lut;
}

62
app/lut_funcs.h Normal file
View File

@ -0,0 +1,62 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __LUT_FUNCS_H__
#define __LUT_FUNCS_H__
#include "gimplutF.h"
#include "gimphistogramF.h"
/* brightness contrast */
void brightness_contrast_lut_setup (GimpLut *lut,
double brightness, double contrast,
int nchannels);
GimpLut *brightness_contrast_lut_new (double brightness, double contrast,
int nchannels);
/* invert */
void invert_lut_setup (GimpLut *lut, int nchannels);
GimpLut *invert_lut_new (int nchannels);
/* add (or subtract) */
void add_lut_setup (GimpLut *lut, double ammount, int nchannels);
GimpLut *add_lut_new (double ammount, int nchannels);
/* intersect (MINIMUM(pixel, value)) */
void intersect_lut_setup (GimpLut *lut, double value, int nchannels);
GimpLut *intersect_lut_new (double value, int nchannels);
/* threshold */
void threshold_lut_setup (GimpLut *lut, double value, int nchannels);
GimpLut *threshold_lut_new (double value, int nchannels);
/* levels */
void levels_lut_setup (GimpLut *lut, double *gamma,
int *low_input, int *high_input,
int *low_output, int *high_output, int nchannels);
GimpLut *levels_lut_new (double *gamma, int *low_input, int *high_input,
int *low_output, int *high_output, int nchannels);
/* posterize */
void posterize_lut_setup (GimpLut *lut, int levels, int nchannels);
GimpLut *posterize_lut_new (int levels, int nchannels);
/* equalize histogram */
void eq_histogram_lut_setup (GimpLut *lut, GimpHistogram *hist, int bytes);
GimpLut *eq_histogram_lut_new (GimpHistogram *h, int nchannels);
#endif /* __LUT_FUNCS_H__ */

View File

@ -214,6 +214,42 @@ parasite_list_find(ParasiteList *list, const char *name)
return NULL; return NULL;
} }
static int saved_bytes;
static void
save_a_parasite(char *key, Parasite *p, FILE *fp)
{
if (parasite_is_persistent(p))
saved_bytes += parasite_save(p, fp);
}
int
parasite_list_save(ParasiteList *list, FILE *fp)
{
guint32 num;
num = parasite_list_persistent_length (list);
num = GINT32_TO_BE(num);
fwrite(&num, 4, 1, fp);
saved_bytes = 4;
parasite_list_foreach(list, (GHFunc)save_a_parasite, fp);
return saved_bytes;
}
void
parasite_list_load(ParasiteList *list, FILE *fp)
{
Parasite *p;
guint32 num, version;
num = 0;
fread(&num, 4, 1, fp);
num = GINT32_FROM_BE(num);
while (num--)
{
p = parasite_load(fp);
parasite_list_add(list, p);
parasite_free(p);
}
}
void void
parasite_shift_parent(Parasite *p) parasite_shift_parent(Parasite *p)

View File

@ -19,6 +19,7 @@
#define __PARASITE_LIST_H__ #define __PARASITE_LIST_H__
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include "libgimp/parasiteF.h" #include "libgimp/parasiteF.h"
#include "parasitelistF.h" #include "parasitelistF.h"
#include "gimpobject.h" #include "gimpobject.h"
@ -46,6 +47,8 @@ void parasite_list_foreach (ParasiteList *list, GHFunc function,
gpointer user_data); gpointer user_data);
Parasite *parasite_list_find (ParasiteList *list, const char *name); Parasite *parasite_list_find (ParasiteList *list, const char *name);
int parasite_list_save (ParasiteList *list, FILE *fp);
void parasite_list_load (ParasiteList *list, FILE *fp);
void parasite_shift_parent (Parasite *p); void parasite_shift_parent (Parasite *p);
#endif /* __GIMP_PARASITE_H__ */ #endif /* __GIMP_PARASITE_H__ */

292
app/pixel_processor.c Normal file
View File

@ -0,0 +1,292 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* pixel_processor.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 "../config.h"
#include "pixel_processor.h"
#include "pixel_region.h"
#include "gimprc.h"
#include <stdarg.h>
#include <stdio.h>
#ifdef ENABLE_MP
#include <pthread.h>
#define IF_THREAD(statement) statement
#else /* !USE_PTHREADS */
#define IF_THREAD(statement)
#endif /* !USE_PTHREADS */
typedef void (*p1_func)(void *, PixelRegion *);
typedef void (*p2_func)(void *, PixelRegion * ,PixelRegion *);
typedef void (*p3_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *);
typedef void (*p4_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *,
PixelRegion *);
typedef struct _PixelRegionIterator PixelRegionIterator;
struct _PixelProcessor
{
void *data;
p_func f;
PixelRegionIterator *PRI;
IF_THREAD(pthread_mutex_t mutex;)
int nthreads;
int n_regions;
PixelRegion *r[4];
void *progress_report_data;
ProgressReportFunc progress_report_func;
};
static void *
do_parallel_regions(PixelProcessor *p_s)
{
PixelRegion tr[4];
int ntiles = 0;
int i;
int cont = 1;
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
if (p_s->nthreads != 0 && p_s->PRI)
p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI);
if (p_s->PRI == NULL)
{
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
p_s->nthreads++;
do
{
for (i = 0; i < p_s->n_regions; i++)
if (p_s->r[i])
memcpy(&tr[i], p_s->r[i], sizeof(PixelRegion));
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
ntiles++;
switch(p_s->n_regions)
{
case 1:
((p1_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL);
break;
case 2:
((p2_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL);
break;
case 3:
((p3_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL);
break;
case 4:
((p4_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL,
p_s->r[3] ? &tr[3] : NULL);
break;
default:
g_message("do_parallel_regions: Bad number of regions %d\n",
p_s->n_regions);
}
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
if (p_s->progress_report_func)
if (!p_s->progress_report_func(p_s->progress_report_data,
p_s->r[0]->x, p_s->r[0]->y,
p_s->r[0]->w, p_s->r[0]->h))
cont = 0;
} while (cont && p_s->PRI &&
(p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI)));
p_s->nthreads--;
/* fprintf(stderr, "processed %d tiles\n", ntiles); */
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
#define MAX_THREADS 30
static void
pixel_regions_do_parallel(PixelProcessor *p_s)
{
int i;
IF_THREAD(int nthreads;)
IF_THREAD(pthread_t threads[MAX_THREADS];)
IF_THREAD(pthread_attr_t pthread_attr;)
/* (p_s->PRI->region_width * p_s->PRI->region_height) /(64*64)); */
IF_THREAD(
nthreads = MIN(num_processors, 5);
if (nthreads > 1)
{
pthread_attr_init (&pthread_attr);
for (i = 0; i < nthreads; i++)
{
pthread_create (&threads[i], &pthread_attr,
(void *(*)(void *)) do_parallel_regions,
p_s);
}
for (i = 0; i < nthreads; i++)
{
pthread_join(threads[i], NULL);
}
}
else
)
do_parallel_regions(p_s);
if (p_s->nthreads != 0)
fprintf(stderr, "Ack, we lost a thread\n");
}
static PixelProcessor *
pixel_regions_real_process_parallel(p_func f, void *data,
ProgressReportFunc report_func,
void *report_data,
int num_regions, va_list ap)
{
int i;
PixelProcessor *p_s;
p_s = g_new(PixelProcessor, 200);
for (i = 0; i < num_regions; i++)
p_s->r[i] = va_arg (ap, PixelRegion *);
switch(num_regions)
{
case 1:
p_s->PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s->r[0]);
break;
case 2:
p_s->PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s->r[0],
p_s->r[1]);
break;
case 3:
p_s->PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s->r[0],
p_s->r[1],
p_s->r[2]);
break;
case 4:
p_s->PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s->r[0],
p_s->r[1],
p_s->r[2],
p_s->r[3]);
break;
default:
g_message("pixel_regions_real_process_parallel: Bad number of regions %d\n",
p_s->n_regions);
}
if (!p_s->PRI)
{
pixel_processor_free(p_s);
return NULL;
}
p_s->f = f;
p_s->data = data;
p_s->n_regions = num_regions;
IF_THREAD(pthread_mutex_init(&(p_s->mutex), NULL);)
p_s->nthreads = 0;
p_s->progress_report_data = report_data;
p_s->progress_report_func = report_func;
pixel_regions_do_parallel(p_s);
if (p_s->PRI)
return p_s;
pixel_processor_free (p_s);
return NULL;
}
void
pixel_regions_process_parallel(p_func f, void *data, int num_regions, ...)
{
va_list va;
va_start (va, num_regions);
pixel_regions_real_process_parallel(f, data, NULL, NULL, num_regions, va);
va_end (va);
}
PixelProcessor *
pixel_regions_process_parallel_progress(p_func f, void *data,
ProgressReportFunc progress_func,
void *progress_data, int num_regions,
...)
{
PixelProcessor *ret;
va_list va;
va_start (va, num_regions);
ret = pixel_regions_real_process_parallel(f, data,
progress_func, progress_data,
num_regions, va);
va_end (va);
return ret;
}
void
pixel_processor_stop(PixelProcessor *pp)
{
if (!pp)
return;
if (pp->PRI)
{
pixel_regions_process_stop (pp->PRI);
pp->PRI = NULL;
}
pixel_processor_free(pp);
}
PixelProcessor *
pixel_processor_cont(PixelProcessor *pp)
{
pixel_regions_do_parallel(pp);
if (pp->PRI)
return pp;
pixel_processor_free (pp);
return NULL;
}
void
pixel_processor_free (PixelProcessor *pp)
{
if (pp->PRI)
pixel_processor_stop(pp);
else
g_free(pp);
}

40
app/pixel_processor.h Normal file
View File

@ -0,0 +1,40 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* pixel_processor.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 __PIXEL_PROCESSOR_H__
#define __PIXEL_PROCESSOR_H__
typedef struct _PixelProcessor PixelProcessor;
typedef void (*p_func)(void);
typedef int (*ProgressReportFunc)(void *, int, int, int, int);
void pixel_regions_process_parallel (p_func f, void *data, int num_regions,
...);
PixelProcessor *pixel_process_progress (p_func f, void *data,
ProgressReportFunc progress_func,
void *progress_data,
int num_regions, ...);
void pixel_processor_free (PixelProcessor *);
void pixel_processor_stop (PixelProcessor *);
PixelProcessor *pixel_processor_cont (PixelProcessor *);
#endif /* __PIXEL_PROCESSOR_H__ */

View File

@ -26,18 +26,6 @@
#include "tile_manager_pvt.h" #include "tile_manager_pvt.h"
#include "tile.h" /* ick. */ #include "tile.h" /* ick. */
#ifdef ENABLE_MP
#include <pthread.h>
#define IF_THREAD(statement) statement
#else /* !USE_PTHREADS */
#define IF_THREAD(statement)
#endif /* !USE_PTHREADS */
typedef struct _PixelRegionHolder PixelRegionHolder; typedef struct _PixelRegionHolder PixelRegionHolder;
@ -303,159 +291,6 @@ pixel_region_set_col (PR, x, y, h, data)
} }
} }
typedef void (*p1_func)(void *, PixelRegion *);
typedef void (*p2_func)(void *, PixelRegion * ,PixelRegion *);
typedef void (*p3_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *);
typedef void (*p4_func)(void *, PixelRegion * ,PixelRegion *, PixelRegion *,
PixelRegion *);
struct parallel_struct
{
void *data;
p_func f;
PixelRegionIterator *PRI;
IF_THREAD(pthread_mutex_t mutex;)
int nthreads;
int n_regions;
PixelRegion *r[4];
};
static void *
do_parallel_regions(struct parallel_struct *p_s)
{
PixelRegion tr[4];
int ntiles = 0;
int i;
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
if (p_s->nthreads != 0 && p_s->PRI)
p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI);
if (p_s->PRI == NULL)
{
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
p_s->nthreads++;
do
{
for (i = 0; i < p_s->n_regions; i++)
if (p_s->r[i])
memcpy(&tr[i], p_s->r[i], sizeof(PixelRegion));
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
ntiles++;
switch(p_s->n_regions)
{
case 1:
((p1_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL);
break;
case 2:
((p2_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL);
break;
case 3:
((p3_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL);
break;
case 4:
((p4_func)p_s->f)(p_s->data,
p_s->r[0] ? &tr[0] : NULL,
p_s->r[1] ? &tr[1] : NULL,
p_s->r[2] ? &tr[2] : NULL,
p_s->r[3] ? &tr[3] : NULL);
break;
default:
g_message("do_parallel_regions: Bad number of regions %d\n",
p_s->n_regions);
}
IF_THREAD(pthread_mutex_lock(&p_s->mutex);)
} while (p_s->PRI && (p_s->PRI = (PixelRegionIterator*)pixel_regions_process(p_s->PRI)));
p_s->nthreads--;
/* fprintf(stderr, "processed %d tiles\n", ntiles); */
IF_THREAD(pthread_mutex_unlock(&p_s->mutex);)
return NULL;
}
#define MAX_THREADS 30
void pixel_regions_process_parallel(p_func f, void *data, int num_regions, ...)
{
int i;
struct parallel_struct p_s;
IF_THREAD(pthread_t threads[MAX_THREADS];)
IF_THREAD(pthread_attr_t pthread_attr;)
IF_THREAD(int nthreads;)
va_list ap;
va_start (ap, num_regions);
for (i = 0; i < num_regions; i++)
p_s.r[i] = va_arg (ap, PixelRegion *);
va_end (ap);
switch(num_regions)
{
case 1:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0]);
break;
case 2:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1]);
break;
case 3:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1],
p_s.r[2]);
break;
case 4:
p_s.PRI = (PixelRegionIterator *) pixel_regions_register(num_regions,
p_s.r[0],
p_s.r[1],
p_s.r[2],
p_s.r[3]);
break;
default:
g_message("pixel_regions_process_parallel: Bad number of regions %d\n",
p_s.n_regions);
}
if (!p_s.PRI)
return;
p_s.f = f;
p_s.data = data;
p_s.n_regions = num_regions;
IF_THREAD(pthread_mutex_init(&p_s.mutex, NULL);)
p_s.nthreads = 0;
IF_THREAD(
nthreads = MIN(num_processors,
(p_s.PRI->region_width * p_s.PRI->region_height) /(64*64));
if (nthreads > 1)
{
pthread_attr_init (&pthread_attr);
for (i = 0; i < nthreads; i++)
{
pthread_create (&threads[i], &pthread_attr,
(void *(*)(void *)) do_parallel_regions,
&p_s);
}
for (i = 0; i < nthreads; i++)
{
pthread_join(threads[i], NULL);
}
}
else
)
do_parallel_regions(&p_s);
if (p_s.nthreads != 0)
fprintf(stderr, "Ack, we've lost a thread.");
}
void * void *
pixel_regions_register (int num_regions, ...) pixel_regions_register (int num_regions, ...)
{ {

View File

@ -19,6 +19,7 @@
#define __PIXEL_REGION_H__ #define __PIXEL_REGION_H__
#include "tile_manager.h" #include "tile_manager.h"
#include "pixel_processor.h" /* this is temporary, */
typedef struct _PixelRegion PixelRegion; typedef struct _PixelRegion PixelRegion;
@ -36,7 +37,6 @@ struct _PixelRegion
int process_count; /* used internally */ int process_count; /* used internally */
}; };
typedef void (*p_func)(void);
/* PixelRegion functions */ /* PixelRegion functions */
void pixel_region_init (PixelRegion *, TileManager *, int, int, int, int, int); void pixel_region_init (PixelRegion *, TileManager *, int, int, int, int, int);
@ -48,8 +48,6 @@ void pixel_region_set_row (PixelRegion *, int, int, int, unsigned char *)
void pixel_region_get_col (PixelRegion *, int, int, int, unsigned char *, int); void pixel_region_get_col (PixelRegion *, int, int, int, unsigned char *, int);
void pixel_region_set_col (PixelRegion *, int, int, int, unsigned char *); void pixel_region_set_col (PixelRegion *, int, int, int, unsigned char *);
void *pixel_regions_register (int, ...); void *pixel_regions_register (int, ...);
void pixel_regions_process_parallel (p_func f, void *data, int num_regions,
...);
void *pixel_regions_process (void *); void *pixel_regions_process (void *);
void pixel_regions_process_stop (void *); void pixel_regions_process_stop (void *);

View File

@ -34,6 +34,7 @@
#include "interface.h" #include "interface.h"
#include "posterize.h" #include "posterize.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -84,29 +85,6 @@ static void posterize_preview_update (GtkWidget *, gpointer);
static void posterize_levels_text_update (GtkWidget *, gpointer); static void posterize_levels_text_update (GtkWidget *, gpointer);
static gint posterize_delete_callback (GtkWidget *, GdkEvent *, gpointer); static gint posterize_delete_callback (GtkWidget *, GdkEvent *, gpointer);
static Argument * posterize_invoker (Argument *);
/* posterize machinery */
static float
posterize_lut_func(PosterizeDialog *pd,
int nchannels, int channel, float value)
{
int levels;
/* don't posterize the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
if (pd->levels < 2)
levels = 2;
else
levels = pd->levels;
value = rint(value * (pd->levels - 1.0)) / (pd->levels - 1.0);
return value;
}
/* by_color select action functions */ /* by_color select action functions */
@ -343,8 +321,7 @@ posterize_preview (PosterizeDialog *pd)
if (!pd->image_map) if (!pd->image_map)
g_message (_("posterize_preview(): No image map")); g_message (_("posterize_preview(): No image map"));
active_tool->preserve = TRUE; active_tool->preserve = TRUE;
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func, posterize_lut_setup(pd->lut, pd->levels, gimp_drawable_bytes(pd->drawable));
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut); (void *) pd->lut);
active_tool->preserve = FALSE; active_tool->preserve = FALSE;
@ -365,8 +342,8 @@ posterize_ok_callback (GtkWidget *widget,
if (!pd->preview) if (!pd->preview)
{ {
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func, posterize_lut_setup(pd->lut, pd->levels,
(void *) pd, gimp_drawable_bytes(pd->drawable)); gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut); (void *) pd->lut);
} }
@ -444,100 +421,3 @@ posterize_levels_text_update (GtkWidget *w,
} }
} }
/* The posterize procedure definition */
ProcArg posterize_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"levels",
"levels of posterization: (2 <= levels <= 255)"
}
};
ProcRecord posterize_proc =
{
"gimp_posterize",
"Posterize the specified drawable",
"This procedures reduces the number of shades allows in each intensity channel to the specified 'levels' parameter.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997",
PDB_INTERNAL,
/* Input arguments */
2,
posterize_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { posterize_invoker } },
};
static Argument *
posterize_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
PosterizeDialog pd;
GImage *gimage;
GimpDrawable *drawable;
int levels;
int int_value;
int x1, y1, x2, y2;
drawable = NULL;
levels = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
else
gimage = drawable_gimage (drawable);
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* levels */
if (success)
{
int_value = args[1].value.pdb_int;
if (int_value >= 2 && int_value < 256)
levels = int_value;
else
success = FALSE;
}
/* arrange to modify the levels */
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);
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));
}
return procedural_db_return_args (&posterize_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __POSTERIZE_H__ #define __POSTERIZE_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* by_color select functions */ /* by_color select functions */
Tool * tools_new_posterize (void); Tool * tools_new_posterize (void);
@ -27,7 +26,4 @@ void tools_free_posterize (Tool *);
void posterize_initialize (GDisplay *); void posterize_initialize (GDisplay *);
/* Procedure definition and marshalling function */
extern ProcRecord posterize_proc;
#endif /* __POSTERIZE_H__ */ #endif /* __POSTERIZE_H__ */

View File

@ -28,6 +28,7 @@
#include "image_map.h" #include "image_map.h"
#include "interface.h" #include "interface.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -94,59 +95,6 @@ static void brightness_contrast_contrast_text_update (GtkWidget *, gpointer
static void *brightness_contrast_options = NULL; static void *brightness_contrast_options = NULL;
static BrightnessContrastDialog *brightness_contrast_dialog = NULL; static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
static Argument * brightness_contrast_invoker (Argument *);
/* brightness contrast machinery */
static float
brightness_contrast_lut_func(BrightnessContrastDialog *bcd,
int nchannels, int channel, float value)
{
float nvalue;
double power;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (bcd->brightness < 0)
value = value * (1.0 + bcd->brightness/255.0);
else
value = value + ((1.0 - value) * bcd->brightness/255.0);
/* apply contrast */
if (bcd->contrast < 0)
{
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
{
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;
}
/* by_color select action functions */ /* by_color select action functions */
@ -467,8 +415,9 @@ brightness_contrast_preview (BrightnessContrastDialog *bcd)
if (!bcd->image_map) if (!bcd->image_map)
g_message (_("brightness_contrast_preview(): No image map")); g_message (_("brightness_contrast_preview(): No image map"));
active_tool->preserve = TRUE; active_tool->preserve = TRUE;
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func, brightness_contrast_lut_setup(bcd->lut, bcd->brightness / 255.0,
(void *) bcd, gimp_drawable_bytes(bcd->drawable)); bcd->contrast / 127.0,
gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut); (void *) bcd->lut);
active_tool->preserve = FALSE; active_tool->preserve = FALSE;
@ -489,8 +438,9 @@ brightness_contrast_ok_callback (GtkWidget *widget,
if (!bcd->preview) if (!bcd->preview)
{ {
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func, brightness_contrast_lut_setup(bcd->lut, bcd->brightness / 255.0,
(void *) bcd, gimp_drawable_bytes(bcd->drawable)); bcd->contrast / 127.0,
gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut); (void *) bcd->lut);
} }
@ -632,119 +582,3 @@ brightness_contrast_contrast_text_update (GtkWidget *w,
} }
/* The brightness_contrast procedure definition */
ProcArg brightness_contrast_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"brightness",
"brightness adjustment: (-127 <= brightness <= 127)"
},
{ PDB_INT32,
"contrast",
"constrast adjustment: (-127 <= contrast <= 127)"
}
};
ProcRecord brightness_contrast_proc =
{
"gimp_brightness_contrast",
"Modify brightness/contrast in the specified drawable",
"This procedures allows the brightness and contrast of the specified drawable to be modified. Both 'brightness' and 'contrast' parameters are defined between -127 and 127.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997",
PDB_INTERNAL,
/* Input arguments */
3,
brightness_contrast_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { brightness_contrast_invoker } },
};
static Argument *
brightness_contrast_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
int int_value;
BrightnessContrastDialog bcd;
GImage *gimage;
int brightness;
int contrast;
int x1, y1, x2, y2;
GimpDrawable *drawable;
drawable = NULL;
brightness = 0;
contrast = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
else
gimage = drawable_gimage (drawable);
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* brightness */
if (success)
{
int_value = args[1].value.pdb_int;
if (int_value < -127 || int_value > 127)
success = FALSE;
else
brightness = int_value;
}
/* contrast */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value < -127 || int_value > 127)
success = FALSE;
else
contrast = int_value;
}
/* arrange to modify the brightness/contrast */
if (success)
{
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);
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);
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));
}
return procedural_db_return_args (&brightness_contrast_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __BRIGHTNESS_CONTRAST_H__ #define __BRIGHTNESS_CONTRAST_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* by_color select functions */ /* by_color select functions */
Tool * tools_new_brightness_contrast (void); Tool * tools_new_brightness_contrast (void);
@ -27,7 +26,4 @@ void tools_free_brightness_contrast (Tool *);
void brightness_contrast_initialize (GDisplay *); void brightness_contrast_initialize (GDisplay *);
/* Procedure definition and marshalling function */
extern ProcRecord brightness_contrast_proc;
#endif /* __BRIGHTNESS_CONTRAST_H__ */ #endif /* __BRIGHTNESS_CONTRAST_H__ */

View File

@ -28,6 +28,7 @@
#include "image_map.h" #include "image_map.h"
#include "interface.h" #include "interface.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -94,59 +95,6 @@ static void brightness_contrast_contrast_text_update (GtkWidget *, gpointer
static void *brightness_contrast_options = NULL; static void *brightness_contrast_options = NULL;
static BrightnessContrastDialog *brightness_contrast_dialog = NULL; static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
static Argument * brightness_contrast_invoker (Argument *);
/* brightness contrast machinery */
static float
brightness_contrast_lut_func(BrightnessContrastDialog *bcd,
int nchannels, int channel, float value)
{
float nvalue;
double power;
/* return the original value for the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
/* apply brightness */
if (bcd->brightness < 0)
value = value * (1.0 + bcd->brightness/255.0);
else
value = value + ((1.0 - value) * bcd->brightness/255.0);
/* apply contrast */
if (bcd->contrast < 0)
{
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
{
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;
}
/* by_color select action functions */ /* by_color select action functions */
@ -467,8 +415,9 @@ brightness_contrast_preview (BrightnessContrastDialog *bcd)
if (!bcd->image_map) if (!bcd->image_map)
g_message (_("brightness_contrast_preview(): No image map")); g_message (_("brightness_contrast_preview(): No image map"));
active_tool->preserve = TRUE; active_tool->preserve = TRUE;
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func, brightness_contrast_lut_setup(bcd->lut, bcd->brightness / 255.0,
(void *) bcd, gimp_drawable_bytes(bcd->drawable)); bcd->contrast / 127.0,
gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut); (void *) bcd->lut);
active_tool->preserve = FALSE; active_tool->preserve = FALSE;
@ -489,8 +438,9 @@ brightness_contrast_ok_callback (GtkWidget *widget,
if (!bcd->preview) if (!bcd->preview)
{ {
gimp_lut_setup(bcd->lut, (GimpLutFunc) brightness_contrast_lut_func, brightness_contrast_lut_setup(bcd->lut, bcd->brightness / 255.0,
(void *) bcd, gimp_drawable_bytes(bcd->drawable)); bcd->contrast / 127.0,
gimp_drawable_bytes(bcd->drawable));
image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (bcd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) bcd->lut); (void *) bcd->lut);
} }
@ -632,119 +582,3 @@ brightness_contrast_contrast_text_update (GtkWidget *w,
} }
/* The brightness_contrast procedure definition */
ProcArg brightness_contrast_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"brightness",
"brightness adjustment: (-127 <= brightness <= 127)"
},
{ PDB_INT32,
"contrast",
"constrast adjustment: (-127 <= contrast <= 127)"
}
};
ProcRecord brightness_contrast_proc =
{
"gimp_brightness_contrast",
"Modify brightness/contrast in the specified drawable",
"This procedures allows the brightness and contrast of the specified drawable to be modified. Both 'brightness' and 'contrast' parameters are defined between -127 and 127.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997",
PDB_INTERNAL,
/* Input arguments */
3,
brightness_contrast_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { brightness_contrast_invoker } },
};
static Argument *
brightness_contrast_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
int int_value;
BrightnessContrastDialog bcd;
GImage *gimage;
int brightness;
int contrast;
int x1, y1, x2, y2;
GimpDrawable *drawable;
drawable = NULL;
brightness = 0;
contrast = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
else
gimage = drawable_gimage (drawable);
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* brightness */
if (success)
{
int_value = args[1].value.pdb_int;
if (int_value < -127 || int_value > 127)
success = FALSE;
else
brightness = int_value;
}
/* contrast */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value < -127 || int_value > 127)
success = FALSE;
else
contrast = int_value;
}
/* arrange to modify the brightness/contrast */
if (success)
{
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);
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);
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));
}
return procedural_db_return_args (&brightness_contrast_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __BRIGHTNESS_CONTRAST_H__ #define __BRIGHTNESS_CONTRAST_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* by_color select functions */ /* by_color select functions */
Tool * tools_new_brightness_contrast (void); Tool * tools_new_brightness_contrast (void);
@ -27,7 +26,4 @@ void tools_free_brightness_contrast (Tool *);
void brightness_contrast_initialize (GDisplay *); void brightness_contrast_initialize (GDisplay *);
/* Procedure definition and marshalling function */
extern ProcRecord brightness_contrast_proc;
#endif /* __BRIGHTNESS_CONTRAST_H__ */ #endif /* __BRIGHTNESS_CONTRAST_H__ */

View File

@ -31,6 +31,7 @@
#include "interface.h" #include "interface.h"
#include "levels.h" #include "levels.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -141,61 +142,6 @@ static gint levels_output_da_events (GtkWidget *, GdkEvent *,
static void levels_histogram_range (HistogramWidget *, int, int, static void levels_histogram_range (HistogramWidget *, int, int,
void *); void *);
static Argument * levels_invoker (Argument *);
/* levels machinery */
static float
levels_lut_func(LevelsDialog *ld,
int nchannels, int channel, float value)
{
double inten;
int j;
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;
/* 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]);
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]));
}
/* 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]));
inten /= 255.0;
}
return inten;
}
static void static void
levels_histogram_range (HistogramWidget *h, levels_histogram_range (HistogramWidget *h,
@ -715,8 +661,9 @@ levels_update (LevelsDialog *ld,
/* Recalculate the transfer arrays */ /* Recalculate the transfer arrays */
levels_calculate_transfers (ld); levels_calculate_transfers (ld);
/* set up the lut */ /* set up the lut */
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func, levels_lut_setup(ld->lut, ld->gamma, ld->low_input, ld->high_input,
(void *) ld, gimp_drawable_bytes(ld->drawable)); ld->low_output, ld->high_output,
gimp_drawable_bytes(ld->drawable));
if (update & LOW_INPUT) if (update & LOW_INPUT)
{ {
@ -1005,8 +952,9 @@ levels_ok_callback (GtkWidget *widget,
if (!ld->preview) if (!ld->preview)
{ {
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func, levels_lut_setup(ld->lut, ld->gamma, ld->low_input, ld->high_input,
(void *) ld, gimp_drawable_bytes(ld->drawable)); ld->low_output, ld->high_output,
gimp_drawable_bytes(ld->drawable));
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut); (void *) ld->lut);
} }
@ -1359,204 +1307,3 @@ levels_output_da_events (GtkWidget *widget,
} }
/* The levels procedure definition */
ProcArg levels_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"channel",
"the channel to modify: { VALUE (0), RED (1), GREEN (2), BLUE (3), GRAY (0) }"
},
{ PDB_INT32,
"low_input",
"intensity of lowest input: (0 <= low_input <= 255)"
},
{ PDB_INT32,
"high_input",
"intensity of highest input: (0 <= high_input <= 255)"
},
{ PDB_FLOAT,
"gamma",
"gamma correction factor: (0.1 <= gamma <= 10)"
},
{ PDB_INT32,
"low_output",
"intensity of lowest output: (0 <= low_input <= 255)"
},
{ PDB_INT32,
"high_output",
"intensity of highest output: (0 <= high_input <= 255)"
}
};
ProcRecord levels_proc =
{
"gimp_levels",
"Modifies intensity levels in the specified drawable",
"This tool allows intensity levels in the specified drawable to be remapped according to a set of parameters. The low/high input levels specify an initial mapping from the source intensities. The gamma value determines how intensities between the low and high input intensities are interpolated. A gamma value of 1.0 results in a linear interpolation. Higher gamma values result in more high-level intensities. Lower gamma values result in more low-level intensities. The low/high output levels constrain the final intensity mapping--that is, no final intensity will be lower than the low output level and no final intensity will be higher than the high output level. This tool is only valid on RGB color and grayscale images. It will not operate on indexed drawables.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1995-1996",
PDB_INTERNAL,
/* Input arguments */
7,
levels_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { levels_invoker } },
};
static Argument *
levels_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
LevelsDialog ld;
GimpDrawable *drawable;
int channel;
int low_input;
int high_input;
double gamma;
int low_output;
int high_output;
int int_value;
double fp_value;
int x1, y1, x2, y2;
int i;
drawable = NULL;
low_input = 0;
high_input = 0;
gamma = 1.0;
low_output = 0;
high_output = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* channel */
if (success)
{
int_value = args[1].value.pdb_int;
if (success)
{
if (drawable_gray (drawable))
{
if (int_value != 0)
success = FALSE;
}
else if (drawable_color (drawable))
{
if (int_value < 0 || int_value > 3)
success = FALSE;
}
else
success = FALSE;
}
channel = int_value;
}
/* low input */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value >= 0 && int_value < 256)
low_input = int_value;
else
success = FALSE;
}
/* high input */
if (success)
{
int_value = args[3].value.pdb_int;
if (int_value >= 0 && int_value < 256)
high_input = int_value;
else
success = FALSE;
}
/* gamma */
if (success)
{
fp_value = args[4].value.pdb_float;
if (fp_value >= 0.1 && fp_value <= 10.0)
gamma = fp_value;
else
success = FALSE;
}
/* low output */
if (success)
{
int_value = args[5].value.pdb_int;
if (int_value >= 0 && int_value < 256)
low_output = int_value;
else
success = FALSE;
}
/* high output */
if (success)
{
int_value = args[6].value.pdb_int;
if (int_value >= 0 && int_value < 256)
high_output = int_value;
else
success = FALSE;
}
/* arrange to modify the levels */
if (success)
{
for (i = 0; i < 5; i++)
{
ld.low_input[i] = 0;
ld.gamma[i] = 1.0;
ld.high_input[i] = 255;
ld.low_output[i] = 0;
ld.high_output[i] = 255;
}
ld.lut = gimp_lut_new();
ld.channel = channel;
ld.color = drawable_color (drawable);
ld.low_input[channel] = low_input;
ld.high_input[channel] = high_input;
ld.gamma[channel] = gamma;
ld.low_output[channel] = low_output;
ld.high_output[channel] = high_output;
/* 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);
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);
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));
}
return procedural_db_return_args (&levels_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __LEVELS_H__ #define __LEVELS_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* hue-saturation functions */ /* hue-saturation functions */
Tool * tools_new_levels (void); Tool * tools_new_levels (void);
@ -28,7 +27,4 @@ void tools_free_levels (Tool *);
void levels_initialize (GDisplay *); void levels_initialize (GDisplay *);
void levels_free (void); void levels_free (void);
/* Procedure definition and marshalling function */
extern ProcRecord levels_proc;
#endif /* __LEVELS_H__ */ #endif /* __LEVELS_H__ */

View File

@ -34,6 +34,7 @@
#include "interface.h" #include "interface.h"
#include "posterize.h" #include "posterize.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -84,29 +85,6 @@ static void posterize_preview_update (GtkWidget *, gpointer);
static void posterize_levels_text_update (GtkWidget *, gpointer); static void posterize_levels_text_update (GtkWidget *, gpointer);
static gint posterize_delete_callback (GtkWidget *, GdkEvent *, gpointer); static gint posterize_delete_callback (GtkWidget *, GdkEvent *, gpointer);
static Argument * posterize_invoker (Argument *);
/* posterize machinery */
static float
posterize_lut_func(PosterizeDialog *pd,
int nchannels, int channel, float value)
{
int levels;
/* don't posterize the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
if (pd->levels < 2)
levels = 2;
else
levels = pd->levels;
value = rint(value * (pd->levels - 1.0)) / (pd->levels - 1.0);
return value;
}
/* by_color select action functions */ /* by_color select action functions */
@ -343,8 +321,7 @@ posterize_preview (PosterizeDialog *pd)
if (!pd->image_map) if (!pd->image_map)
g_message (_("posterize_preview(): No image map")); g_message (_("posterize_preview(): No image map"));
active_tool->preserve = TRUE; active_tool->preserve = TRUE;
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func, posterize_lut_setup(pd->lut, pd->levels, gimp_drawable_bytes(pd->drawable));
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut); (void *) pd->lut);
active_tool->preserve = FALSE; active_tool->preserve = FALSE;
@ -365,8 +342,8 @@ posterize_ok_callback (GtkWidget *widget,
if (!pd->preview) if (!pd->preview)
{ {
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func, posterize_lut_setup(pd->lut, pd->levels,
(void *) pd, gimp_drawable_bytes(pd->drawable)); gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut); (void *) pd->lut);
} }
@ -444,100 +421,3 @@ posterize_levels_text_update (GtkWidget *w,
} }
} }
/* The posterize procedure definition */
ProcArg posterize_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"levels",
"levels of posterization: (2 <= levels <= 255)"
}
};
ProcRecord posterize_proc =
{
"gimp_posterize",
"Posterize the specified drawable",
"This procedures reduces the number of shades allows in each intensity channel to the specified 'levels' parameter.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997",
PDB_INTERNAL,
/* Input arguments */
2,
posterize_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { posterize_invoker } },
};
static Argument *
posterize_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
PosterizeDialog pd;
GImage *gimage;
GimpDrawable *drawable;
int levels;
int int_value;
int x1, y1, x2, y2;
drawable = NULL;
levels = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
else
gimage = drawable_gimage (drawable);
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* levels */
if (success)
{
int_value = args[1].value.pdb_int;
if (int_value >= 2 && int_value < 256)
levels = int_value;
else
success = FALSE;
}
/* arrange to modify the levels */
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);
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));
}
return procedural_db_return_args (&posterize_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __POSTERIZE_H__ #define __POSTERIZE_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* by_color select functions */ /* by_color select functions */
Tool * tools_new_posterize (void); Tool * tools_new_posterize (void);
@ -27,7 +26,4 @@ void tools_free_posterize (Tool *);
void posterize_initialize (GDisplay *); void posterize_initialize (GDisplay *);
/* Procedure definition and marshalling function */
extern ProcRecord posterize_proc;
#endif /* __POSTERIZE_H__ */ #endif /* __POSTERIZE_H__ */

View File

@ -31,6 +31,7 @@
#include "interface.h" #include "interface.h"
#include "levels.h" #include "levels.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -141,61 +142,6 @@ static gint levels_output_da_events (GtkWidget *, GdkEvent *,
static void levels_histogram_range (HistogramWidget *, int, int, static void levels_histogram_range (HistogramWidget *, int, int,
void *); void *);
static Argument * levels_invoker (Argument *);
/* levels machinery */
static float
levels_lut_func(LevelsDialog *ld,
int nchannels, int channel, float value)
{
double inten;
int j;
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;
/* 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]);
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]));
}
/* 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]));
inten /= 255.0;
}
return inten;
}
static void static void
levels_histogram_range (HistogramWidget *h, levels_histogram_range (HistogramWidget *h,
@ -715,8 +661,9 @@ levels_update (LevelsDialog *ld,
/* Recalculate the transfer arrays */ /* Recalculate the transfer arrays */
levels_calculate_transfers (ld); levels_calculate_transfers (ld);
/* set up the lut */ /* set up the lut */
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func, levels_lut_setup(ld->lut, ld->gamma, ld->low_input, ld->high_input,
(void *) ld, gimp_drawable_bytes(ld->drawable)); ld->low_output, ld->high_output,
gimp_drawable_bytes(ld->drawable));
if (update & LOW_INPUT) if (update & LOW_INPUT)
{ {
@ -1005,8 +952,9 @@ levels_ok_callback (GtkWidget *widget,
if (!ld->preview) if (!ld->preview)
{ {
gimp_lut_setup(ld->lut, (GimpLutFunc) levels_lut_func, levels_lut_setup(ld->lut, ld->gamma, ld->low_input, ld->high_input,
(void *) ld, gimp_drawable_bytes(ld->drawable)); ld->low_output, ld->high_output,
gimp_drawable_bytes(ld->drawable));
image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (ld->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) ld->lut); (void *) ld->lut);
} }
@ -1359,204 +1307,3 @@ levels_output_da_events (GtkWidget *widget,
} }
/* The levels procedure definition */
ProcArg levels_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"channel",
"the channel to modify: { VALUE (0), RED (1), GREEN (2), BLUE (3), GRAY (0) }"
},
{ PDB_INT32,
"low_input",
"intensity of lowest input: (0 <= low_input <= 255)"
},
{ PDB_INT32,
"high_input",
"intensity of highest input: (0 <= high_input <= 255)"
},
{ PDB_FLOAT,
"gamma",
"gamma correction factor: (0.1 <= gamma <= 10)"
},
{ PDB_INT32,
"low_output",
"intensity of lowest output: (0 <= low_input <= 255)"
},
{ PDB_INT32,
"high_output",
"intensity of highest output: (0 <= high_input <= 255)"
}
};
ProcRecord levels_proc =
{
"gimp_levels",
"Modifies intensity levels in the specified drawable",
"This tool allows intensity levels in the specified drawable to be remapped according to a set of parameters. The low/high input levels specify an initial mapping from the source intensities. The gamma value determines how intensities between the low and high input intensities are interpolated. A gamma value of 1.0 results in a linear interpolation. Higher gamma values result in more high-level intensities. Lower gamma values result in more low-level intensities. The low/high output levels constrain the final intensity mapping--that is, no final intensity will be lower than the low output level and no final intensity will be higher than the high output level. This tool is only valid on RGB color and grayscale images. It will not operate on indexed drawables.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1995-1996",
PDB_INTERNAL,
/* Input arguments */
7,
levels_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { levels_invoker } },
};
static Argument *
levels_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
LevelsDialog ld;
GimpDrawable *drawable;
int channel;
int low_input;
int high_input;
double gamma;
int low_output;
int high_output;
int int_value;
double fp_value;
int x1, y1, x2, y2;
int i;
drawable = NULL;
low_input = 0;
high_input = 0;
gamma = 1.0;
low_output = 0;
high_output = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* channel */
if (success)
{
int_value = args[1].value.pdb_int;
if (success)
{
if (drawable_gray (drawable))
{
if (int_value != 0)
success = FALSE;
}
else if (drawable_color (drawable))
{
if (int_value < 0 || int_value > 3)
success = FALSE;
}
else
success = FALSE;
}
channel = int_value;
}
/* low input */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value >= 0 && int_value < 256)
low_input = int_value;
else
success = FALSE;
}
/* high input */
if (success)
{
int_value = args[3].value.pdb_int;
if (int_value >= 0 && int_value < 256)
high_input = int_value;
else
success = FALSE;
}
/* gamma */
if (success)
{
fp_value = args[4].value.pdb_float;
if (fp_value >= 0.1 && fp_value <= 10.0)
gamma = fp_value;
else
success = FALSE;
}
/* low output */
if (success)
{
int_value = args[5].value.pdb_int;
if (int_value >= 0 && int_value < 256)
low_output = int_value;
else
success = FALSE;
}
/* high output */
if (success)
{
int_value = args[6].value.pdb_int;
if (int_value >= 0 && int_value < 256)
high_output = int_value;
else
success = FALSE;
}
/* arrange to modify the levels */
if (success)
{
for (i = 0; i < 5; i++)
{
ld.low_input[i] = 0;
ld.gamma[i] = 1.0;
ld.high_input[i] = 255;
ld.low_output[i] = 0;
ld.high_output[i] = 255;
}
ld.lut = gimp_lut_new();
ld.channel = channel;
ld.color = drawable_color (drawable);
ld.low_input[channel] = low_input;
ld.high_input[channel] = high_input;
ld.gamma[channel] = gamma;
ld.low_output[channel] = low_output;
ld.high_output[channel] = high_output;
/* 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);
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);
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));
}
return procedural_db_return_args (&levels_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __LEVELS_H__ #define __LEVELS_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* hue-saturation functions */ /* hue-saturation functions */
Tool * tools_new_levels (void); Tool * tools_new_levels (void);
@ -28,7 +27,4 @@ void tools_free_levels (Tool *);
void levels_initialize (GDisplay *); void levels_initialize (GDisplay *);
void levels_free (void); void levels_free (void);
/* Procedure definition and marshalling function */
extern ProcRecord levels_proc;
#endif /* __LEVELS_H__ */ #endif /* __LEVELS_H__ */

View File

@ -34,6 +34,7 @@
#include "interface.h" #include "interface.h"
#include "posterize.h" #include "posterize.h"
#include "gimplut.h" #include "gimplut.h"
#include "lut_funcs.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -84,29 +85,6 @@ static void posterize_preview_update (GtkWidget *, gpointer);
static void posterize_levels_text_update (GtkWidget *, gpointer); static void posterize_levels_text_update (GtkWidget *, gpointer);
static gint posterize_delete_callback (GtkWidget *, GdkEvent *, gpointer); static gint posterize_delete_callback (GtkWidget *, GdkEvent *, gpointer);
static Argument * posterize_invoker (Argument *);
/* posterize machinery */
static float
posterize_lut_func(PosterizeDialog *pd,
int nchannels, int channel, float value)
{
int levels;
/* don't posterize the alpha channel */
if ((nchannels == 2 || nchannels == 4) && channel == nchannels -1)
return value;
if (pd->levels < 2)
levels = 2;
else
levels = pd->levels;
value = rint(value * (pd->levels - 1.0)) / (pd->levels - 1.0);
return value;
}
/* by_color select action functions */ /* by_color select action functions */
@ -343,8 +321,7 @@ posterize_preview (PosterizeDialog *pd)
if (!pd->image_map) if (!pd->image_map)
g_message (_("posterize_preview(): No image map")); g_message (_("posterize_preview(): No image map"));
active_tool->preserve = TRUE; active_tool->preserve = TRUE;
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func, posterize_lut_setup(pd->lut, pd->levels, gimp_drawable_bytes(pd->drawable));
(void *) pd, gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut); (void *) pd->lut);
active_tool->preserve = FALSE; active_tool->preserve = FALSE;
@ -365,8 +342,8 @@ posterize_ok_callback (GtkWidget *widget,
if (!pd->preview) if (!pd->preview)
{ {
gimp_lut_setup_exact(pd->lut, (GimpLutFunc) posterize_lut_func, posterize_lut_setup(pd->lut, pd->levels,
(void *) pd, gimp_drawable_bytes(pd->drawable)); gimp_drawable_bytes(pd->drawable));
image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2, image_map_apply (pd->image_map, (ImageMapApplyFunc)gimp_lut_process_2,
(void *) pd->lut); (void *) pd->lut);
} }
@ -444,100 +421,3 @@ posterize_levels_text_update (GtkWidget *w,
} }
} }
/* The posterize procedure definition */
ProcArg posterize_args[] =
{
{ PDB_DRAWABLE,
"drawable",
"the drawable"
},
{ PDB_INT32,
"levels",
"levels of posterization: (2 <= levels <= 255)"
}
};
ProcRecord posterize_proc =
{
"gimp_posterize",
"Posterize the specified drawable",
"This procedures reduces the number of shades allows in each intensity channel to the specified 'levels' parameter.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997",
PDB_INTERNAL,
/* Input arguments */
2,
posterize_args,
/* Output arguments */
0,
NULL,
/* Exec method */
{ { posterize_invoker } },
};
static Argument *
posterize_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
int success = TRUE;
PosterizeDialog pd;
GImage *gimage;
GimpDrawable *drawable;
int levels;
int int_value;
int x1, y1, x2, y2;
drawable = NULL;
levels = 0;
/* the drawable */
if (success)
{
int_value = args[0].value.pdb_int;
drawable = drawable_get_ID (int_value);
if (drawable == NULL)
success = FALSE;
else
gimage = drawable_gimage (drawable);
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* levels */
if (success)
{
int_value = args[1].value.pdb_int;
if (int_value >= 2 && int_value < 256)
levels = int_value;
else
success = FALSE;
}
/* arrange to modify the levels */
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);
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));
}
return procedural_db_return_args (&posterize_proc, success);
}

View File

@ -19,7 +19,6 @@
#define __POSTERIZE_H__ #define __POSTERIZE_H__
#include "tools.h" #include "tools.h"
#include "procedural_db.h"
/* by_color select functions */ /* by_color select functions */
Tool * tools_new_posterize (void); Tool * tools_new_posterize (void);
@ -27,7 +26,4 @@ void tools_free_posterize (Tool *);
void posterize_initialize (GDisplay *); void posterize_initialize (GDisplay *);
/* Procedure definition and marshalling function */
extern ProcRecord posterize_proc;
#endif /* __POSTERIZE_H__ */ #endif /* __POSTERIZE_H__ */

View File

@ -75,6 +75,65 @@ parasite_new (const char *name, guint32 flags,
return p; return p;
} }
Parasite *
parasite_load(FILE *fp)
{
guint32 tmp;
Parasite *p;
p = g_new(Parasite, 1);
tmp = 0;
fread(&tmp, 4, 1, fp);
tmp = GUINT32_FROM_BE(tmp);
if (tmp > 0)
{
p->name = g_malloc(tmp);
fread(p->name, tmp, 1, fp);
}
else
{
g_free (p);
return NULL;
}
fread(&tmp, 4, 1, fp);
p->flags = GUINT32_FROM_BE(tmp);
tmp = 0;
fread(&tmp, 4, 1, fp);
p->size = GUINT32_FROM_BE(tmp);
if (p->size > 0)
{
p->data = g_malloc(p->size);
fread(p->data, p->size, 1, fp);
}
else
p->data = NULL;
return p;
}
int
parasite_save(const Parasite *p, FILE *fp)
{
gint32 len, bytes = 0;
guint32 tmp;
len = strlen(p->name) + 1;
tmp = GUINT32_TO_BE(len);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
if (len > 0)
fwrite(p->name, len, 1, fp);
bytes += len;
tmp = GUINT32_TO_BE(p->flags);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
tmp = GUINT32_TO_BE(p->size);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
if (p->size > 0)
fwrite(p->data, 1, p->size, fp);
bytes += p->size;
return bytes;
}
void void
parasite_free (Parasite *parasite) parasite_free (Parasite *parasite)
{ {

View File

@ -21,6 +21,7 @@
#define _PARASITE_H_ #define _PARASITE_H_
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include <libgimp/parasiteF.h> #include <libgimp/parasiteF.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -36,7 +37,9 @@ extern "C" {
#define PARASITE_GRANDPARENT_PERSISTENT (PARASITE_PERSISTENT << 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); guint32 size, const void *data);
Parasite *parasite_load (FILE *fp);
int parasite_save (const Parasite *p, FILE *fp);
void parasite_free (Parasite *parasite); void parasite_free (Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite); Parasite *parasite_copy (const Parasite *parasite);

View File

@ -75,6 +75,65 @@ parasite_new (const char *name, guint32 flags,
return p; return p;
} }
Parasite *
parasite_load(FILE *fp)
{
guint32 tmp;
Parasite *p;
p = g_new(Parasite, 1);
tmp = 0;
fread(&tmp, 4, 1, fp);
tmp = GUINT32_FROM_BE(tmp);
if (tmp > 0)
{
p->name = g_malloc(tmp);
fread(p->name, tmp, 1, fp);
}
else
{
g_free (p);
return NULL;
}
fread(&tmp, 4, 1, fp);
p->flags = GUINT32_FROM_BE(tmp);
tmp = 0;
fread(&tmp, 4, 1, fp);
p->size = GUINT32_FROM_BE(tmp);
if (p->size > 0)
{
p->data = g_malloc(p->size);
fread(p->data, p->size, 1, fp);
}
else
p->data = NULL;
return p;
}
int
parasite_save(const Parasite *p, FILE *fp)
{
gint32 len, bytes = 0;
guint32 tmp;
len = strlen(p->name) + 1;
tmp = GUINT32_TO_BE(len);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
if (len > 0)
fwrite(p->name, len, 1, fp);
bytes += len;
tmp = GUINT32_TO_BE(p->flags);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
tmp = GUINT32_TO_BE(p->size);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
if (p->size > 0)
fwrite(p->data, 1, p->size, fp);
bytes += p->size;
return bytes;
}
void void
parasite_free (Parasite *parasite) parasite_free (Parasite *parasite)
{ {

View File

@ -21,6 +21,7 @@
#define _PARASITE_H_ #define _PARASITE_H_
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include <libgimp/parasiteF.h> #include <libgimp/parasiteF.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -36,7 +37,9 @@ extern "C" {
#define PARASITE_GRANDPARENT_PERSISTENT (PARASITE_PERSISTENT << 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); guint32 size, const void *data);
Parasite *parasite_load (FILE *fp);
int parasite_save (const Parasite *p, FILE *fp);
void parasite_free (Parasite *parasite); void parasite_free (Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite); Parasite *parasite_copy (const Parasite *parasite);

View File

@ -75,6 +75,65 @@ parasite_new (const char *name, guint32 flags,
return p; return p;
} }
Parasite *
parasite_load(FILE *fp)
{
guint32 tmp;
Parasite *p;
p = g_new(Parasite, 1);
tmp = 0;
fread(&tmp, 4, 1, fp);
tmp = GUINT32_FROM_BE(tmp);
if (tmp > 0)
{
p->name = g_malloc(tmp);
fread(p->name, tmp, 1, fp);
}
else
{
g_free (p);
return NULL;
}
fread(&tmp, 4, 1, fp);
p->flags = GUINT32_FROM_BE(tmp);
tmp = 0;
fread(&tmp, 4, 1, fp);
p->size = GUINT32_FROM_BE(tmp);
if (p->size > 0)
{
p->data = g_malloc(p->size);
fread(p->data, p->size, 1, fp);
}
else
p->data = NULL;
return p;
}
int
parasite_save(const Parasite *p, FILE *fp)
{
gint32 len, bytes = 0;
guint32 tmp;
len = strlen(p->name) + 1;
tmp = GUINT32_TO_BE(len);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
if (len > 0)
fwrite(p->name, len, 1, fp);
bytes += len;
tmp = GUINT32_TO_BE(p->flags);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
tmp = GUINT32_TO_BE(p->size);
fwrite(&tmp, 4, 1, fp);
bytes += 4;
if (p->size > 0)
fwrite(p->data, 1, p->size, fp);
bytes += p->size;
return bytes;
}
void void
parasite_free (Parasite *parasite) parasite_free (Parasite *parasite)
{ {

View File

@ -21,6 +21,7 @@
#define _PARASITE_H_ #define _PARASITE_H_
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include <libgimp/parasiteF.h> #include <libgimp/parasiteF.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -36,7 +37,9 @@ extern "C" {
#define PARASITE_GRANDPARENT_PERSISTENT (PARASITE_PERSISTENT << 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); guint32 size, const void *data);
Parasite *parasite_load (FILE *fp);
int parasite_save (const Parasite *p, FILE *fp);
void parasite_free (Parasite *parasite); void parasite_free (Parasite *parasite);
Parasite *parasite_copy (const Parasite *parasite); Parasite *parasite_copy (const Parasite *parasite);