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

2003-02-18  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:

	* libgimpcolor/gimpbilinear.c (gimp_bilinear_rgba): fixes RGBA
	resampling in Map Object and Lighting Effects plug-ins (#72876 and
	#105496).

	* plug-ins/common/curve_bend.c: fixes bug #72863.
	* plug-ins/common/deinterlace.c: fixes bug #72856.
	* plug-ins/common/gauss_iir.c: fixes bug #72848.
	* plug-ins/common/gauss_rle.c: fixes bug #72849.
	* plug-ins/common/iwarp.c: fixes bug #72865 (except preview, see
	comment).
	* plug-ins/common/mblur.c: fixes bug #72850.
	* plug-ins/common/pixelize.c: fixes bug #72851.
	* plug-ins/common/polar.c: fixes bug #72866.
	* plug-ins/common/ripple.c: fixes bug #72868.
This commit is contained in:
Sven Neumann 2003-02-18 17:54:02 +00:00 committed by Sven Neumann
parent 8929780522
commit ee835025dc
11 changed files with 456 additions and 205 deletions

View file

@ -1,3 +1,23 @@
2003-02-18 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:
* libgimpcolor/gimpbilinear.c (gimp_bilinear_rgba): fixes RGBA
resampling in Map Object and Lighting Effects plug-ins (#72876 and
#105496).
* plug-ins/common/curve_bend.c: fixes bug #72863.
* plug-ins/common/deinterlace.c: fixes bug #72856.
* plug-ins/common/gauss_iir.c: fixes bug #72848.
* plug-ins/common/gauss_rle.c: fixes bug #72849.
* plug-ins/common/iwarp.c: fixes bug #72865 (except preview, see
comment).
* plug-ins/common/mblur.c: fixes bug #72850.
* plug-ins/common/pixelize.c: fixes bug #72851.
* plug-ins/common/polar.c: fixes bug #72866.
* plug-ins/common/ripple.c: fixes bug #72868.
2003-02-18 Michael Natterer <mitch@gimp.org> 2003-02-18 Michael Natterer <mitch@gimp.org>
* app/widgets/gimppropwidgets.[ch]: added gimp_prop_preview_new(). * app/widgets/gimppropwidgets.[ch]: added gimp_prop_preview_new().

View file

