Applied patches from David Necas <yeti@physics.muni.cz> that fix incorrect

2003-03-17  Sven Neumann  <sven@gimp.org>

	Applied patches from David Necas <yeti@physics.muni.cz> that fix
	incorrect RGBA resampling in a number of plug-ins:

	* plug-ins/common/fractaltrace.c: fixes bug #72873.
	* plug-ins/common/tiler.c: fixes bug #72875.
	* plug-ins/common/waves.c: fixes bug #72870.
	* plug-ins/common/whirlpinch.c: fixes bug #72871.
This commit is contained in:
Sven Neumann 2003-03-17 11:19:41 +00:00 committed by Sven Neumann
parent b417203a62
commit 21113a2fc7
5 changed files with 177 additions and 116 deletions

View File

@ -1,3 +1,13 @@
2003-03-17 Sven Neumann <sven@gimp.org>
Applied patches from David Necas <yeti@physics.muni.cz> that fix
incorrect RGBA resampling in a number of plug-ins:
* plug-ins/common/fractaltrace.c: fixes bug #72873.
* plug-ins/common/tiler.c: fixes bug #72875.
* plug-ins/common/waves.c: fixes bug #72870.
* plug-ins/common/whirlpinch.c: fixes bug #72871.
2003-03-17 Michael Natterer <mitch@gimp.org>
* app/core/core-enums.[ch]: added GIMP_UNDO_CHANNEL_COLOR.

View File

@ -337,6 +337,7 @@ pixels_get (gint x,
}
}
#include <stdio.h>
static void
pixels_get_biliner (gdouble x,
gdouble y,
@ -346,6 +347,7 @@ pixels_get_biliner (gdouble x,
gdouble a, b, c, d;
gint x1, y1, x2, y2;
gdouble dx, dy;
gdouble alpha;
x1 = (gint) floor (x);
x2 = x1 + 1;
@ -364,14 +366,25 @@ pixels_get_biliner (gdouble x,
pixels_get (x1, y2, &C);
pixels_get (x2, y2, &D);
pixel->r = (guchar) (a * (gdouble) A.r + b * (gdouble) B.r +
c * (gdouble) C.r + d * (gdouble) D.r);
pixel->g = (guchar) (a * (gdouble) A.g + b * (gdouble) B.g +
c * (gdouble) C.g + d * (gdouble) D.g);
pixel->b = (guchar) (a * (gdouble) A.b + b * (gdouble) B.b +
c * (gdouble) C.b + d * (gdouble) D.b);
pixel->a = (guchar) (a * (gdouble) A.a + b * (gdouble) B.a +
c * (gdouble) C.a + d * (gdouble) D.a);
alpha = 1.0001*(a * (gdouble) A.a + b * (gdouble) B.a
+ c * (gdouble) C.a + d * (gdouble) D.a);
pixel->a = (guchar) alpha;
if (pixel->a)
{
pixel->r = (guchar) ((a * (gdouble) A.r * A.a
+ b * (gdouble) B.r * B.a
+ c * (gdouble) C.r * C.a
+ d * (gdouble) D.r * D.a) / alpha);
pixel->g = (guchar) ((a * (gdouble) A.g * A.a
+ b * (gdouble) B.g * B.a
+ c * (gdouble) C.g * C.a
+ d * (gdouble) D.g * D.a) / alpha);
pixel->b = (guchar) ((a * (gdouble) A.b * A.a
+ b * (gdouble) B.b * B.a
+ c * (gdouble) C.b * C.a
+ d * (gdouble) D.b * D.a) / alpha);
}
}
static void
@ -531,15 +544,26 @@ dialog_preview_setpixel (gint x,
gint y,
pixel_t *pixel)
{
guchar grayshade;
if (pixel->a)
grayshade = pixel->r;
else
grayshade =
(((x % (GIMP_CHECK_SIZE * 2) < GIMP_CHECK_SIZE) ?
(y % (GIMP_CHECK_SIZE * 2) < GIMP_CHECK_SIZE) :
(y % (GIMP_CHECK_SIZE * 2) > GIMP_CHECK_SIZE)) ?
GIMP_CHECK_LIGHT : GIMP_CHECK_DARK) * 255;
switch (preview.bpp)
{
case 1:
preview.pixels[y][x*preview.bpp] = pixel->r;
preview.pixels[y][x * preview.bpp] = grayshade;
break;
case 3:
preview.pixels[y][x*preview.bpp] = pixel->r;
preview.pixels[y][x*preview.bpp+1] = pixel->g;
preview.pixels[y][x*preview.bpp+2] = pixel->b;
preview.pixels[y][x * preview.bpp] = grayshade;
preview.pixels[y][x * preview.bpp + 1] = pixel->a ? pixel->g : grayshade;
preview.pixels[y][x * preview.bpp + 2] = pixel->a ? pixel->b : grayshade;
break;
}
}
@ -651,9 +675,11 @@ dialog_preview_draw (void)
break;
case OUTSIDE_TYPE_BLACK:
pixel.r = pixel.g = pixel.b = 0;
pixel.a = 255;
break;
case OUTSIDE_TYPE_WHITE:
pixel.r = pixel.g = pixel.b = 255;
pixel.a = 255;
break;
}
}

