mirror of https://github.com/GNOME/gimp.git
applied patch from Jörg Gittinger that improves the quality of the Motion
2007-05-16 Sven Neumann <sven@gimp.org> * plug-ins/common/mblur.c: applied patch from Jörg Gittinger that improves the quality of the Motion Blur filter (bug #380435). svn path=/trunk/; revision=22513
This commit is contained in:
parent
8684b3267c
commit
3c9f28cc1e
|
@ -1,3 +1,8 @@
|
|||
2007-05-16 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* plug-ins/common/mblur.c: applied patch from Jörg Gittinger that
|
||||
improves the quality of the Motion Blur filter (bug #380435).
|
||||
|
||||
2007-05-16 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* plug-ins/script-fu/script-fu-interface.c (script_fu_interface):
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
* I also used some code from Whirl and Pinch plug-in by Federico Mena Quintero
|
||||
* (federico@nuclecu.unam.mx)
|
||||
*
|
||||
* Copyright (C) 2007 Joerg Gittinger (sw@gittingerbox.de)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
|
@ -30,22 +32,6 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Version 1.2
|
||||
*
|
||||
* Everything is new - no changes
|
||||
*
|
||||
* TODO:
|
||||
* Bilinear interpolation from original mblur for 0.54
|
||||
* Speed all things up
|
||||
* ? better caching scheme
|
||||
* - while blurring along long trajectory do not average all
|
||||
* pixels but average only few samples
|
||||
* Function for weight of samples along trajectory
|
||||
* Preview
|
||||
* Support paths in GiMP 1.1 :-)
|
||||
* Smash all bugs :-)
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libgimp/gimp.h>
|
||||
|
@ -56,7 +42,10 @@
|
|||
|
||||
#define PLUG_IN_PROC "plug-in-mblur"
|
||||
#define PLUG_IN_BINARY "mblur"
|
||||
#define PLUG_IN_VERSION "Sep 1997, 1.2"
|
||||
#define PLUG_IN_VERSION "May 2007, 1.3"
|
||||
|
||||
|
||||
#define MBLUR_LENGTH_MAX 256.0
|
||||
|
||||
|
||||
typedef enum
|
||||
|
@ -126,11 +115,11 @@ static mblur_vals_t mbvals =
|
|||
{
|
||||
MBLUR_LINEAR, /* mblur_type */
|
||||
5, /* length */
|
||||
45, /* radius */
|
||||
10, /* radius */
|
||||
100000.0, /* center_x */
|
||||
100000.0, /* center_y */
|
||||
TRUE, /* blur_outward */
|
||||
FALSE /* preview */
|
||||
TRUE /* preview */
|
||||
};
|
||||
|
||||
|
||||
|
@ -168,8 +157,8 @@ query (void)
|
|||
"This plug-in simulates the effect seen when "
|
||||
"photographing a moving object at a slow shutter "
|
||||
"speed. Done by adding multiple displaced copies.",
|
||||
"Torsten Martinsen, Federico Mena Quintero and Daniel Skarda",
|
||||
"Torsten Martinsen, Federico Mena Quintero and Daniel Skarda",
|
||||
"Torsten Martinsen, Federico Mena Quintero, Daniel Skarda, Joerg Gittinger",
|
||||
"Torsten Martinsen, Federico Mena Quintero, Daniel Skarda, Joerg Gittinger",
|
||||
PLUG_IN_VERSION,
|
||||
N_("_Motion Blur..."),
|
||||
"RGB*, GRAY*",
|
||||
|
@ -235,7 +224,7 @@ run (const gchar *name,
|
|||
/* Make sure all the arguments are present */
|
||||
if (nparams == 9)
|
||||
{
|
||||
mbvals.blur_outward = param[6].data.d_int32;
|
||||
mbvals.blur_outward = param[8].data.d_int32;
|
||||
--nparams;
|
||||
}
|
||||
|
||||
|
@ -312,7 +301,7 @@ mblur_linear (GimpDrawable *drawable,
|
|||
guchar pixel[4];
|
||||
gint32 sum[4];
|
||||
gint progress, max_progress;
|
||||
gint c;
|
||||
gint c, p;
|
||||
gint x, y, i, xx, yy, n;
|
||||
gint dx, dy, px, py, swapdir, err, e, s1, s2;
|
||||
|
||||
|
@ -376,9 +365,9 @@ mblur_linear (GimpDrawable *drawable,
|
|||
err = dy - dx; /* Initial error term */
|
||||
dx *= 2;
|
||||
|
||||
for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
|
||||
for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0;
|
||||
pr != NULL;
|
||||
pr = gimp_pixel_rgns_process (pr))
|
||||
pr = gimp_pixel_rgns_process (pr), p++)
|
||||
{
|
||||
dest = dest_rgn.data;
|
||||
|
||||
|
@ -395,6 +384,7 @@ mblur_linear (GimpDrawable *drawable,
|
|||
for (i = 0; i < n; )
|
||||
{
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
gint32 alpha = pixel[img_bpp-1];
|
||||
|
@ -468,13 +458,16 @@ mblur_linear (GimpDrawable *drawable,
|
|||
else
|
||||
{
|
||||
progress += dest_rgn.w * dest_rgn.h;
|
||||
gimp_progress_update ((gdouble) progress / max_progress);
|
||||
|
||||
if ((p % 8) == 0)
|
||||
gimp_progress_update ((gdouble) progress / max_progress);
|
||||
}
|
||||
}
|
||||
|
||||
gimp_pixel_fetcher_destroy (pft);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mblur_radial (GimpDrawable *drawable,
|
||||
GimpPreview *preview,
|
||||
|
@ -493,13 +486,15 @@ mblur_radial (GimpDrawable *drawable,
|
|||
guchar *dest;
|
||||
guchar *d;
|
||||
guchar pixel[4];
|
||||
guchar p1[4], p2[4], p3[4], p4[4];
|
||||
gint32 sum[4];
|
||||
|
||||
gint progress, max_progress, c;
|
||||
|
||||
gint x, y, i, n, xr, yr;
|
||||
gint count, R, r, w, h, step;
|
||||
gfloat angle, theta, * ct, * st, offset, xx, yy;
|
||||
gint x, y, i, p, n, count;
|
||||
gdouble angle, theta, r, xx, yy, xr, yr;
|
||||
gdouble phi, phi_start, s_val, c_val;
|
||||
gdouble dx, dy;
|
||||
|
||||
/* initialize */
|
||||
|
||||
|
@ -522,25 +517,9 @@ mblur_radial (GimpDrawable *drawable,
|
|||
|
||||
angle = gimp_deg_to_rad (mbvals.angle);
|
||||
|
||||
w = MAX (img_width - center_x, center_x);
|
||||
h = MAX (img_height - center_y, center_y);
|
||||
R = sqrt (w * w + h * h);
|
||||
n = 4 * angle * sqrt (R) + 2;
|
||||
theta = angle / ((float) (n - 1));
|
||||
|
||||
ct = g_new (float, n);
|
||||
st = g_new (float, n);
|
||||
|
||||
offset = theta * (n - 1) / 2;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
ct[i] = cos (theta * i - offset);
|
||||
st[i] = sin (theta * i - offset);
|
||||
}
|
||||
|
||||
for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
|
||||
for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0;
|
||||
pr != NULL;
|
||||
pr = gimp_pixel_rgns_process (pr))
|
||||
pr = gimp_pixel_rgns_process (pr), p++)
|
||||
{
|
||||
dest = dest_rgn.data;
|
||||
|
||||
|
@ -550,31 +529,88 @@ mblur_radial (GimpDrawable *drawable,
|
|||
|
||||
for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++)
|
||||
{
|
||||
xr = x - center_x;
|
||||
yr = y - center_y;
|
||||
r = sqrt (xr * xr + yr * yr);
|
||||
xr = (gdouble) x - center_x;
|
||||
yr = (gdouble) y - center_y;
|
||||
|
||||
if (r == 0)
|
||||
step = 1;
|
||||
else if ((step = R / r) == 0)
|
||||
step = 1;
|
||||
else if (step > n-1)
|
||||
step = n-1;
|
||||
r = sqrt (SQR (xr) + SQR (yr));
|
||||
n = r * angle;
|
||||
|
||||
if (angle == 0.0)
|
||||
{
|
||||
gimp_pixel_fetcher_get_pixel (pft, x, y, d);
|
||||
d += dest_rgn.bpp;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ensure quality with small angles */
|
||||
if (n < 3)
|
||||
n = 3; /* always use at least 3 (interpolation) steps */
|
||||
|
||||
/* limit loop count due to performanc reasons */
|
||||
if (n > 100)
|
||||
n = 100 + sqrt (n-100);
|
||||
|
||||
if (xr != 0.0)
|
||||
{
|
||||
phi = atan(yr/xr);
|
||||
if (xr < 0.0)
|
||||
phi = G_PI + phi;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (yr >= 0.0)
|
||||
phi = G_PI_2;
|
||||
else
|
||||
phi = -G_PI_2;
|
||||
}
|
||||
|
||||
for (c = 0; c < img_bpp; c++)
|
||||
sum[c] = 0;
|
||||
|
||||
for (i = 0, count = 0; i < n; i += step)
|
||||
if (n == 1)
|
||||
phi_start = phi;
|
||||
else
|
||||
phi_start = phi + angle/2.0;
|
||||
|
||||
theta = angle / (gdouble)n;
|
||||
count = 0;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
xx = center_x + xr * ct[i] - yr * st[i];
|
||||
yy = center_y + xr * st[i] + yr * ct[i];
|
||||
s_val = sin (phi_start - (gdouble) i * theta);
|
||||
c_val = cos (phi_start - (gdouble) i * theta);
|
||||
|
||||
xx = center_x + r * c_val;
|
||||
yy = center_y + r * s_val;
|
||||
|
||||
if ((yy < y1) || (yy >= y1 + height) ||
|
||||
(xx < x1) || (xx >= x1 + width))
|
||||
continue;
|
||||
|
||||
++count;
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
|
||||
if ((xx + 1 < x1 + width) && (yy + 1 < y1 + height))
|
||||
{
|
||||
dx = xx - floor (xx);
|
||||
dy = yy - floor (yy);
|
||||
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx, yy, p1);
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx+1, yy, p2);
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx, yy+1, p3);
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx+1, yy+1, p4);
|
||||
|
||||
for (c = 0; c < img_bpp; c++)
|
||||
{
|
||||
pixel[c] = (((gdouble) p1[c] * (1.0-dx) +
|
||||
(gdouble) p2[c] * dx) * (1.0-dy) +
|
||||
((gdouble) p3[c] * (1.0-dx) +
|
||||
(gdouble) p4[c] * dx) * dy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx+.5, yy+.5, pixel);
|
||||
}
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
|
@ -629,16 +665,17 @@ mblur_radial (GimpDrawable *drawable,
|
|||
else
|
||||
{
|
||||
progress += dest_rgn.w * dest_rgn.h;
|
||||
gimp_progress_update ((double) progress / max_progress);
|
||||
|
||||
if ((p % 8) == 0)
|
||||
gimp_progress_update ((gdouble) progress / max_progress);
|
||||
}
|
||||
}
|
||||
|
||||
gimp_pixel_fetcher_destroy (pft);
|
||||
|
||||
g_free (ct);
|
||||
g_free (st);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mblur_zoom (GimpDrawable *drawable,
|
||||
GimpPreview *preview,
|
||||
|
@ -656,11 +693,17 @@ mblur_zoom (GimpDrawable *drawable,
|
|||
gdouble center_y;
|
||||
guchar *dest, *d;
|
||||
guchar pixel[4];
|
||||
guchar p1[4], p2[4], p3[4], p4[4];
|
||||
gint32 sum[4];
|
||||
|
||||
gint progress, max_progress;
|
||||
gint x, y, i, xx, yy, n, c;
|
||||
gfloat f;
|
||||
gint x, y, i, n, p, c;
|
||||
gdouble xx_start, xx_end, yy_start, yy_end;
|
||||
gdouble xx, yy;
|
||||
gdouble dxx, dyy;
|
||||
gdouble dx, dy;
|
||||
gint xy_len;
|
||||
gdouble f, r;
|
||||
gint drawable_x1, drawable_y1;
|
||||
gint drawable_x2, drawable_y2;
|
||||
|
||||
|
@ -686,11 +729,17 @@ mblur_zoom (GimpDrawable *drawable,
|
|||
max_progress = width * height;
|
||||
|
||||
n = mbvals.length;
|
||||
f = 0.02;
|
||||
|
||||
for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
|
||||
r = sqrt (SQR (drawable->width / 2) + SQR (drawable->height / 2));
|
||||
n = ((gdouble) n * r / MBLUR_LENGTH_MAX);
|
||||
f = (r-n)/r;
|
||||
|
||||
for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0;
|
||||
pr != NULL;
|
||||
pr = gimp_pixel_rgns_process (pr))
|
||||
pr = gimp_pixel_rgns_process (pr), p++)
|
||||
{
|
||||
dest = dest_rgn.data;
|
||||
|
||||
|
@ -703,24 +752,60 @@ mblur_zoom (GimpDrawable *drawable,
|
|||
for (c = 0; c < img_bpp; c++)
|
||||
sum[c] = 0;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
if (mbvals.blur_outward)
|
||||
{
|
||||
xx = center_x + (x - center_x) * (1.0 - f * i);
|
||||
yy = center_y + (y - center_y) * (1.0 - f * i);
|
||||
}
|
||||
else
|
||||
{
|
||||
xx = center_x + (x - center_x) * (1.0 + f * i);
|
||||
yy = center_y + (y - center_y) * (1.0 + f * i);
|
||||
}
|
||||
xx_start = x;
|
||||
yy_start = y;
|
||||
|
||||
if (mbvals.blur_outward)
|
||||
{
|
||||
xx_end = center_x + ((gdouble) x - center_x) * f;
|
||||
yy_end = center_y + ((gdouble) y - center_y) * f;
|
||||
}
|
||||
else
|
||||
{
|
||||
xx_end = center_x + ((gdouble) x - center_x) * (1.0/f);
|
||||
yy_end = center_y + ((gdouble) y - center_y) * (1.0/f);
|
||||
}
|
||||
|
||||
xy_len = sqrt (SQR (xx_end-xx_start) + SQR (yy_end-yy_start)) + 1;
|
||||
|
||||
if (xy_len < 3)
|
||||
xy_len = 3;
|
||||
|
||||
dxx = (xx_end - xx_start) / (gdouble) xy_len;
|
||||
dyy = (yy_end - yy_start) / (gdouble) xy_len;
|
||||
|
||||
xx = xx_start;
|
||||
yy = yy_start;
|
||||
|
||||
for (i = 0; i < xy_len; i++)
|
||||
{
|
||||
if ((yy < drawable_y1) || (yy >= drawable_y2) ||
|
||||
(xx < drawable_x1) || (xx >= drawable_x2))
|
||||
break;
|
||||
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel);
|
||||
if ((xx+1 < drawable_x2) && (yy+1 < drawable_y2))
|
||||
{
|
||||
dx = xx - floor (xx);
|
||||
dy = yy - floor (yy);
|
||||
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx, yy, p1);
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx+1, yy, p2);
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx, yy+1, p3);
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx+1, yy+1, p4);
|
||||
|
||||
for (c = 0; c < img_bpp; c++)
|
||||
{
|
||||
pixel[c] = (((gdouble)p1[c] * (1.0-dx) +
|
||||
(gdouble)p2[c] * dx) * (1.0-dy) +
|
||||
((gdouble)p3[c] * (1.0-dx) +
|
||||
(gdouble)p4[c] * dx) * dy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_pixel_fetcher_get_pixel (pft, xx+.5, yy+.5, pixel);
|
||||
}
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
gint32 alpha = pixel[img_bpp-1];
|
||||
|
@ -735,6 +820,9 @@ mblur_zoom (GimpDrawable *drawable,
|
|||
for (c = 0; c < img_bpp; c++)
|
||||
sum[c] += pixel[c];
|
||||
}
|
||||
|
||||
xx += dxx;
|
||||
yy += dyy;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
|
@ -774,7 +862,9 @@ mblur_zoom (GimpDrawable *drawable,
|
|||
else
|
||||
{
|
||||
progress += dest_rgn.w * dest_rgn.h;
|
||||
gimp_progress_update ((double) progress / max_progress);
|
||||
|
||||
if ((p % 8) == 0)
|
||||
gimp_progress_update ((gdouble) progress / max_progress);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -840,7 +930,7 @@ mblur (GimpDrawable *drawable,
|
|||
static void
|
||||
mblur_set_sensitivity (void)
|
||||
{
|
||||
if (!length || !angle)
|
||||
if (!length || !angle || !center || !dir_button)
|
||||
return; /* Not initialized yet */
|
||||
|
||||
switch (mbvals.mblur_type)
|
||||
|
@ -1021,7 +1111,7 @@ mblur_dialog (gint32 image_ID,
|
|||
|
||||
length = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
|
||||
_("L_ength:"), 150, 3,
|
||||
mbvals.length, 1.0, 256.0, 1.0, 8.0, 0,
|
||||
mbvals.length, 1.0, MBLUR_LENGTH_MAX, 1.0, 8.0, 0,
|
||||
TRUE, 0, 0,
|
||||
NULL, NULL);
|
||||
|
||||
|
|
Loading…
Reference in New Issue