@ -173,6 +173,7 @@ gimp_bilinear_rgba (gdouble x,
{ {
gdouble m0, m1; gdouble m0, m1;
gdouble ix, iy; gdouble ix, iy;
gdouble a0, a1, a2, a3, alpha;
GimpRGB v; GimpRGB v;
g_assert (values != NULL); g_assert (values != NULL);
@ -188,33 +189,41 @@ gimp_bilinear_rgba (gdouble x,
ix = 1.0 - x; ix = 1.0 - x;
iy = 1.0 - y; iy = 1.0 - y;
/* Red */ a0 = values[0].a;
a1 = values[1].a;
m0 = ix * values[0].r + x * values[1].r; a2 = values[2].a;
m1 = ix * values[2].r + x * values[3].r; a3 = values[3].a;
v.r = iy * m0 + y * m1;
/* Green */
m0 = ix * values[0].g + x * values[1].g;
m1 = ix * values[2].g + x * values[3].g;
v.g = iy * m0 + y * m1;
/* Blue */
m0 = ix * values[0].b + x * values[1].b;
m1 = ix * values[2].b + x * values[3].b;
v.b = iy * m0 + y * m1;
/* Alpha */ /* Alpha */
m0 = ix * values[0].a + x * values[1].a; m0 = ix * a0 + x * a1;
m1 = ix * values[2].a + x * values[3].a; m1 = ix * a2 + x * a3;
v.a = iy * m0 + y * m1; alpha = v.a = iy * m0 + y * m1;
if (alpha > 0)
{
/* Red */
m0 = ix * a0 * values[0].r + x * a1 * values[1].r;
m1 = ix * a2 * values[2].r + x * a3 * values[3].r;
v.r = (iy * m0 + y * m1)/alpha;
/* Green */
m0 = ix * a0 * values[0].g + x * a1 * values[1].g;
m1 = ix * a2 * values[2].g + x * a3 * values[3].g;
v.g = (iy * m0 + y * m1)/alpha;
/* Blue */
m0 = ix * a0 * values[0].b + x * a1 * values[1].b;
m1 = ix * a2 * values[2].b + x * a3 * values[3].b;
v.b = (iy * m0 + y * m1)/alpha;
}
return v; return v;
} }

View file

@ -3590,11 +3590,22 @@ p_vertical_bend (BenderDialog *cd,
if(cd->smoothing == TRUE) if(cd->smoothing == TRUE)
{ {
/* smooting is on, so we are using a mixed color */ /* smooting is on, so we are using a mixed color */
gulong alpha1 = last_arr[l_x].color[3];
gulong alpha2 = color[3];
gulong alpha;
l_mixmask = 255 * ((gdouble)(l_dy) / (gdouble)(l_diff+1)); l_mixmask = 255 * ((gdouble)(l_dy) / (gdouble)(l_diff+1));
mixcolor[0] = MIX_CHANNEL(last_arr[l_x].color[0], color[0], l_mixmask); alpha = alpha1 * l_mixmask + alpha2 * (255 - l_mixmask);
mixcolor[1] = MIX_CHANNEL(last_arr[l_x].color[1], color[1], l_mixmask); mixcolor[3] = alpha/255;
mixcolor[2] = MIX_CHANNEL(last_arr[l_x].color[2], color[2], l_mixmask); if (mixcolor[3])
mixcolor[3] = MIX_CHANNEL(last_arr[l_x].color[3], color[3], l_mixmask); {
mixcolor[0] = (alpha1 * l_mixmask * last_arr[l_x].color[0]
+ alpha2 * (255 - l_mixmask) * color[0])/alpha;
mixcolor[1] = (alpha1 * l_mixmask * last_arr[l_x].color[1]
+ alpha2 * (255 - l_mixmask) * color[1])/alpha;
mixcolor[2] = (alpha1 * l_mixmask * last_arr[l_x].color[2]
+ alpha2 * (255 - l_mixmask) * color[2])/alpha;
/*mixcolor[2] = MIX_CHANNEL(last_arr[l_x].color[2], color[2], l_mixmask);*/
}
} }
else else
{ {

View file

@ -176,6 +176,7 @@ deinterlace (GimpDrawable *drawable)
GimpPixelRgn srcPR, destPR; GimpPixelRgn srcPR, destPR;
gint width, height; gint width, height;
gint bytes; gint bytes;
gint has_alpha;
guchar *dest; guchar *dest;
guchar *upper; guchar *upper;
guchar *lower; guchar *lower;
@ -191,6 +192,7 @@ deinterlace (GimpDrawable *drawable)
gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
/* Get the size of the input image. (This will/must be the same /* Get the size of the input image. (This will/must be the same
* as the size of the output image. * as the size of the output image.
*/ */
@ -223,8 +225,36 @@ deinterlace (GimpDrawable *drawable)
{ {
gimp_pixel_rgn_get_row (&srcPR, upper, x1, row-1, (x2-x1)); gimp_pixel_rgn_get_row (&srcPR, upper, x1, row-1, (x2-x1));
gimp_pixel_rgn_get_row (&srcPR, lower, x1, row+1, (x2-x1)); gimp_pixel_rgn_get_row (&srcPR, lower, x1, row+1, (x2-x1));
for (col=0; col < ((x2-x1)*bytes); col++)
dest[col]=(upper[col]+lower[col])>>1; if (has_alpha)
{
guchar *upix = upper;
guchar *lpix = lower;
guchar *dpix = dest;
for (col = 0; col < x2-x1; col++)
{
gint b;
guint ualpha = upix[bytes-1];
guint lalpha = lpix[bytes-1];
guint alpha = ualpha + lalpha;
if (dpix[bytes-1] = alpha >> 1)
{
for (b = 0; b < bytes-1; b++)
dpix[b] = (upix[b] * ualpha
+ lpix[b] * lalpha) / alpha;
}
upix += bytes;
lpix += bytes;
dpix += bytes;
}
}
else
{
for (col = 0; col < ((x2-x1)*bytes); col++)
dest[col] = (upper[col] + lower[col]) >> 1;
}
} }
gimp_pixel_rgn_set_row (&destPR, dest, x1, row, (x2-x1)); gimp_pixel_rgn_set_row (&destPR, dest, x1, row, (x2-x1));

View file

@ -574,8 +574,6 @@ gauss_iir (GimpDrawable *drawable,
gdouble progress, max_progress; gdouble progress, max_progress;
gint initial_p[4]; gint initial_p[4];
gint initial_m[4]; gint initial_m[4];
guchar *guc_tmp1, *guc_tmp2;
gint *gi_tmp1, *gi_tmp2;
gdouble std_dev; gdouble std_dev;
if (horz <= 0.0 && vert <= 0.0) if (horz <= 0.0 && vert <= 0.0)
@ -609,8 +607,6 @@ gauss_iir (GimpDrawable *drawable,
max_progress = (horz <= 0.0 ) ? 0 : width * height * horz; max_progress = (horz <= 0.0 ) ? 0 : width * height * horz;
max_progress += (vert <= 0.0 ) ? 0 : width * height * vert; max_progress += (vert <= 0.0 ) ? 0 : width * height * vert;
if (has_alpha)
multiply_alpha (src, height, bytes);
/* First the vertical pass */ /* First the vertical pass */
if (vert > 0.0) if (vert > 0.0)
@ -627,6 +623,8 @@ gauss_iir (GimpDrawable *drawable,
memset(val_m, 0, height * bytes * sizeof (gdouble)); memset(val_m, 0, height * bytes * sizeof (gdouble));
gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, (y2 - y1)); gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, (y2 - y1));
if (has_alpha)
multiply_alpha (src, height, bytes);
sp_p = src; sp_p = src;
sp_m = src + (height - 1) * bytes; sp_m = src + (height - 1) * bytes;
@ -634,21 +632,11 @@ gauss_iir (GimpDrawable *drawable,
vm = val_m + (height - 1) * bytes; vm = val_m + (height - 1) * bytes;
/* Set up the first vals */ /* Set up the first vals */
#ifndef ORIGINAL_READABLE_CODE
for(guc_tmp1 = sp_p, guc_tmp2 = sp_m,
gi_tmp1 = initial_p, gi_tmp2 = initial_m;
(guc_tmp1 - sp_p) < bytes;)
{
*gi_tmp1++ = *guc_tmp1++;
*gi_tmp2++ = *guc_tmp2++;
}
#else
for (i = 0; i < bytes; i++) for (i = 0; i < bytes; i++)
{ {
initial_p[i] = sp_p[i]; initial_p[i] = sp_p[i];
initial_m[i] = sp_m[i]; initial_m[i] = sp_m[i];
} }
#endif
for (row = 0; row < height; row++) for (row = 0; row < height; row++)
{ {
@ -679,6 +667,8 @@ gauss_iir (GimpDrawable *drawable,
} }
transfer_pixels (val_p, val_m, dest, bytes, height); transfer_pixels (val_p, val_m, dest, bytes, height);
if (has_alpha)
separate_alpha (src, height, bytes);
gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, (y2 - y1)); gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, (y2 - y1));
@ -712,6 +702,8 @@ if (horz > 0.0)
memset(val_m, 0, width * bytes * sizeof (gdouble)); memset(val_m, 0, width * bytes * sizeof (gdouble));
gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, (x2 - x1)); gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, (x2 - x1));
if (has_alpha)
multiply_alpha (dest, width, bytes);
sp_p = src; sp_p = src;
sp_m = src + (width - 1) * bytes; sp_m = src + (width - 1) * bytes;
@ -719,21 +711,11 @@ if (horz > 0.0)
vm = val_m + (width - 1) * bytes; vm = val_m + (width - 1) * bytes;
/* Set up the first vals */ /* Set up the first vals */
#ifndef ORIGINAL_READABLE_CODE
for(guc_tmp1 = sp_p, guc_tmp2 = sp_m,
gi_tmp1 = initial_p, gi_tmp2 = initial_m;
(guc_tmp1 - sp_p) < bytes;)
{
*gi_tmp1++ = *guc_tmp1++;
*gi_tmp2++ = *guc_tmp2++;
}
#else
for (i = 0; i < bytes; i++) for (i = 0; i < bytes; i++)
{ {
initial_p[i] = sp_p[i]; initial_p[i] = sp_p[i];
initial_m[i] = sp_m[i]; initial_m[i] = sp_m[i];
} }
#endif
for (col = 0; col < width; col++) for (col = 0; col < width; col++)
{ {
@ -764,6 +746,8 @@ if (horz > 0.0)
} }
transfer_pixels (val_p, val_m, dest, bytes, width); transfer_pixels (val_p, val_m, dest, bytes, width);
if (has_alpha)
separate_alpha (dest, width, bytes);
gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, (x2 - x1)); gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, (x2 - x1));
@ -773,9 +757,6 @@ if (horz > 0.0)
} }
} }
if (has_alpha)
separate_alpha (dest, width, bytes);
/* merge the shadow, update the drawable */ /* merge the shadow, update the drawable */
gimp_drawable_flush (drawable); gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
@ -864,12 +845,8 @@ find_constants (gdouble n_p[],
2 * cos (constants[3]) * exp (constants[1] + 2 * constants[0]); 2 * cos (constants[3]) * exp (constants[1] + 2 * constants[0]);
d_p [4] = exp (2 * constants[0] + 2 * constants[1]); d_p [4] = exp (2 * constants[0] + 2 * constants[1]);
#ifndef ORIGINAL_READABLE_CODE
memcpy(d_m, d_p, 5 * sizeof(gdouble));
#else
for (i = 0; i <= 4; i++) for (i = 0; i <= 4; i++)
d_m [i] = d_p [i]; d_m [i] = d_p [i];
#endif
n_m[0] = 0.0; n_m[0] = 0.0;
for (i = 1; i <= 4; i++) for (i = 1; i <= 4; i++)
@ -889,14 +866,8 @@ find_constants (gdouble n_p[],
sum_d += d_p[i]; sum_d += d_p[i];
} }
#ifndef ORIGINAL_READABLE_CODE a = sum_n_p / (1.0 + sum_d);
sum_d++; b = sum_n_m / (1.0 + sum_d);
a = sum_n_p / sum_d;
b = sum_n_m / sum_d;
#else
a = sum_n_p / (1 + sum_d);
b = sum_n_m / (1 + sum_d);
#endif
for (i = 0; i <= 4; i++) for (i = 0; i <= 4; i++)
{ {

View file

@ -601,8 +601,6 @@ gauss_rle (GimpDrawable *drawable,
max_progress = (horz <= 0.0 ) ? 0 : width * height * horz; max_progress = (horz <= 0.0 ) ? 0 : width * height * horz;
max_progress += (vert <= 0.0 ) ? 0 : width * height * vert; max_progress += (vert <= 0.0 ) ? 0 : width * height * vert;
if (has_alpha)
multiply_alpha (src, height, bytes);
/* First the vertical pass */ /* First the vertical pass */
if (vert > 0.0) if (vert > 0.0)
@ -624,6 +622,8 @@ gauss_rle (GimpDrawable *drawable,
for (col = 0; col < width; col++) for (col = 0; col < width; col++)
{ {
gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, (y2 - y1)); gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, (y2 - y1));
if (has_alpha)
multiply_alpha (src, height, bytes);
sp = src; sp = src;
dp = dest; dp = dest;
@ -665,6 +665,8 @@ gauss_rle (GimpDrawable *drawable,
dp[row * bytes + b] = val / total; dp[row * bytes + b] = val / total;
} }
} }
if (has_alpha)
separate_alpha (dest, height, bytes);
gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, (y2 - y1)); gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, (y2 - y1));
progress += height * vert; progress += height * vert;
@ -702,6 +704,8 @@ gauss_rle (GimpDrawable *drawable,
for (row = 0; row < height; row++) for (row = 0; row < height; row++)
{ {
gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, (x2 - x1)); gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, (x2 - x1));
if (has_alpha)
multiply_alpha (src, width, bytes);
sp = src; sp = src;
dp = dest; dp = dest;
@ -743,6 +747,8 @@ gauss_rle (GimpDrawable *drawable,
dp[col * bytes + b] = val / total; dp[col * bytes + b] = val / total;
} }
} }
if (has_alpha)
separate_alpha (dest, width, bytes);
gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, (x2 - x1)); gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, (x2 - x1));
progress += width * horz; progress += width * horz;
@ -751,9 +757,6 @@ gauss_rle (GimpDrawable *drawable,
} }
} }
if (has_alpha)
separate_alpha (dest, width, bytes);
/* merge the shadow, update the drawable */ /* merge the shadow, update the drawable */
gimp_drawable_flush (drawable); gimp_drawable_flush (drawable);

