moved nearest-neighbor code to it's own function to improve performance
2007-02-24 Sven Neumann <sven@gimp.org> * app/core/gimp-transform-region.c (gimp_transform_region): moved nearest-neighbor code to it's own function to improve performance and readability. svn path=/trunk/; revision=21987
This commit is contained in:
committed by
Sven Neumann
parent
db72bf1358
commit
ef28e94e7f
@ -1,3 +1,9 @@
|
|||||||
|
2007-02-24 Sven Neumann <sven@gimp.org>
|
||||||
|
|
||||||
|
* app/core/gimp-transform-region.c (gimp_transform_region):
|
||||||
|
moved nearest-neighbor code to it's own function to improve
|
||||||
|
performance and readability.
|
||||||
|
|
||||||
2007-02-23 Sven Neumann <sven@gimp.org>
|
2007-02-23 Sven Neumann <sven@gimp.org>
|
||||||
|
|
||||||
* app/core/gimp-transform-region.c (gimp_transform_region): moved
|
* app/core/gimp-transform-region.c (gimp_transform_region): moved
|
||||||
|
|||||||
@ -44,6 +44,20 @@
|
|||||||
|
|
||||||
/* forward function prototypes */
|
/* forward function prototypes */
|
||||||
|
|
||||||
|
static void gimp_transform_region_nearest (TileManager *orig_tiles,
|
||||||
|
PixelRegion *destPR,
|
||||||
|
gint dest_x1,
|
||||||
|
gint dest_y1,
|
||||||
|
gint dest_x2,
|
||||||
|
gint dest_y2,
|
||||||
|
gint u1,
|
||||||
|
gint v1,
|
||||||
|
gint u2,
|
||||||
|
gint v2,
|
||||||
|
GimpMatrix3 *m,
|
||||||
|
gint alpha,
|
||||||
|
guchar *bg_color,
|
||||||
|
GimpProgress *progress);
|
||||||
static void gimp_transform_region_lanczos (TileManager *orig_tiles,
|
static void gimp_transform_region_lanczos (TileManager *orig_tiles,
|
||||||
PixelRegion *destPR,
|
PixelRegion *destPR,
|
||||||
gint dest_x1,
|
gint dest_x1,
|
||||||
@ -59,6 +73,13 @@ static void gimp_transform_region_lanczos (TileManager *orig_tiles,
|
|||||||
guchar *bg_color,
|
guchar *bg_color,
|
||||||
GimpProgress *progress);
|
GimpProgress *progress);
|
||||||
|
|
||||||
|
static inline void transform_coordinates (const gint coords,
|
||||||
|
const gdouble *tu,
|
||||||
|
const gdouble *tv,
|
||||||
|
const gdouble *tw,
|
||||||
|
gdouble *u,
|
||||||
|
gdouble *v);
|
||||||
|
|
||||||
static inline gboolean supersample_dtest (gdouble u0, gdouble v0,
|
static inline gboolean supersample_dtest (gdouble u0, gdouble v0,
|
||||||
gdouble u1, gdouble v1,
|
gdouble u1, gdouble v1,
|
||||||
gdouble u2, gdouble v2,
|
gdouble u2, gdouble v2,
|
||||||
@ -128,7 +149,6 @@ gimp_transform_region (GimpPickable *pickable,
|
|||||||
gdouble tu[5], tv[5], tw[5]; /* undivided source coordinates and
|
gdouble tu[5], tv[5], tw[5]; /* undivided source coordinates and
|
||||||
* divisor
|
* divisor
|
||||||
*/
|
*/
|
||||||
gint coords;
|
|
||||||
gint alpha;
|
gint alpha;
|
||||||
gint width;
|
gint width;
|
||||||
gint bytes;
|
gint bytes;
|
||||||
@ -190,15 +210,21 @@ gimp_transform_region (GimpPickable *pickable,
|
|||||||
switch (interpolation_type)
|
switch (interpolation_type)
|
||||||
{
|
{
|
||||||
case GIMP_INTERPOLATION_NONE:
|
case GIMP_INTERPOLATION_NONE:
|
||||||
break;
|
gimp_transform_region_nearest (orig_tiles, destPR,
|
||||||
|
dest_x1, dest_y1, dest_x2, dest_y2,
|
||||||
|
u1, v1, u2, v2,
|
||||||
|
&m, alpha, bg_color, progress);
|
||||||
|
return;
|
||||||
|
|
||||||
case GIMP_INTERPOLATION_LINEAR:
|
case GIMP_INTERPOLATION_LINEAR:
|
||||||
surround = pixel_surround_new (orig_tiles, 2, 2, bg_color);
|
surround = pixel_surround_new (orig_tiles, 2, 2, bg_color);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMP_INTERPOLATION_CUBIC:
|
case GIMP_INTERPOLATION_CUBIC:
|
||||||
surround = pixel_surround_new (orig_tiles, 4, 4, bg_color);
|
surround = pixel_surround_new (orig_tiles, 4, 4, bg_color);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIMP_INTERPOLATION_LANCZOS:
|
case GIMP_INTERPOLATION_LANCZOS:
|
||||||
/* lanczos is currently implemented separately */
|
|
||||||
gimp_transform_region_lanczos (orig_tiles, destPR,
|
gimp_transform_region_lanczos (orig_tiles, destPR,
|
||||||
dest_x1, dest_y1, dest_x2, dest_y2,
|
dest_x1, dest_y1, dest_x2, dest_y2,
|
||||||
u1, v1, u2, v2,
|
u1, v1, u2, v2,
|
||||||
@ -215,8 +241,6 @@ gimp_transform_region (GimpPickable *pickable,
|
|||||||
vinc = m.coeff[1][0];
|
vinc = m.coeff[1][0];
|
||||||
winc = m.coeff[2][0];
|
winc = m.coeff[2][0];
|
||||||
|
|
||||||
coords = (interpolation_type != GIMP_INTERPOLATION_NONE) ? 5 : 1;
|
|
||||||
|
|
||||||
for (y = dest_y1; y < dest_y2; y++)
|
for (y = dest_y1; y < dest_y2; y++)
|
||||||
{
|
{
|
||||||
if (progress && !(y & 0xf))
|
if (progress && !(y & 0xf))
|
||||||
@ -229,7 +253,6 @@ gimp_transform_region (GimpPickable *pickable,
|
|||||||
tv[0] = vinc * dest_x1 + m.coeff[1][1] * y + m.coeff[1][2];
|
tv[0] = vinc * dest_x1 + m.coeff[1][1] * y + m.coeff[1][2];
|
||||||
tw[0] = winc * dest_x1 + m.coeff[2][1] * y + m.coeff[2][2];
|
tw[0] = winc * dest_x1 + m.coeff[2][1] * y + m.coeff[2][2];
|
||||||
|
|
||||||
if (interpolation_type != GIMP_INTERPOLATION_NONE)
|
|
||||||
{
|
{
|
||||||
gdouble xx = dest_x1;
|
gdouble xx = dest_x1;
|
||||||
gdouble yy = y;
|
gdouble yy = y;
|
||||||
@ -255,76 +278,30 @@ gimp_transform_region (GimpPickable *pickable,
|
|||||||
|
|
||||||
for (x = dest_x1; x < dest_x2; x++)
|
for (x = dest_x1; x < dest_x2; x++)
|
||||||
{
|
{
|
||||||
gint i; /* normalize homogeneous coords */
|
gint i;
|
||||||
|
|
||||||
for (i = 0; i < coords; i++)
|
/* normalize homogeneous coords */
|
||||||
{
|
transform_coordinates (5, tu, tv, tw, u, v);
|
||||||
if (tw[i] == 1.0)
|
|
||||||
{
|
|
||||||
u[i] = tu[i];
|
|
||||||
v[i] = tv[i];
|
|
||||||
}
|
|
||||||
else if (tw[i] != 0.0)
|
|
||||||
{
|
|
||||||
u[i] = tu[i] / tw[i];
|
|
||||||
v[i] = tv[i] / tw[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_warning ("homogeneous coordinate = 0...\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the destination pixels */
|
/* Set the destination pixels */
|
||||||
if (interpolation_type == GIMP_INTERPOLATION_NONE)
|
if (u[0] < u1 || v[0] < v1 ||
|
||||||
{
|
u[0] >= u2 || v[0] >= v2 )
|
||||||
guchar color[MAX_CHANNELS];
|
|
||||||
gint iu = (gint) u[0];
|
|
||||||
gint iv = (gint) v[0];
|
|
||||||
gint b;
|
|
||||||
|
|
||||||
if (iu >= u1 && iu < u2 &&
|
|
||||||
iv >= v1 && iv < v2)
|
|
||||||
{
|
|
||||||
/* u, v coordinates into source tiles */
|
|
||||||
gint u = iu - u1;
|
|
||||||
gint v = iv - v1;
|
|
||||||
|
|
||||||
read_pixel_data_1 (orig_tiles, u, v, color);
|
|
||||||
|
|
||||||
for (b = 0; b < bytes; b++)
|
|
||||||
*d++ = color[b];
|
|
||||||
}
|
|
||||||
else /* not in source range */
|
|
||||||
{
|
|
||||||
/* increment the destination pointers */
|
|
||||||
|
|
||||||
for (b = 0; b < bytes; b++)
|
|
||||||
*d++ = bg_color[b];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gint b;
|
|
||||||
|
|
||||||
if (u [0] < u1 || v [0] < v1 ||
|
|
||||||
u [0] >= u2 || v [0] >= v2 )
|
|
||||||
{
|
{
|
||||||
/* not in source range */
|
/* not in source range */
|
||||||
/* increment the destination pointers */
|
/* increment the destination pointers */
|
||||||
|
|
||||||
for (b = 0; b < bytes; b++)
|
for (i = 0; i < bytes; i++)
|
||||||
*d++ = bg_color[b];
|
*d++ = bg_color[i];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
guchar color[MAX_CHANNELS];
|
guchar color[MAX_CHANNELS];
|
||||||
|
|
||||||
/* clamp texture coordinates */
|
/* clamp texture coordinates */
|
||||||
for (b = 0; b < 5; b++)
|
for (i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
u[b] = CLAMP (u[b], u1, u2 - 1);
|
u[i] = CLAMP (u[i], u1, u2 - 1);
|
||||||
v[b] = CLAMP (v[b], v1, v2 - 1);
|
v[i] = CLAMP (v[i], v1, v2 - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supersample &&
|
if (supersample &&
|
||||||
@ -363,12 +340,11 @@ gimp_transform_region (GimpPickable *pickable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set the destination pixel */
|
/* Set the destination pixel */
|
||||||
for (b = 0; b < bytes; b++)
|
for (i = 0; i < bytes; i++)
|
||||||
*d++ = color[b];
|
*d++ = color[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < coords; i++)
|
for (i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
tu[i] += uinc;
|
tu[i] += uinc;
|
||||||
tv[i] += vinc;
|
tv[i] += vinc;
|
||||||
@ -386,6 +362,94 @@ gimp_transform_region (GimpPickable *pickable,
|
|||||||
g_free (dest);
|
g_free (dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gimp_transform_region_nearest (TileManager *orig_tiles,
|
||||||
|
PixelRegion *destPR,
|
||||||
|
gint dest_x1,
|
||||||
|
gint dest_y1,
|
||||||
|
gint dest_x2,
|
||||||
|
gint dest_y2,
|
||||||
|
gint u1,
|
||||||
|
gint v1,
|
||||||
|
gint u2,
|
||||||
|
gint v2,
|
||||||
|
GimpMatrix3 *m,
|
||||||
|
gint alpha,
|
||||||
|
guchar *bg_color,
|
||||||
|
GimpProgress *progress)
|
||||||
|
{
|
||||||
|
guchar *dest;
|
||||||
|
gint x, y;
|
||||||
|
gint width;
|
||||||
|
gint bytes;
|
||||||
|
gdouble uinc, vinc, winc; /* increments in source coordinates */
|
||||||
|
|
||||||
|
width = dest_x2 - dest_x1;
|
||||||
|
bytes = destPR->bytes;
|
||||||
|
|
||||||
|
dest = g_new (guchar, width * bytes);
|
||||||
|
|
||||||
|
uinc = m->coeff[0][0];
|
||||||
|
vinc = m->coeff[1][0];
|
||||||
|
winc = m->coeff[2][0];
|
||||||
|
|
||||||
|
for (y = dest_y1; y < dest_y2; y++)
|
||||||
|
{
|
||||||
|
guchar *d = dest;
|
||||||
|
gdouble tu, tv, tw; /* undivided source coordinates and divisor */
|
||||||
|
|
||||||
|
/* set up inverse transform steps */
|
||||||
|
tu = uinc * dest_x1 + m->coeff[0][1] * y + m->coeff[0][2];
|
||||||
|
tv = vinc * dest_x1 + m->coeff[1][1] * y + m->coeff[1][2];
|
||||||
|
tw = winc * dest_x1 + m->coeff[2][1] * y + m->coeff[2][2];
|
||||||
|
|
||||||
|
if (progress && !(y & 0xf))
|
||||||
|
gimp_progress_set_value (progress,
|
||||||
|
(gdouble) (y - dest_y1) /
|
||||||
|
(gdouble) (dest_y2 - dest_y1));
|
||||||
|
|
||||||
|
for (x = dest_x1; x < dest_x2; x++)
|
||||||
|
{
|
||||||
|
guchar color[MAX_CHANNELS];
|
||||||
|
gdouble u, v; /* source coordinates */
|
||||||
|
gint iu, iv;
|
||||||
|
gint b;
|
||||||
|
|
||||||
|
/* normalize homogeneous coords */
|
||||||
|
transform_coordinates (1, &tu, &tv, &tw, &u, &v);
|
||||||
|
|
||||||
|
iu = (gint) u;
|
||||||
|
iv = (gint) v;
|
||||||
|
|
||||||
|
/* Set the destination pixels */
|
||||||
|
if (iu >= u1 && iu < u2 &&
|
||||||
|
iv >= v1 && iv < v2)
|
||||||
|
{
|
||||||
|
read_pixel_data_1 (orig_tiles, iu - u1, iv - v1, color);
|
||||||
|
|
||||||
|
for (b = 0; b < bytes; b++)
|
||||||
|
*d++ = color[b];
|
||||||
|
}
|
||||||
|
else /* not in source range */
|
||||||
|
{
|
||||||
|
/* increment the destination pointers */
|
||||||
|
|
||||||
|
for (b = 0; b < bytes; b++)
|
||||||
|
*d++ = bg_color[b];
|
||||||
|
}
|
||||||
|
|
||||||
|
tu += uinc;
|
||||||
|
tv += vinc;
|
||||||
|
tw += winc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the pixel region row */
|
||||||
|
pixel_region_set_row (destPR, 0, (y - dest_y1), width, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (dest);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gimp_transform_region_lanczos (TileManager *orig_tiles,
|
gimp_transform_region_lanczos (TileManager *orig_tiles,
|
||||||
PixelRegion *destPR,
|
PixelRegion *destPR,
|
||||||
@ -447,27 +511,15 @@ gimp_transform_region_lanczos (TileManager *orig_tiles,
|
|||||||
|
|
||||||
for (x = dest_x1; x < dest_x2; x++)
|
for (x = dest_x1; x < dest_x2; x++)
|
||||||
{
|
{
|
||||||
du = uw = m->coeff[0][0] * x + m->coeff[0][1] * y + m->coeff[0][2];
|
uw = m->coeff[0][0] * x + m->coeff[0][1] * y + m->coeff[0][2];
|
||||||
dv = vw = m->coeff[1][0] * x + m->coeff[1][1] * y + m->coeff[1][2];
|
vw = m->coeff[1][0] * x + m->coeff[1][1] * y + m->coeff[1][2];
|
||||||
ww = m->coeff[2][0] * x + m->coeff[2][1] * y + m->coeff[2][2];
|
ww = m->coeff[2][0] * x + m->coeff[2][1] * y + m->coeff[2][2];
|
||||||
|
|
||||||
if (ww == 1.0)
|
transform_coordinates (1, &uw, &vw, &ww, &du, &dv);
|
||||||
{
|
|
||||||
du = uw;
|
|
||||||
dv = vw;
|
|
||||||
}
|
|
||||||
else if (ww != 0.0)
|
|
||||||
{
|
|
||||||
du = uw / ww;
|
|
||||||
dv = vw / ww;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_warning ("homogeneous coordinate = 0...\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
u = (gint) du;
|
u = (gint) du;
|
||||||
v = (gint) dv;
|
v = (gint) dv;
|
||||||
|
|
||||||
/* get weight for fractional error */
|
/* get weight for fractional error */
|
||||||
su = (gint) ((du - u) * LANCZOS_SPP);
|
su = (gint) ((du - u) * LANCZOS_SPP);
|
||||||
sv = (gint) ((dv - v) * LANCZOS_SPP);
|
sv = (gint) ((dv - v) * LANCZOS_SPP);
|
||||||
@ -564,8 +616,43 @@ gimp_transform_region_lanczos (TileManager *orig_tiles,
|
|||||||
gimp_progress_set_value (progress, 1.0);
|
gimp_progress_set_value (progress, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* private functions */
|
/* private functions */
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
transform_coordinates (const gint coords,
|
||||||
|
const gdouble *tu,
|
||||||
|
const gdouble *tv,
|
||||||
|
const gdouble *tw,
|
||||||
|
gdouble *u,
|
||||||
|
gdouble *v)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
/* normalize homogeneous coords */
|
||||||
|
for (i = 0; i < coords; i++)
|
||||||
|
{
|
||||||
|
if (tw[i] == 1.0)
|
||||||
|
{
|
||||||
|
u[i] = tu[i];
|
||||||
|
v[i] = tv[i];
|
||||||
|
}
|
||||||
|
else if (tw[i] != 0.0)
|
||||||
|
{
|
||||||
|
u[i] = tu[i] / tw[i];
|
||||||
|
v[i] = tv[i] / tw[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning ("homogeneous coordinate = 0...\n");
|
||||||
|
|
||||||
|
u[i] = tu[i];
|
||||||
|
v[i] = tv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define BILINEAR(jk, j1k, jk1, j1k1, dx, dy) \
|
#define BILINEAR(jk, j1k, jk1, j1k1, dx, dy) \
|
||||||
((1 - dy) * (jk + dx * (j1k - jk)) + \
|
((1 - dy) * (jk + dx * (j1k - jk)) + \
|
||||||
dy * (jk1 + dx * (j1k1 - jk1)))
|
dy * (jk1 + dx * (j1k1 - jk1)))
|
||||||
|
|||||||
Reference in New Issue
Block a user