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>
* app/widgets/gimppropwidgets.[ch]: added gimp_prop_preview_new().

View File

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

View File

@ -3590,11 +3590,22 @@ p_vertical_bend (BenderDialog *cd,
if(cd->smoothing == TRUE)
{
/* 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));
mixcolor[0] = MIX_CHANNEL(last_arr[l_x].color[0], color[0], l_mixmask);
mixcolor[1] = MIX_CHANNEL(last_arr[l_x].color[1], color[1], l_mixmask);
mixcolor[2] = MIX_CHANNEL(last_arr[l_x].color[2], color[2], l_mixmask);
mixcolor[3] = MIX_CHANNEL(last_arr[l_x].color[3], color[3], l_mixmask);
alpha = alpha1 * l_mixmask + alpha2 * (255 - l_mixmask);
mixcolor[3] = alpha/255;
if (mixcolor[3])
{
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
{

View File

@ -176,6 +176,7 @@ deinterlace (GimpDrawable *drawable)
GimpPixelRgn srcPR, destPR;
gint width, height;
gint bytes;
gint has_alpha;
guchar *dest;
guchar *upper;
guchar *lower;
@ -191,6 +192,7 @@ deinterlace (GimpDrawable *drawable)
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
* 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, 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));

View File

@ -574,8 +574,6 @@ gauss_iir (GimpDrawable *drawable,
gdouble progress, max_progress;
gint initial_p[4];
gint initial_m[4];
guchar *guc_tmp1, *guc_tmp2;
gint *gi_tmp1, *gi_tmp2;
gdouble std_dev;
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 += (vert <= 0.0 ) ? 0 : width * height * vert;
if (has_alpha)
multiply_alpha (src, height, bytes);
/* First the vertical pass */
if (vert > 0.0)
@ -627,6 +623,8 @@ gauss_iir (GimpDrawable *drawable,
memset(val_m, 0, height * bytes * sizeof (gdouble));
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_m = src + (height - 1) * bytes;
@ -634,21 +632,11 @@ gauss_iir (GimpDrawable *drawable,
vm = val_m + (height - 1) * bytes;
/* 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++)
{
initial_p[i] = sp_p[i];
initial_m[i] = sp_m[i];
}
#endif
for (row = 0; row < height; row++)
{
@ -679,6 +667,8 @@ gauss_iir (GimpDrawable *drawable,
}
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));
@ -712,6 +702,8 @@ if (horz > 0.0)
memset(val_m, 0, width * bytes * sizeof (gdouble));
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_m = src + (width - 1) * bytes;
@ -719,21 +711,11 @@ if (horz > 0.0)
vm = val_m + (width - 1) * bytes;
/* 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++)
{
initial_p[i] = sp_p[i];
initial_m[i] = sp_m[i];
}
#endif
for (col = 0; col < width; col++)
{
@ -764,6 +746,8 @@ if (horz > 0.0)
}
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));
@ -773,9 +757,6 @@ if (horz > 0.0)
}
}
if (has_alpha)
separate_alpha (dest, width, bytes);
/* merge the shadow, update the drawable */
gimp_drawable_flush (drawable);
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]);
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++)
d_m [i] = d_p [i];
#endif
n_m[0] = 0.0;
for (i = 1; i <= 4; i++)
@ -889,14 +866,8 @@ find_constants (gdouble n_p[],
sum_d += d_p[i];
}
#ifndef ORIGINAL_READABLE_CODE
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
a = sum_n_p / (1.0 + sum_d);
b = sum_n_m / (1.0 + sum_d);
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 += (vert <= 0.0 ) ? 0 : width * height * vert;
if (has_alpha)
multiply_alpha (src, height, bytes);
/* First the vertical pass */
if (vert > 0.0)
@ -624,6 +622,8 @@ gauss_rle (GimpDrawable *drawable,
for (col = 0; col < width; col++)
{
gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, (y2 - y1));
if (has_alpha)
multiply_alpha (src, height, bytes);
sp = src;
dp = dest;
@ -665,6 +665,8 @@ gauss_rle (GimpDrawable *drawable,
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));
progress += height * vert;
@ -702,6 +704,8 @@ gauss_rle (GimpDrawable *drawable,
for (row = 0; row < height; row++)
{
gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, (x2 - x1));
if (has_alpha)
multiply_alpha (src, width, bytes);
sp = src;
dp = dest;
@ -743,6 +747,8 @@ gauss_rle (GimpDrawable *drawable,
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));
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 */
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 + 1, yi, p1);
iwarp_get_pixel (xi, yi + 1, p2);
iwarp_get_pixel (xi + 1, yi + 1, p3);
for (i = 0; i < image_bpp; i++)
iwarp_get_pixel (xi + 1, yi + 1, p3);
if (layer_alpha)
{
m0 = p0[i] + dx * (p1[i] - p0[i]);
m1 = p2[i] + dx * (p3[i] - p2[i]);
color[i] = (guchar) (m0 + dy * (m1 - m0));
gdouble a0 = p0[image_bpp-1];
gdouble a1 = p1[image_bpp-1];
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
iwarp_supersample_test (GimpVector2 *v0,
@ -613,13 +638,11 @@ iwarp_supersample (gint sxl,
srow[row-sxl], srow[row-sxl+1],
row, col, color, &cc, 0, 1.0);
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
dest = dest_data + (col-syl) * stride + (row-sxl) * image_bpp;
for (i = 0; i < image_bpp; i++)
*dest++ = color[i] / cc;
if (layer_alpha)
*dest++ = 255;
(*progress)++;
}
@ -679,16 +702,12 @@ iwarp_frame (void)
color);
for (i = 0; i < image_bpp; i++)
*dest++ = color[i];
if (layer_alpha)
*dest++ = 255;
}
else
{
iwarp_get_pixel (col, row, color);
for (i = 0; i < image_bpp; i++)
*dest++ = color[i];
if (layer_alpha)
*dest++ = 255;
}
}
dest_row += dest_rgn.rowstride;
@ -721,6 +740,11 @@ iwarp (void)
gchar *st;
gdouble delta;
if (image_bpp == 1 || image_bpp == 3)
layer_alpha = FALSE;
else
layer_alpha = TRUE;
if (animate_num_frames > 1 && do_animate)
{
animlayers = g_new (gint32, animate_num_frames);
@ -735,10 +759,6 @@ iwarp (void)
delta = 1.0 / (animate_num_frames - 1);
}
layerID = gimp_image_get_active_layer (imageID);
if (image_bpp == 1 || image_bpp == 3)
layer_alpha = TRUE;
else
layer_alpha = FALSE;
frame_number = 0;
for (i = 0; i < animate_num_frames; i++)
{
@ -896,7 +916,7 @@ iwarp_init (void)
xl, (gint) (pre2img * y) + yl, sel_width);
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);
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 sel_x1, sel_y1, sel_x2, sel_y2;
static gint sel_width, sel_height;
static gint has_alpha;
static double cen_x, cen_y;
@ -245,6 +246,7 @@ run (gchar *name,
gimp_tile_width () - 1) / gimp_tile_width ());
/* Run! */
has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
mblur ();
/* If run mode is interactive, flush displays */
@ -357,9 +359,20 @@ mblur_linear (void)
for (i = 0; i < n; )
{
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
for (c= 0; c < img_bpp; c++)
sum[c]+= pixel[c];
i++;
if (has_alpha)
{
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)
{
@ -379,16 +392,27 @@ mblur_linear (void)
break;
}
if ( i==0 )
if (i == 0)
{
gimp_pixel_fetcher_get_pixel (pft, xx, yy, d);
}
else
{
for (c=0; c < img_bpp; c++)
d[c]= sum[c] / i;
if (has_alpha)
{
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;
}
@ -483,8 +507,19 @@ mblur_radial (void)
++count;
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
for (c = 0; c < img_bpp; c++)
sum[c] += pixel[c];
if (has_alpha)
{
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)
@ -493,8 +528,19 @@ mblur_radial (void)
}
else
{
for (c = 0; c < img_bpp; c++)
d[c]= sum[c] / count;
if (has_alpha)
{
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;
}
@ -568,8 +614,19 @@ mblur_zoom (void)
break;
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
for (c = 0; c < img_bpp; c++)
sum[c] += pixel[c];
if (has_alpha)
{
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)
@ -578,8 +635,19 @@ mblur_zoom (void)
}
else
{
for (c = 0; c < img_bpp; c++)
d[c] = sum[c] / i;
if (has_alpha)
{
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;
}

View File

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

View File

@ -363,7 +363,7 @@ polarize (void)
guchar *dest, *d;
guchar pixel[4][4];
guchar pixel2[4];
guchar values[4];
gdouble values[4];
gint progress, max_progress;
double cx, cy;
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 + 1, cy + 1, pixel[3]);
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_8 (cx, cy, values);
}
if (img_has_alpha)
{
gdouble alpha;
values[0] = pixel[0][img_bpp-1];
values[1] = pixel[1][img_bpp-1];
values[2] = pixel[2][img_bpp-1];
values[3] = pixel[3][img_bpp-1];
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
{

View File

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