View File

@ -35,12 +35,6 @@ static void run (gchar *name,
GimpParam **return_vals);
static void tile (GimpDrawable *drawable);
static gint scale (gint width,
gint height,
gint x,
gint y,
gint data);
GimpPlugInInfo PLUG_IN_INFO =
{
@ -119,43 +113,70 @@ run (gchar *name,
gimp_drawable_detach (drawable);
}
static gint
scale (gint width,
gint height,
gint x,
gint y,
gint data)
static void
weld_pixels (guchar *dest1,
guchar *dest2,
gint width,
gint height,
gint x,
gint y,
guint bpp,
guchar *src1,
guchar *src2)
{
gint A = width/2-1;
gint B = height/2-1;
gint a, b;
gdouble a = (ABS(x - width) - 1)/ (gdouble) (width - 1);
gdouble b = (ABS(y - height) - 1) / (gdouble) (height - 1);
gdouble w;
guint i;
if (x < width/2)
a = width/2 - x - 1;
/* mimic ambiguous point handling in original algorithm */
if (a < 1e-8 && b > 0.99999999)
w = 1.0;
else if (a > 0.99999999 && b < 1e-8)
w = 0.0;
else
a = x - width/2 - (width & 1);
w = 1.0 - a*b/(a*b + (1.0 - a)*(1.0 - b));
if (y < height/2)
b = height/2 - y -1;
for (i = 0; i < bpp; i++)
dest1[i] = dest2[i] = (guchar) (w * src1[i] + (1.0 - w) * src2[i]);
}
static void
weld_pixels_alpha (guchar *dest1,
guchar *dest2,
gint width,
gint height,
gint x,
gint y,
guint bpp,
guchar *src1,
guchar *src2)
{
gdouble a = (ABS(x - width) - 1)/ (gdouble) (width - 1);
gdouble b = (ABS(y - height) - 1) / (gdouble) (height - 1);
gdouble w;
gdouble alpha;
guint ai = bpp-1;
guint i;
/* mimic ambiguous point handling in original algorithm */
if (a < 1e-8 && b > 0.99999999)
w = 1.0;
else if (a > 0.99999999 && b < 1e-8)
w = 0.0;
else
b = y - height/2 - (height & 1);
if ((B*a<A*b) || ((B*a==A*b) && (a&1)))
w = 1.0 - a*b/(a*b + (1.0 - a)*(1.0 - b));
alpha = w * src1[ai] + (1.0 - w) * src2[ai];
dest1[ai] = dest2[ai] = (guchar) alpha;
if (dest1[ai])
{
a = A-a;
b = B-b;
if (a==A)
return data;
else
return data - data * (A*B-a*B) /(A * b + A * B - a * B);
for (i = 0; i < ai; i++)
dest1[i] = dest2[i] = (guchar) ((w * src1[i] * src1[ai]
+ (1.0 - w) * src2[i] * src2[ai])
/ alpha);
}
else
{
if (a==A)
return 0;
else
return data * (A * B - a * B) / (A * b + A * B - a * B);
}
}
static void
@ -171,8 +192,11 @@ tile_region (GimpDrawable *drawable, gboolean left,
gint max_progress;
GimpPixelRgn src1_rgn, src2_rgn, dest1_rgn, dest2_rgn;
gpointer pr;
gboolean has_alpha;
guint asymmetry_correction;
bpp = gimp_drawable_bpp (drawable->drawable_id);
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
height = y2 - y1;
width = x2 - x1;
@ -196,6 +220,8 @@ tile_region (GimpDrawable *drawable, gboolean left,
off_x = -w - wodd;
}
asymmetry_correction = !wodd && !left;
gimp_pixel_rgn_init (&src1_rgn, drawable, rgn1_x, y1, w, h, FALSE, FALSE);
gimp_pixel_rgn_init (&dest1_rgn, drawable, rgn1_x, y1, w, h, TRUE, TRUE);
gimp_pixel_rgn_init (&src2_rgn, drawable, rgn2_x, y1 + h + hodd,
@ -224,22 +250,30 @@ tile_region (GimpDrawable *drawable, gboolean left,
guchar *d2 = dest2;
gint col = src1_rgn.x - x1;
for (x = 0; x < src1_rgn.w; x++, col++)
{
gint c;
for (c = 0; c < bpp; c++)
{
gint val = scale (width, height, col, row, s1[c]) +
scale (width, height, col + off_x, row + h + hodd, s2[c]);
d1[c] = d2[c] = (val > 255) ? 255 : val;
}
s1 += bpp;
s2 += bpp;
d1 += bpp;
d2 += bpp;
}
if (has_alpha)
{
for (x = 0; x < src1_rgn.w; x++, col++)
{
weld_pixels_alpha (d1, d2, w, h, col + asymmetry_correction,
row, bpp, s1, s2);
s1 += bpp;
s2 += bpp;
d1 += bpp;
d2 += bpp;
}
}
else
{
for (x = 0; x < src1_rgn.w; x++, col++)
{
weld_pixels (d1, d2, w, h, col + asymmetry_correction,
row, bpp, s1, s2);
s1 += bpp;
s2 += bpp;
d1 += bpp;
d2 += bpp;
}
}
src1 += src1_rgn.rowstride;
src2 += src2_rgn.rowstride;

View File

@ -80,6 +80,7 @@ static void wave (guchar *src,
gint width,
gint height,
gint bypp,
gboolean has_alpha,
gdouble amplitude,
gdouble wavelength,
gdouble phase,
@ -216,11 +217,12 @@ pluginCore (piArgs *argp,
gint retval=0;
GimpPixelRgn srcPr, dstPr;
guchar *src, *dst;
guint width, height, bpp;
guint width, height, bpp, has_alpha;
width = drawable->width;
height = drawable->height;
bpp = drawable->bpp;
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
src = g_new (guchar, width * height * bpp);
dst = g_new (guchar, width * height * bpp);
@ -228,8 +230,9 @@ pluginCore (piArgs *argp,
gimp_pixel_rgn_init (&dstPr, drawable, 0, 0, width, height, TRUE, TRUE);
gimp_pixel_rgn_get_rect (&srcPr, src, 0, 0, width, height);
wave (src, dst, width, height, bpp, argp->amplitude, argp->wavelength,
argp->phase, argp->type==0, argp->reflective, 1);
wave (src, dst, width, height, bpp, has_alpha,
argp->amplitude, argp->wavelength, argp->phase,
argp->type==0, argp->reflective, 1);
gimp_pixel_rgn_set_rect (&dstPr, dst, 0, 0, width, height);
g_free (src);
@ -416,6 +419,7 @@ waves_do_preview (void)
dst = g_new (guchar, preview->width * preview->height * preview->bpp);
wave (preview->cache, dst, preview->width, preview->height, preview->bpp,
preview->bpp == 2 || preview->bpp == 4,
argp->amplitude * preview->scale_x,
argp->wavelength * preview->scale_x,
argp->phase, argp->type == 0, argp->reflective, 0);
@ -464,6 +468,8 @@ mw_preview_new (GtkWidget *parent, GimpDrawable *drawable)
gtk_widget_show (pframe);
preview = gimp_fixme_preview_new (drawable, FALSE);
/* FIXME: this forces gimp_fixme_preview to set its alpha correctly */
gimp_fixme_preview_fill_scaled (preview, drawable);
gtk_container_add (GTK_CONTAINER (pframe), preview->widget);
gtk_widget_show (preview->widget);
@ -501,6 +507,7 @@ wave (guchar *src,
gint width,
gint height,
gint bypp,
gboolean has_alpha,
gdouble amplitude,
gdouble wavelength,
gdouble phase,
@ -526,10 +533,8 @@ wave (guchar *src,
gint xi, yi;
guchar values[4];
guchar val;
gint k;
guchar *values[4];
guchar zeroes[4] = { 0, 0, 0, 0 };
phase = phase * G_PI / 180;
rowsiz = width * bypp;
@ -643,32 +648,28 @@ wave (guchar *src,
x2_in = WITHIN (0, xi + 1, width - 1);
y2_in = WITHIN (0, yi + 1, height - 1);
for (k = 0; k < bypp; k++)
{
if (x1_in && y1_in)
values[0] = *(p + k);
else
values[0] = 0;
if (x1_in && y1_in)
values[0] = p;
else
values[0] = zeroes;
if (x2_in && y1_in)
values[1] = *(p + bypp + k);
else
values[1] = 0;
if (x2_in && y1_in)
values[1] = p + bypp;
else
values[1] = zeroes;
if (x1_in && y2_in)
values[2] = *(p + rowsiz + k);
else
values[2] = 0;
if (x1_in && y2_in)
values[2] = p + rowsiz;
else
values[2] = zeroes;
if (x2_in && y2_in)
values[3] = *(p + bypp + k + rowsiz);
else
values[3] = 0;
if (x2_in && y2_in)
values[3] = p + bypp + rowsiz;
else
values[3] = zeroes;
val = gimp_bilinear_8 (needx, needy, values);
*dest++ = val;
}
gimp_bilinear_pixels_8 (dest, needx, needy, bypp, has_alpha, values);
dest += bypp;
}
dst += rowsiz;

View File

@ -350,8 +350,7 @@ whirl_pinch (void)
guchar *top_row, *bot_row;
guchar *top_p, *bot_p;
gint row, col;
guchar pixel[4][4];
guchar values[4];
guchar **pixel;
double whirl;
double cx, cy;
int ix, iy;
@ -361,6 +360,9 @@ whirl_pinch (void)
/* Initialize rows */
top_row = g_malloc (img_bpp * sel_width);
bot_row = g_malloc (img_bpp * sel_width);
pixel = g_new (guchar *, 4);
for (i = 0; i < 4; i++)
pixel[i] = g_new (guchar, 4);
/* Initialize pixel region */
gimp_pixel_rgn_init (&dest_rgn, drawable,
@ -408,16 +410,9 @@ whirl_pinch (void)
gimp_pixel_fetcher_get_pixel (pft, ix, iy + 1, pixel[2]);
gimp_pixel_fetcher_get_pixel (pft, ix + 1, iy + 1, pixel[3]);
for (i = 0; i < img_bpp; i++)
{
values[0] = pixel[0][i];
values[1] = pixel[1][i];
values[2] = pixel[2][i];
values[3] = pixel[3][i];
*top_p++ = gimp_bilinear_8 (cx, cy, values);
}
gimp_bilinear_pixels_8 (top_p, cx, cy, img_bpp, img_has_alpha,
pixel);
top_p += img_bpp;
/* Bottom */
cx = cen_x + (cen_x - cx);
@ -438,17 +433,9 @@ whirl_pinch (void)
gimp_pixel_fetcher_get_pixel (pfb, ix, iy + 1, pixel[2]);
gimp_pixel_fetcher_get_pixel (pfb, ix + 1, iy + 1, pixel[3]);
for (i = 0; i < img_bpp; i++)
{
values[0] = pixel[0][i];
values[1] = pixel[1][i];
values[2] = pixel[2][i];
values[3] = pixel[3][i];
*bot_p++ = gimp_bilinear_8 (cx, cy, values);
}
bot_p -= 2 * img_bpp; /* We move backwards! */
gimp_bilinear_pixels_8 (bot_p, cx, cy, img_bpp, img_has_alpha,
pixel);
bot_p -= img_bpp;
}
else
{
@ -492,6 +479,9 @@ whirl_pinch (void)
gimp_pixel_fetcher_destroy (pft);
gimp_pixel_fetcher_destroy (pfb);
for (i = 0; i < 4; i++)
g_free (pixel[i]);
g_free (pixel);
g_free (top_row);
g_free (bot_row);