View file

@ -421,14 +421,39 @@ iwarp_get_point (gdouble x,
iwarp_get_pixel (xi, yi, p0); iwarp_get_pixel (xi, yi, p0);
iwarp_get_pixel (xi + 1, yi, p1); iwarp_get_pixel (xi + 1, yi, p1);
iwarp_get_pixel (xi, yi + 1, p2); iwarp_get_pixel (xi, yi + 1, p2);
iwarp_get_pixel (xi + 1, yi + 1, p3); iwarp_get_pixel (xi + 1, yi + 1, p3);
for (i = 0; i < image_bpp; i++) if (layer_alpha)
{ {
m0 = p0[i] + dx * (p1[i] - p0[i]); gdouble a0 = p0[image_bpp-1];
m1 = p2[i] + dx * (p3[i] - p2[i]); gdouble a1 = p1[image_bpp-1];
color[i] = (guchar) (m0 + dy * (m1 - m0)); gdouble a2 = p2[image_bpp-1];
gdouble a3 = p3[image_bpp-1];
gdouble alpha;
m0 = a0 + dx * (a1 - a0);
m1 = a2 + dx * (a3 - a2);
alpha = (m0 + dy * (m1 - m0));
color[image_bpp-1] = alpha;
if (color[image_bpp-1])
{
for (i = 0; i < image_bpp-1; i++)
{
m0 = a0*p0[i] + dx * (a1*p1[i] - a0*p0[i]);
m1 = a2*p2[i] + dx * (a3*p3[i] - a2*p2[i]);
color[i] = (m0 + dy * (m1 - m0))/alpha;
}
}
} }
} else
{
for (i = 0; i < image_bpp; i++)
{
m0 = p0[i] + dx * (p1[i] - p0[i]);
m1 = p2[i] + dx * (p3[i] - p2[i]);
color[i] = m0 + dy * (m1 - m0);
}
}
}
static gboolean static gboolean
iwarp_supersample_test (GimpVector2 *v0, iwarp_supersample_test (GimpVector2 *v0,
@ -613,13 +638,11 @@ iwarp_supersample (gint sxl,
srow[row-sxl], srow[row-sxl+1], srow[row-sxl], srow[row-sxl+1],
row, col, color, &cc, 0, 1.0); row, col, color, &cc, 0, 1.0);
if (layer_alpha) if (layer_alpha)
dest = dest_data + (col-syl) * (stride) + (row-sxl) * (image_bpp+1); dest = dest_data + (col-syl) * (stride) + (row-sxl) * image_bpp;
else else
dest = dest_data + (col-syl) * stride + (row-sxl) * image_bpp; dest = dest_data + (col-syl) * stride + (row-sxl) * image_bpp;
for (i = 0; i < image_bpp; i++) for (i = 0; i < image_bpp; i++)
*dest++ = color[i] / cc; *dest++ = color[i] / cc;
if (layer_alpha)
*dest++ = 255;
(*progress)++; (*progress)++;
} }
@ -679,16 +702,12 @@ iwarp_frame (void)
color); color);
for (i = 0; i < image_bpp; i++) for (i = 0; i < image_bpp; i++)
*dest++ = color[i]; *dest++ = color[i];
if (layer_alpha)
*dest++ = 255;
} }
else else
{ {
iwarp_get_pixel (col, row, color); iwarp_get_pixel (col, row, color);
for (i = 0; i < image_bpp; i++) for (i = 0; i < image_bpp; i++)
*dest++ = color[i]; *dest++ = color[i];
if (layer_alpha)
*dest++ = 255;
} }
} }
dest_row += dest_rgn.rowstride; dest_row += dest_rgn.rowstride;
@ -721,6 +740,11 @@ iwarp (void)
gchar *st; gchar *st;
gdouble delta; gdouble delta;
if (image_bpp == 1 || image_bpp == 3)
layer_alpha = FALSE;
else
layer_alpha = TRUE;
if (animate_num_frames > 1 && do_animate) if (animate_num_frames > 1 && do_animate)
{ {
animlayers = g_new (gint32, animate_num_frames); animlayers = g_new (gint32, animate_num_frames);
@ -735,10 +759,6 @@ iwarp (void)
delta = 1.0 / (animate_num_frames - 1); delta = 1.0 / (animate_num_frames - 1);
} }
layerID = gimp_image_get_active_layer (imageID); layerID = gimp_image_get_active_layer (imageID);
if (image_bpp == 1 || image_bpp == 3)
layer_alpha = TRUE;
else
layer_alpha = FALSE;
frame_number = 0; frame_number = 0;
for (i = 0; i < animate_num_frames; i++) for (i = 0; i < animate_num_frames; i++)
{ {
@ -896,7 +916,7 @@ iwarp_init (void)
xl, (gint) (pre2img * y) + yl, sel_width); xl, (gint) (pre2img * y) + yl, sel_width);
for (x = 0; x < preview_width; x++) for (x = 0; x < preview_width; x++)
{ {
pts = srcimage + (y * preview_width +x) * image_bpp; pts = srcimage + (y * preview_width + x) * image_bpp;
xi = (gint) (pre2img * x); xi = (gint) (pre2img * x);
for (i = 0; i < image_bpp; i++) for (i = 0; i < image_bpp; i++)
{ {

View file

@ -118,6 +118,7 @@ static GtkObject *length, *angle;
static gint img_width, img_height, img_bpp; static gint img_width, img_height, img_bpp;
static gint sel_x1, sel_y1, sel_x2, sel_y2; static gint sel_x1, sel_y1, sel_x2, sel_y2;
static gint sel_width, sel_height; static gint sel_width, sel_height;
static gint has_alpha;
static double cen_x, cen_y; static double cen_x, cen_y;
@ -245,6 +246,7 @@ run (gchar *name,
gimp_tile_width () - 1) / gimp_tile_width ()); gimp_tile_width () - 1) / gimp_tile_width ());
/* Run! */ /* Run! */
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
mblur (); mblur ();
/* If run mode is interactive, flush displays */ /* If run mode is interactive, flush displays */
@ -357,9 +359,20 @@ mblur_linear (void)
for (i = 0; i < n; ) for (i = 0; i < n; )
{ {
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel); gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
for (c= 0; c < img_bpp; c++) if (has_alpha)
sum[c]+= pixel[c]; {
i++; gint32 alpha = pixel[img_bpp-1];
sum[img_bpp-1] += alpha;
for (c = 0; c < img_bpp-1; c++)
sum[c] += pixel[c] * alpha;
}
else
{
for (c = 0; c < img_bpp; c++)
sum[c] += pixel[c];
}
i++;
while (e >= 0 && dx) while (e >= 0 && dx)
{ {
@ -379,16 +392,27 @@ mblur_linear (void)
break; break;
} }
if ( i==0 ) if (i == 0)
{ {
gimp_pixel_fetcher_get_pixel (pft, xx, yy, d); gimp_pixel_fetcher_get_pixel (pft, xx, yy, d);
} }
else else
{ {
for (c=0; c < img_bpp; c++) if (has_alpha)
d[c]= sum[c] / i; {
gint32 alpha = sum[img_bpp-1];
if (d[img_bpp-1] = alpha/i)
for (c = 0; c < img_bpp-1; c++)
d[c] = sum[c] / alpha;
}
else
{
for (c = 0; c < img_bpp; c++)
d[c] = sum[c] / i;
}
} }
d+= dest_rgn.bpp; d += dest_rgn.bpp;
} }
dest += dest_rgn.rowstride; dest += dest_rgn.rowstride;
} }
@ -483,8 +507,19 @@ mblur_radial (void)
++count; ++count;
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel); gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
for (c = 0; c < img_bpp; c++) if (has_alpha)
sum[c] += pixel[c]; {
gint32 alpha = pixel[img_bpp-1];
sum[img_bpp-1] += alpha;
for (c = 0; c < img_bpp-1; c++)
sum[c] += pixel[c] * alpha;
}
else
{
for (c = 0; c < img_bpp; c++)
sum[c] += pixel[c];
}
} }
if (count == 0) if (count == 0)
@ -493,8 +528,19 @@ mblur_radial (void)
} }
else else
{ {
for (c = 0; c < img_bpp; c++) if (has_alpha)
d[c]= sum[c] / count; {
gint32 alpha = sum[img_bpp-1];
if (d[img_bpp-1] = alpha/count)
for (c = 0; c < img_bpp-1; c++)
d[c] = sum[c] / alpha;
}
else
{
for (c = 0; c < img_bpp; c++)
d[c] = sum[c] / count;
}
} }
d += dest_rgn.bpp; d += dest_rgn.bpp;
} }
@ -568,8 +614,19 @@ mblur_zoom (void)
break; break;
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel); gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
for (c = 0; c < img_bpp; c++) if (has_alpha)
sum[c] += pixel[c]; {
gint32 alpha = pixel[img_bpp-1];
sum[img_bpp-1] += alpha;
for (c = 0; c < img_bpp-1; c++)
sum[c] += pixel[c] * alpha;
}
else
{
for (c = 0; c < img_bpp; c++)
sum[c] += pixel[c];
}
} }
if (i == 0) if (i == 0)
@ -578,8 +635,19 @@ mblur_zoom (void)
} }
else else
{ {
for (c = 0; c < img_bpp; c++) if (has_alpha)
d[c] = sum[c] / i; {
gint32 alpha = sum[img_bpp-1];
if (d[img_bpp-1] = alpha/i)
for (c = 0; c < img_bpp-1; c++)
d[c] = sum[c] / alpha;
}
else
{
for (c = 0; c < img_bpp; c++)
d[c] = sum[c] / i;
}
} }
d += dest_rgn.bpp; d += dest_rgn.bpp;
} }

