iterate over tiles instead of rows in the destination buffer.

2007-02-26  Sven Neumann  <sven@gimp.org>

	* app/core/gimp-transform-region.c (gimp_transform_region_lanczos):
	iterate	over tiles instead of rows in the destination buffer.


svn path=/trunk/; revision=21997
This commit is contained in:
Sven Neumann 2007-02-26 13:03:51 +00:00 committed by Sven Neumann
parent 43d2cde05f
commit ca30a115b3
2 changed files with 128 additions and 112 deletions

View file

@ -1,4 +1,9 @@
2007-02-24 Sven Neumann <sven@gimp.org>
2007-02-26 Sven Neumann <sven@gimp.org>
* app/core/gimp-transform-region.c (gimp_transform_region_lanczos):
iterate over tiles instead of rows in the destination buffer.
2007-02-26 Sven Neumann <sven@gimp.org>
* app/core/gimp-transform-region.c (gimp_transform_region): moved
linear and cubic code to their own functions and let them iterate

View file

@ -655,153 +655,164 @@ gimp_transform_region_lanczos (TileManager *orig_tiles,
GimpProgress *progress)
{
gfloat *lanczos; /* Lanczos lookup table */
guchar lwin[LANCZOS_WIDTH2 * LANCZOS_WIDTH2][MAX_CHANNELS + 1];
gdouble x_kernel[LANCZOS_WIDTH2]; /* 1-D kernels of window coeffs */
gdouble y_kernel[LANCZOS_WIDTH2];
gdouble x_sum, y_sum; /* sum of Lanczos weights */
gdouble uw;
gdouble ww;
gdouble vw;
gdouble du;
gdouble dv;
guchar *dest, *d;
gint x, y;
gint width;
gint bytes;
gint pos;
gdouble newval;
gdouble arecip;
gdouble aval;
guchar lwin[LANCZOS_WIDTH2 * LANCZOS_WIDTH2][MAX_CHANNELS + 1];
gint b, u, v, i, j;
gint pu, pv, su, sv;
gdouble uinc, vinc, winc; /* increments in source coordinates */
gint pixels;
gint total;
gint n;
gpointer pr;
/* allocate and fill lanczos lookup table */
lanczos = create_lanczos_lookup ();
width = dest_x2 - dest_x1;
bytes = destPR->bytes;
uinc = m->coeff[0][0];
vinc = m->coeff[1][0];
winc = m->coeff[2][0];
dest = g_new (guchar, width * bytes);
total = destPR->w * destPR->h;
for (y = dest_y1; y < dest_y2; y++)
for (pr = pixel_regions_register (1, destPR), pixels = 0, n = 0;
pr != NULL;
pr = pixel_regions_process (pr), n++)
{
if (progress && !(y & 0xf))
gimp_progress_set_value (progress,
(gdouble) (y - dest_y1) /
(gdouble) (dest_y2 - dest_y1));
guchar *dest = destPR->data;
gint y;
pixel_region_get_row (destPR, 0, (y - dest_y1), width, dest, 1);
d = dest;
for (x = dest_x1; x < dest_x2; x++)
for (y = destPR->y; y < destPR->y + destPR->h; y++)
{
uw = m->coeff[0][0] * x + m->coeff[0][1] * y + m->coeff[0][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];
gint x = dest_x1 + destPR->x;
gint width = destPR->w;
guchar *d = dest;
gdouble tu, tv, tw; /* undivided source coordinates and divisor */
normalize_coordinates (1, &uw, &vw, &ww, &du, &dv);
/* set up inverse transform steps */
tu = uinc * x + m->coeff[0][1] * (dest_y1 + y) + m->coeff[0][2];
tv = vinc * x + m->coeff[1][1] * (dest_y1 + y) + m->coeff[1][2];
tw = winc * x + m->coeff[2][1] * (dest_y1 + y) + m->coeff[2][2];
u = (gint) du;
v = (gint) dv;
/* get weight for fractional error */
su = (gint) ((du - u) * LANCZOS_SPP);
sv = (gint) ((dv - v) * LANCZOS_SPP);
if (u < u1 || v < v1 ||
u >= u2 || v >= v2)
while (width--)
{
/* not in source range */
/* increment the destination pointers */
for (b = 0; b < bytes; b++)
*d++ = bg_color[b];
}
else
{
pos = 0;
gdouble u, v; /* source coordinates */
gint iu, iv;
gint b;
for (j = 0; j < LANCZOS_WIDTH2 ; j++)
for (i = 0; i < LANCZOS_WIDTH2 ; i++, pos++)
{
pu = CLAMP (u + i - LANCZOS_WIDTH, u1, u2 - 1);
pv = CLAMP (v + j - LANCZOS_WIDTH, v1, v2 - 1);
/* normalize homogeneous coords */
normalize_coordinates (1, &tu, &tv, &tw, &u, &v);
read_pixel_data_1 (orig_tiles,
pu - u1, pv - v1, &lwin[pos][0]);
}
iu = (gint) u;
iv = (gint) v;
/* fill 1D kernels */
for (x_sum = y_sum = 0.0, i = LANCZOS_WIDTH;
i >= -LANCZOS_WIDTH;
i--)
if (iu < u1 || iv < v1 ||
iu >= u2 || iv >= v2)
{
pos = i * LANCZOS_SPP;
x_sum += x_kernel[LANCZOS_WIDTH + i] = lanczos[ABS (su - pos)];
y_sum += y_kernel[LANCZOS_WIDTH + i] = lanczos[ABS (sv - pos)];
}
/* normalise the weighted arrays */
for (i = 0; i < LANCZOS_WIDTH2 ; i++)
{
x_kernel[i] /= x_sum;
y_kernel[i] /= y_sum;
}
pos = 0;
aval = 0.0;
for (j = 0; j < LANCZOS_WIDTH2 ; j++)
for (i = 0; i < LANCZOS_WIDTH2 ; i++, pos++)
{
aval += y_kernel[j] * x_kernel[i] * lwin[pos][alpha];
}
if (aval <= 0.0)
{
arecip = 0.0;
aval = 0;
}
else if (aval > 255.0)
{
arecip = 1.0 / aval;
aval = 255;
/* not in source range */
for (b = 0; b < destPR->bytes; b++)
*d++ = bg_color[b];
}
else
{
arecip = 1.0 / aval;
}
gdouble arecip;
gdouble aval;
gint pos;
gint su, sv;
gint i, j;
for (b = 0; b < alpha; b++)
{
pos = 0;
newval = 0.0;
/* get weight for fractional error */
su = (gint) ((u - iu) * LANCZOS_SPP);
sv = (gint) ((v - iv) * LANCZOS_SPP);
for (j = 0; j < LANCZOS_WIDTH2 ; j++)
for (pos = 0, j = 0; j < LANCZOS_WIDTH2 ; j++)
for (i = 0; i < LANCZOS_WIDTH2 ; i++, pos++)
{
newval += y_kernel[j] * x_kernel[i] * lwin[pos][b] * lwin[pos][alpha];
gint pu = CLAMP (iu + i - LANCZOS_WIDTH, u1, u2 - 1);
gint pv = CLAMP (iv + j - LANCZOS_WIDTH, v1, v2 - 1);
read_pixel_data_1 (orig_tiles,
pu - u1, pv - v1, &lwin[pos][0]);
}
newval *= arecip;
*d++ = CLAMP (newval, 0, 255);
/* fill 1D kernels */
for (x_sum = y_sum = 0.0, i = LANCZOS_WIDTH;
i >= -LANCZOS_WIDTH;
i--)
{
pos = i * LANCZOS_SPP;
x_sum += x_kernel[LANCZOS_WIDTH + i] = lanczos[ABS (su - pos)];
y_sum += y_kernel[LANCZOS_WIDTH + i] = lanczos[ABS (sv - pos)];
}
/* normalise the weighted arrays */
for (i = 0; i < LANCZOS_WIDTH2 ; i++)
{
x_kernel[i] /= x_sum;
y_kernel[i] /= y_sum;
}
aval = 0.0;
for (pos = 0, j = 0; j < LANCZOS_WIDTH2 ; j++)
for (i = 0; i < LANCZOS_WIDTH2 ; i++, pos++)
{
aval += y_kernel[j] * x_kernel[i] * lwin[pos][alpha];
}
if (aval <= 0.0)
{
arecip = 0.0;
aval = 0;
}
else if (aval > 255.0)
{
arecip = 1.0 / aval;
aval = 255;
}
else
{
arecip = 1.0 / aval;
}
for (b = 0; b < alpha; b++)
{
gdouble newval = 0.0;
for (pos = 0, j = 0; j < LANCZOS_WIDTH2; j++)
for (i = 0; i < LANCZOS_WIDTH2; i++, pos++)
{
newval += (y_kernel[j] * x_kernel[i] *
lwin[pos][b] * lwin[pos][alpha]);
}
newval *= arecip;
*d++ = CLAMP (newval, 0, 255);
}
*d++ = RINT (aval);
}
*d++ = RINT (aval);
tu += uinc;
tv += vinc;
tw += winc;
}
dest += destPR->rowstride;
}
/* set the pixel region row */
pixel_region_set_row (destPR, 0, (y - dest_y1), width, dest);
}
if (progress)
{
pixels += destPR->w * destPR->h;
if (n % 16 == 0)
gimp_progress_set_value (progress,
(gdouble) pixels / (gdouble) total);
}
}
g_free (dest);
g_free (lanczos);
if (progress)
gimp_progress_set_value (progress, 1.0);
}