diff --git a/ChangeLog b/ChangeLog index 72747d9063..c4af0c8a2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2003-02-18 Sven Neumann + + Applied patches from David Necas 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 * app/widgets/gimppropwidgets.[ch]: added gimp_prop_preview_new(). diff --git a/libgimpcolor/gimpbilinear.c b/libgimpcolor/gimpbilinear.c index 2a981065a0..c85bb1cf22 100644 --- a/libgimpcolor/gimpbilinear.c +++ b/libgimpcolor/gimpbilinear.c @@ -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; } diff --git a/plug-ins/common/curve_bend.c b/plug-ins/common/curve_bend.c index 7f8224a8a5..9ed2097de6 100644 --- a/plug-ins/common/curve_bend.c +++ b/plug-ins/common/curve_bend.c @@ -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 { diff --git a/plug-ins/common/deinterlace.c b/plug-ins/common/deinterlace.c index 424e053c1b..43873d95dd 100644 --- a/plug-ins/common/deinterlace.c +++ b/plug-ins/common/deinterlace.c @@ -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)); diff --git a/plug-ins/common/gauss_iir.c b/plug-ins/common/gauss_iir.c index cad667df5f..138d70c4b0 100644 --- a/plug-ins/common/gauss_iir.c +++ b/plug-ins/common/gauss_iir.c @@ -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++) { diff --git a/plug-ins/common/gauss_rle.c b/plug-ins/common/gauss_rle.c index 3afa699daf..79ca3a3ac5 100644 --- a/plug-ins/common/gauss_rle.c +++ b/plug-ins/common/gauss_rle.c @@ -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); diff --git a/plug-ins/common/iwarp.c b/plug-ins/common/iwarp.c index 5a100a3fa6..1b632fa4c8 100644 --- a/plug-ins/common/iwarp.c +++ b/plug-ins/common/iwarp.c @@ -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++) { diff --git a/plug-ins/common/mblur.c b/plug-ins/common/mblur.c index d6b1def9e7..ddae6d5f22 100644 --- a/plug-ins/common/mblur.c +++ b/plug-ins/common/mblur.c @@ -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; } diff --git a/plug-ins/common/pixelize.c b/plug-ins/common/pixelize.c index 718fe4ccb3..48ef5c85c8 100644 --- a/plug-ins/common/pixelize.c +++ b/plug-ins/common/pixelize.c @@ -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 */ diff --git a/plug-ins/common/polar.c b/plug-ins/common/polar.c index 73c8edc367..e6860e95d8 100644 --- a/plug-ins/common/polar.c +++ b/plug-ins/common/polar.c @@ -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 { diff --git a/plug-ins/common/ripple.c b/plug-ins/common/ripple.c index 6f08a19c8c..c3167f36e1 100644 --- a/plug-ins/common/ripple.c +++ b/plug-ins/common/ripple.c @@ -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; }