View file

@ -125,7 +125,8 @@ static void pixelize_small (GimpDrawable *drawable,
gint tile_height); gint tile_height);
static void pixelize_sub (gint pixelwidth, static void pixelize_sub (gint pixelwidth,
gint pixelheight, gint pixelheight,
gint bpp); gint bpp,
gint has_alpha);
/***** Local vars *****/ /***** Local vars *****/
@ -440,7 +441,7 @@ pixelize_large (GimpDrawable *drawable,
guchar *src_row, *dest_row; guchar *src_row, *dest_row;
guchar *src, *dest; guchar *src, *dest;
gulong *average; gulong *average;
gint row, col, b, bpp; gint row, col, b, bpp, has_alpha;
gint x, y, x_step, y_step; gint x, y, x_step, y_step;
gulong count; gulong count;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
@ -450,6 +451,7 @@ pixelize_large (GimpDrawable *drawable,
gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
bpp = gimp_drawable_bpp (drawable->drawable_id); bpp = gimp_drawable_bpp (drawable->drawable_id);
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
average = g_new (gulong, bpp); average = g_new (gulong, bpp);
/* Initialize progress */ /* Initialize progress */
@ -479,24 +481,50 @@ pixelize_large (GimpDrawable *drawable,
for (row = 0; row < src_rgn.h; row++) for (row = 0; row < src_rgn.h; row++)
{ {
src = src_row; src = src_row;
for (col = 0; col < src_rgn.w; col++) if (has_alpha)
{ {
for(b = 0; b < bpp; b++) for (col = 0; col < src_rgn.w; col++)
average[b] += src[b]; {
src += src_rgn.bpp; gulong alpha = src[bpp-1];
count += 1;
} average[bpp-1] += alpha;
for (b = 0; b < bpp-1; b++)
average[b] += src[b] * alpha;
src += src_rgn.bpp;
}
}
else
{
for (col = 0; col < src_rgn.w; col++)
{
for (b = 0; b < bpp; b++)
average[b] += src[b];
src += src_rgn.bpp;
}
}
src_row += src_rgn.rowstride; src_row += src_rgn.rowstride;
} }
/* Update progress */ /* Update progress */
count += src_rgn.w * src_rgn.h;
progress += src_rgn.w * src_rgn.h; progress += src_rgn.w * src_rgn.h;
gimp_progress_update ((double) progress / (double) max_progress); gimp_progress_update ((double) progress / (double) max_progress);
} }
if (count > 0) if (count > 0)
{ {
for (b = 0; b < bpp; b++) if (has_alpha)
average[b] = (guchar) (average[b] / count); {
gulong alpha = average[bpp-1];
if (average[bpp-1] = alpha/count)
for (b = 0; b < bpp-1; b++)
average[b] /= alpha;
}
else
{
for (b = 0; b < bpp; b++)
average[b] /= count;
}
} }
gimp_pixel_rgn_init (&dest_rgn, drawable, gimp_pixel_rgn_init (&dest_rgn, drawable,
@ -551,7 +579,7 @@ pixelize_small (GimpDrawable *drawable,
gint tile_height) gint tile_height)
{ {
GimpPixelRgn src_rgn, dest_rgn; GimpPixelRgn src_rgn, dest_rgn;
gint bpp; gint bpp, has_alpha;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
gint progress, max_progress; gint progress, max_progress;
@ -564,6 +592,7 @@ pixelize_small (GimpDrawable *drawable,
max_progress = (x2 - x1) * (y2 - y1); max_progress = (x2 - x1) * (y2 - y1);
bpp = drawable->bpp; bpp = drawable->bpp;
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
area.width = (tile_width / pixelwidth) * pixelwidth; area.width = (tile_width / pixelwidth) * pixelwidth;
area.height = (tile_height / pixelheight) * pixelheight; area.height = (tile_height / pixelheight) * pixelheight;
@ -584,7 +613,7 @@ pixelize_small (GimpDrawable *drawable,
gimp_pixel_rgn_get_rect (&src_rgn, area.data, gimp_pixel_rgn_get_rect (&src_rgn, area.data,
area.x, area.y, area.w, area.h); area.x, area.y, area.w, area.h);
pixelize_sub (pixelwidth, pixelheight, bpp); pixelize_sub (pixelwidth, pixelheight, bpp, has_alpha);
gimp_pixel_rgn_set_rect (&dest_rgn, area.data, gimp_pixel_rgn_set_rect (&dest_rgn, area.data,
area.x, area.y, area.w, area.h); area.x, area.y, area.w, area.h);
@ -611,9 +640,10 @@ pixelize_small (GimpDrawable *drawable,
static void static void
pixelize_sub (gint pixelwidth, pixelize_sub (gint pixelwidth,
gint pixelheight, gint pixelheight,
gint bpp) gint bpp,
gint has_alpha)
{ {
glong average[4]; /* bpp <= 4 */ gulong average[4]; /* bpp <= 4 */
gint x, y, w, h; gint x, y, w, h;
guchar *buf_row, *buf; guchar *buf_row, *buf;
gint row, col; gint row, col;
@ -643,21 +673,50 @@ pixelize_sub (gint pixelwidth,
for (row = 0; row < h; row++) for (row = 0; row < h; row++)
{ {
buf = buf_row; buf = buf_row;
for (col = 0; col < w; col++) if (has_alpha)
{ {
for (i = 0; i < bpp; i++) for (col = 0; col < w; col++)
average[i] += buf[i]; {
count++; gulong alpha = buf[bpp-1];
buf += bpp;
} average[bpp-1] += alpha;
for (i = 0; i < bpp-1; i++)
average[i] += buf[i] * alpha;
buf += bpp;
}
}
else
{
for (col = 0; col < w; col++)
{
for (i = 0; i < bpp; i++)
average[i] += buf[i];
buf += bpp;
}
}
buf_row += rowstride; buf_row += rowstride;
} }
count += w*h;
/* Average */ /* Average */
if (count > 0) if (count > 0)
{ {
for (i = 0; i < bpp; i++) if (has_alpha)
average[i] /= count; {
gulong alpha = average[bpp-1];
if (average[bpp-1] = alpha/count)
{
for (i = 0; i < bpp-1; i++)
average[i] /= alpha;
}
}
else
{
for (i = 0; i < bpp; i++)
average[i] /= count;
}
} }
/* Write */ /* Write */

View file

@ -363,7 +363,7 @@ polarize (void)
guchar *dest, *d; guchar *dest, *d;
guchar pixel[4][4]; guchar pixel[4][4];
guchar pixel2[4]; guchar pixel2[4];
guchar values[4]; gdouble values[4];
gint progress, max_progress; gint progress, max_progress;
double cx, cy; double cx, cy;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
@ -407,15 +407,41 @@ polarize (void)
gimp_pixel_fetcher_get_pixel (pft, cx, cy + 1, pixel[2]); gimp_pixel_fetcher_get_pixel (pft, cx, cy + 1, pixel[2]);
gimp_pixel_fetcher_get_pixel (pft, cx + 1, cy + 1, pixel[3]); gimp_pixel_fetcher_get_pixel (pft, cx + 1, cy + 1, pixel[3]);
for (b = 0; b < img_bpp; b++) if (img_has_alpha)
{ {
values[0] = pixel[0][b]; gdouble alpha;
values[1] = pixel[1][b]; values[0] = pixel[0][img_bpp-1];
values[2] = pixel[2][b]; values[1] = pixel[1][img_bpp-1];
values[3] = pixel[3][b]; values[2] = pixel[2][img_bpp-1];
values[3] = pixel[3][img_bpp-1];
d[b] = gimp_bilinear_8 (cx, cy, values); alpha = gimp_bilinear (cx, cy, values);
} d[img_bpp-1] = alpha;
if (d[img_bpp-1])
{
for (b = 0; b < img_bpp-1; b++)
{
values[0] = pixel[0][img_bpp-1] * pixel[0][b];
values[1] = pixel[1][img_bpp-1] * pixel[1][b];
values[2] = pixel[2][img_bpp-1] * pixel[2][b];
values[3] = pixel[3][img_bpp-1] * pixel[3][b];
d[b] = gimp_bilinear (cx, cy, values)/alpha;
}
}
}
else
{
for (b = 0; b < img_bpp; b++)
{
values[0] = pixel[0][b];
values[1] = pixel[1][b];
values[2] = pixel[2][b];
values[3] = pixel[3][b];
d[b] = gimp_bilinear (cx, cy, values);
}
}
} }
else else
{ {

View file

@ -73,17 +73,23 @@ static void run (gchar *name,
gint *nreturn_vals, gint *nreturn_vals,
GimpParam **return_vals); GimpParam **return_vals);
static void ripple (GimpDrawable *drawable); static void ripple (GimpDrawable *drawable);
static gint ripple_dialog (void); static gint ripple_dialog (void);
static void ripple_ok_callback (GtkWidget *widget, static void ripple_ok_callback (GtkWidget *widget,
gpointer data); gpointer data);
static gdouble displace_amount (gint location); static gdouble displace_amount (gint location);
static guchar averagetwo (gdouble location, static void average_two_pixels (guchar *dest,
guchar *v); guchar pixels[4][4],
static guchar averagefour (gdouble location, gdouble x,
guchar *v); gint bpp,
gboolean has_alpha);
static void average_four_pixels (guchar *dest,
guchar pixels[4][4],
gdouble x,
gint bpp,
gboolean has_alpha);
/***** Local vars *****/ /***** Local vars *****/
@ -251,25 +257,24 @@ ripple (GimpDrawable *drawable)
GimpPixelRgn dest_rgn; GimpPixelRgn dest_rgn;
gpointer pr; gpointer pr;
GimpPixelFetcher *pft; GimpPixelFetcher *pft;
gint width, height; gint width, height;
gint bytes; gint bytes;
guchar *destline; gboolean has_alpha;
guchar *dest; guchar *destline;
guchar *otherdest; guchar *dest;
guchar pixel[4][4]; guchar *otherdest;
gint x1, y1, x2, y2; guchar pixel[4][4];
gint x, y; gint x1, y1, x2, y2;
gint progress, max_progress; gint x, y;
gdouble needx, needy; gint progress, max_progress;
gdouble needx, needy;
guchar values[4];
gint xi, yi; gint xi, yi;
gint k;
pft = gimp_pixel_fetcher_new (drawable); pft = gimp_pixel_fetcher_new (drawable);
gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
width = drawable->width; width = drawable->width;
height = drawable->height; height = drawable->height;
@ -344,12 +349,9 @@ ripple (GimpDrawable *drawable)
gimp_pixel_fetcher_get_pixel (pft, x, yi + 1, gimp_pixel_fetcher_get_pixel (pft, x, yi + 1,
pixel[1]); pixel[1]);
for (k = 0; k < bytes; k++) average_two_pixels (otherdest, pixel,
{ needy, bytes, has_alpha);
values[0] = pixel[0][k]; otherdest += bytes;
values[1] = pixel[1][k];
*otherdest++ = averagetwo(needy, values);
}
} }
else else
{ {
@ -361,14 +363,9 @@ ripple (GimpDrawable *drawable)
gimp_pixel_fetcher_get_pixel (pft, x, yi + 2, gimp_pixel_fetcher_get_pixel (pft, x, yi + 2,
pixel[3]); pixel[3]);
for (k = 0; k < bytes; k++) average_four_pixels(otherdest, pixel,
{ needy, bytes, has_alpha);
values[0] = pixel[0][k]; otherdest += bytes;
values[1] = pixel[1][k];
values[2] = pixel[2][k];
values[3] = pixel[3][k];
*otherdest++ = averagefour (needy, values);
}
} }
} /* antialias */ } /* antialias */
else else
@ -428,12 +425,9 @@ ripple (GimpDrawable *drawable)
gimp_pixel_fetcher_get_pixel (pft, xi + 1, y, gimp_pixel_fetcher_get_pixel (pft, xi + 1, y,
pixel[1]); pixel[1]);
for (k = 0; k < bytes; k++) average_two_pixels (dest, pixel,
{ needx, bytes, has_alpha);
values[0] = pixel[0][k]; dest += bytes;
values[1] = pixel[1][k];
*dest++ = averagetwo (needx, values);
}
} }
else else
{ {
@ -445,14 +439,9 @@ ripple (GimpDrawable *drawable)
gimp_pixel_fetcher_get_pixel (pft, xi + 2, y, gimp_pixel_fetcher_get_pixel (pft, xi + 2, y,
pixel[3]); pixel[3]);
for (k = 0; k < bytes; k++) average_four_pixels(dest, pixel,
{ needx, bytes, has_alpha);
values[0] = pixel[0][k]; dest += bytes;
values[1] = pixel[1][k];
values[2] = pixel[2][k];
values[3] = pixel[3][k];
*dest++ = averagefour (needx, values);
}
} }
} /* antialias */ } /* antialias */
@ -652,22 +641,66 @@ ripple_ok_callback (GtkWidget *widget,
gtk_widget_destroy (GTK_WIDGET (data)); gtk_widget_destroy (GTK_WIDGET (data));
} }
static guchar static void
averagetwo (gdouble location, average_two_pixels (guchar *dest,
guchar *v) guchar pixels[4][4],
gdouble x,
gint bpp,
gboolean has_alpha)
{ {
location = fmod(location, 1.0); gint b;
return (guchar) ((1.0 - location) * v[0] + location * v[1]); x = fmod (x, 1.0);
if (has_alpha)
{
double xa0 = pixels[0][bpp-1] * (1.0 - x);
double xa1 = pixels[1][bpp-1] * x;
double alpha;
alpha = xa0 + xa1;
dest[bpp-1] = alpha;
if (dest[bpp-1])
for (b = 0; b < bpp-1; b++)
dest[b] = (xa0 * pixels[0][b] + xa1 * pixels[1][b])/alpha;
}
else
{
for (b = 0; b < bpp; b++)
dest[b] = (1.0 - x) * pixels[0][b] + x * pixels[1][b];
}
} }
static guchar static void
averagefour (gdouble location, average_four_pixels (guchar *dest,
guchar *v) guchar pixels[4][4],
gdouble x,
gint bpp,
gboolean has_alpha)
{ {
location = fmod(location, 1.0); gint b;
return ((1.0 - location) * (v[0] + v[2]) + location * (v[1] + v[3]))/2; x = fmod (x, 1.0);
if (has_alpha)
{
double xa0 = pixels[0][bpp-1] * (1.0 - x)/2;
double xa1 = pixels[1][bpp-1] * x/2;
double xa2 = pixels[2][bpp-1] * (1.0 - x)/2;
double xa3 = pixels[3][bpp-1] * x/2;
double alpha;
alpha = xa0 + xa1 + xa2 + xa3;
dest[bpp-1] = alpha;
if (dest[bpp-1])
for (b = 0; b < bpp-1; b++)
dest[b] = (xa0 * pixels[0][b] + xa1 * pixels[1][b]
+ xa2 * pixels[2][b] + xa3 * pixels[3][b])/alpha;
}
else
{
for (b = 0; b < bpp; b++)
dest[b] = (1.0 - x) * (pixels[0][b] + pixels[2][b])
+ x * (pixels[1][b] + pixels[3][b]);
}
} }
static gdouble static gdouble
@ -676,12 +709,13 @@ displace_amount (gint location)
switch (rvals.waveform) switch (rvals.waveform)
{ {
case SINE: case SINE:
return rvals.amplitude*sin(location*(2*G_PI)/(double)rvals.period); return (rvals.amplitude *
sin (location * (2 * G_PI) / (gdouble) rvals.period));
case SAWTOOTH: case SAWTOOTH:
return floor (rvals.amplitude * return floor (rvals.amplitude *
(fabs ((((location%rvals.period) / (fabs ((((location % rvals.period) /
(double)rvals.period) * 4) - 2) - 1)); (gdouble) rvals.period) * 4) - 2) - 1));
} }
return 0; return 0.0;
} }