Commit fe34aed3 authored by jaycox's avatar jaycox
Browse files

optimized by using a lookup table



	* app/color_balance.c: optimized by using a lookup table

	* app/paint_funcs.c: parallelized apply_mask_to_region,
	combine_mask_and_region, and initial_region.  Use rand_r
	if we are multithreaded.
parent 27f68dfe
1999-01-31 Jay Cox <jaycox@earthlink.net>
* app/color_balance.c: optimized by using a lookup table
* app/paint_funcs.c: parallelized apply_mask_to_region,
combine_mask_and_region, and initial_region. Use rand_r
if we are multithreaded.
Sun Jan 31 18:02:46 1999 Owen Taylor <otaylor@gtk.org>
* app/blob.c: Merged in changes from gsumi. This
......@@ -7,7 +15,7 @@ Sun Jan 31 18:02:46 1999 Owen Taylor <otaylor@gtk.org>
Sun Jan 31 19:42:26 GMT 1999 Adam D. Moss <adam@gimp.org>
* app/tile.c app/tile_manager.c:
* app/tile.c, app/tile_manager.c:
Fixed the tile-corruption bug which has been around
since early GIMP-1.1. When dirtying a copy-on-write
......
......@@ -71,6 +71,10 @@ struct _ColorBalanceDialog
double magenta_green[3];
double yellow_blue[3];
char r_lookup[255];
char g_lookup[255];
char b_lookup[255];
gint preserve_luminosity;
gint preview;
gint application_mode;
......@@ -122,23 +126,9 @@ color_balance (PixelRegion *srcPR,
int r, g, b;
int r_n, g_n, b_n;
int w, h;
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
cbd = (ColorBalanceDialog *) user_data;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub;
cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub;
cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub;
magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub;
magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub;
yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub;
yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
......@@ -151,30 +141,14 @@ color_balance (PixelRegion *srcPR,
d = dest;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = CLAMP0255 (r_n);
g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = CLAMP0255 (g_n);
b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = CLAMP0255 (b_n);
r = s[RED_PIX];
g = s[GREEN_PIX];
b = s[BLUE_PIX];
r_n = cbd->r_lookup[r];
g_n = cbd->g_lookup[g];
b_n = cbd->b_lookup[b];
if (cbd->preserve_luminosity)
{
......@@ -616,12 +590,65 @@ color_balance_update (ColorBalanceDialog *cbd,
}
}
static void
color_balance_create_lookup_tables (ColorBalanceDialog *cbd)
{
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
int i, r_n, g_n, b_n;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub;
cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub;
cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub;
magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub;
magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub;
yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub;
yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
for (i = 0; i < 256; i++)
{
r_n = i;
g_n = i;
b_n = i;
r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = CLAMP0255 (r_n);
g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = CLAMP0255 (g_n);
b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = CLAMP0255 (b_n);
cbd->r_lookup[i] = r_n;
cbd->g_lookup[i] = g_n;
cbd->b_lookup[i] = b_n;
}
}
static void
color_balance_preview (ColorBalanceDialog *cbd)
{
if (!cbd->image_map)
g_message (_("color_balance_preview(): No image map"));
active_tool->preserve = TRUE;
color_balance_create_lookup_tables(cbd);
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
active_tool->preserve = FALSE;
}
......
......@@ -71,6 +71,10 @@ struct _ColorBalanceDialog
double magenta_green[3];
double yellow_blue[3];
char r_lookup[255];
char g_lookup[255];
char b_lookup[255];
gint preserve_luminosity;
gint preview;
gint application_mode;
......@@ -122,23 +126,9 @@ color_balance (PixelRegion *srcPR,
int r, g, b;
int r_n, g_n, b_n;
int w, h;
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
cbd = (ColorBalanceDialog *) user_data;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub;
cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub;
cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub;
magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub;
magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub;
yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub;
yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
......@@ -151,30 +141,14 @@ color_balance (PixelRegion *srcPR,
d = dest;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = CLAMP0255 (r_n);
g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = CLAMP0255 (g_n);
b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = CLAMP0255 (b_n);
r = s[RED_PIX];
g = s[GREEN_PIX];
b = s[BLUE_PIX];
r_n = cbd->r_lookup[r];
g_n = cbd->g_lookup[g];
b_n = cbd->b_lookup[b];
if (cbd->preserve_luminosity)
{
......@@ -616,12 +590,65 @@ color_balance_update (ColorBalanceDialog *cbd,
}
}
static void
color_balance_create_lookup_tables (ColorBalanceDialog *cbd)
{
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
int i, r_n, g_n, b_n;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub;
cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub;
cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub;
magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub;
magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub;
yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub;
yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
for (i = 0; i < 256; i++)
{
r_n = i;
g_n = i;
b_n = i;
r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = CLAMP0255 (r_n);
r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = CLAMP0255 (r_n);
g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = CLAMP0255 (g_n);
g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = CLAMP0255 (g_n);
b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = CLAMP0255 (b_n);
b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = CLAMP0255 (b_n);
cbd->r_lookup[i] = r_n;
cbd->g_lookup[i] = g_n;
cbd->b_lookup[i] = b_n;
}
}
static void
color_balance_preview (ColorBalanceDialog *cbd)
{
if (!cbd->image_map)
g_message (_("color_balance_preview(): No image map"));
active_tool->preserve = TRUE;
color_balance_create_lookup_tables(cbd);
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
active_tool->preserve = FALSE;
}
......
......@@ -983,12 +983,19 @@ dissolve_pixels (const unsigned char *src,
{
int alpha, b;
int rand_val;
#ifdef ENABLE_MP
/* if we are running with multiple threads rand_r give _much_
better performance than rand */
unsigned int seed;
seed = random_table [y % RANDOM_TABLE_SIZE];
for (b = 0; b < x; b++)
rand_r(&seed);
#else
/* Set up the random number generator */
srand (random_table [y % RANDOM_TABLE_SIZE]);
for (b = 0; b < x; b++)
rand ();
#endif
alpha = db - 1;
while (length --)
......@@ -998,8 +1005,11 @@ dissolve_pixels (const unsigned char *src,
dest[b] = src[b];
/* dissolve if random value is > opacity */
#ifdef ENABLE_MP
rand_val = (rand_r(&seed) & 0xFF);
#else
rand_val = (rand() & 0xFF);
#endif
if (has_alpha)
dest[alpha] = (rand_val > src[alpha]) ? 0 : src[alpha];
else
......@@ -4636,54 +4646,66 @@ swap_region (PixelRegion *src,
}
void
apply_mask_to_sub_region (int *opacityp,
PixelRegion *src,
PixelRegion *mask)
{
int h;
unsigned char * s, * m;
int opacity = *opacityp;
s = src->data;
m = mask->data;
h = src->h;
while (h --)
{
apply_mask_to_alpha_channel (s, m, opacity, src->w, src->bytes);
s += src->rowstride;
m += mask->rowstride;
}
}
void
apply_mask_to_region (PixelRegion *src,
PixelRegion *mask,
int opacity)
{
pixel_regions_process_parallel ((p_func)apply_mask_to_sub_region,
&opacity, 2, src, mask);
}
void
combine_mask_and_sub_region (int *opacityp,
PixelRegion *src,
PixelRegion *mask)
{
int h;
unsigned char * s, * m;
void * pr;
for (pr = pixel_regions_register (2, src, mask); pr != NULL; pr = pixel_regions_process (pr))
{
s = src->data;
m = mask->data;
h = src->h;
int opacity = *opacityp;
s = src->data;
m = mask->data;
h = src->h;
while (h --)
{
apply_mask_to_alpha_channel (s, m, opacity, src->w, src->bytes);
s += src->rowstride;
m += mask->rowstride;
}
}
while (h --)
{
combine_mask_and_alpha_channel (s, m, opacity, src->w, src->bytes);
s += src->rowstride;
m += mask->rowstride;
}
}
void
combine_mask_and_region (PixelRegion *src,
PixelRegion *mask,
int opacity)
{
int h;
unsigned char * s, * m;
void * pr;
for (pr = pixel_regions_register (2, src, mask); pr != NULL; pr = pixel_regions_process (pr))
{
s = src->data;
s = src->data;
m = mask->data;
h = src->h;
while (h --)
{
combine_mask_and_alpha_channel (s, m, opacity, src->w, src->bytes);
s += src->rowstride;
m += mask->rowstride;
}
}
pixel_regions_process_parallel ((p_func)combine_mask_and_sub_region,
&opacity, 2, src, mask);
}
......@@ -4711,78 +4733,113 @@ copy_gray_to_region (PixelRegion *src,
}
struct initial_regions_struct
{
int opacity;
int mode;
int *affect;
int type;
unsigned char *data;
};
void
initial_region (PixelRegion *src,
PixelRegion *dest,
PixelRegion *mask,
unsigned char *data,
int opacity,
int mode,
int *affect,
int type)
initial_sub_region(struct initial_regions_struct *st,
PixelRegion *src,
PixelRegion *dest,
PixelRegion *mask)
{
int h;
unsigned char * s, * d, * m;
unsigned char * buf;
void * pr;
unsigned char buf[512];
unsigned char *data;
int opacity;
int mode;
int *affect;
int type;
buf = paint_funcs_get_buffer (src->w * (src->bytes + 1));
data = st->data;
opacity = st->opacity;
mode = st->mode;
affect = st->affect;
type = st->type;
for (pr = pixel_regions_register (3, src, dest, mask); pr != NULL; pr = pixel_regions_process (pr))
{
s = src->data;
d = dest->data;
m = (mask) ? mask->data : NULL;
if (src->w * (src->bytes + 1) > 512)
fprintf(stderr, "initial_sub_region:: error :: src->w * (src->bytes + 1) > 512");
for (h = 0; h < src->h; h++)
{
/* based on the type of the initial image... */
switch (type)
{
case INITIAL_CHANNEL_MASK:
case INITIAL_CHANNEL_SELECTION:
initial_channel_pixels (s, d, src->w, dest->bytes);
break;
s = src->data;
d = dest->data;
m = (mask) ? mask->data : NULL;
case INITIAL_INDEXED:
initial_indexed_pixels (s, d, data, src->w);
break;
for (h = 0; h < src->h; h++)
{
/* based on the type of the initial image... */
switch (type)
{
case INITIAL_CHANNEL_MASK:
case INITIAL_CHANNEL_SELECTION:
initial_channel_pixels (s, d, src->w, dest->bytes);
break;
case INITIAL_INDEXED_ALPHA:
initial_indexed_a_pixels (s, d, m, data, opacity, src->w);
break;
case INITIAL_INDEXED:
initial_indexed_pixels (s, d, data, src->w);
break;
case INITIAL_INTENSITY:
if (mode == DISSOLVE_MODE)
{
dissolve_pixels (s, buf, src->x, src->y + h, opacity, src->w, src->bytes,
src->bytes + 1, 0);
initial_inten_pixels (buf, d, m, opacity, affect,
src->w, src->bytes);
}
else
initial_inten_pixels (s, d, m, opacity, affect, src->w, src->bytes);
break;
case INITIAL_INDEXED_ALPHA:
initial_indexed_a_pixels (s, d, m, data, opacity, src->w);
break;
case INITIAL_INTENSITY_ALPHA:
if (mode == DISSOLVE_MODE)
{
dissolve_pixels (s, buf, src->x, src->y + h, opacity, src->w, src->bytes,
src->bytes, 1);
initial_inten_a_pixels (buf, d, m, opacity, affect,
src->w, src->bytes);
}
else
initial_inten_a_pixels (s, d, m, opacity, affect, src->w, src->bytes);
break;
}
case INITIAL_INTENSITY:
if (mode == DISSOLVE_MODE)
{
dissolve_pixels (s, buf, src->x, src->y + h, opacity, src->w, src->bytes,
src->bytes + 1, 0);
initial_inten_pixels (buf, d, m, opacity, affect,
src->w, src->bytes);
}
else
initial_inten_pixels (s, d, m, opacity, affect, src->w, src->bytes);
break;
s += src->rowstride;
d += dest->rowstride;
if (mask)
m += mask->rowstride;
}
case INITIAL_INTENSITY_ALPHA:
if (mode == DISSOLVE_MODE)
{
dissolve_pixels (s, buf, src->x, src->y + h, opacity, src->w, src->bytes,
src->bytes, 1);
initial_inten_a_pixels (buf, d, m, opacity, affect,
src->w, src->bytes);
}
else
initial_inten_a_pixels (s, d, m, opacity, affect, src->w, src->bytes);
break;
}
s += src->rowstride;
d += dest->rowstride;
if (mask)
m += mask->rowstride;
}
}
void
initial_region (PixelRegion *src,
PixelRegion *dest,
PixelRegion *mask,
unsigned char *data,
int opacity,
int mode,
int *affect,
int type)
{
struct initial_regions_struct st;
st.opacity = opacity;
st.mode = mode;
st.affect = affect;
st.type = type;
st.data = data;
pixel_regions_process_parallel ((p_func)initial_sub_region, &st, 3,