1566 lines
55 KiB
C
1566 lines
55 KiB
C
#include "common.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "asm_c.h"
|
|
#include "image.h"
|
|
#include "scale.h"
|
|
|
|
/*\ NB: If you change this, don't forget asm_scale.S \*/
|
|
struct _imlib_scale_info {
|
|
int *xpoints;
|
|
uint32_t **ypoints;
|
|
int *xapoints, *yapoints;
|
|
int xup_yup;
|
|
uint32_t *pix_assert;
|
|
};
|
|
|
|
#define INV_XAP (256 - xapoints[x])
|
|
#define XAP (xapoints[x])
|
|
#define INV_YAP (256 - yapoints[dyy + y])
|
|
#define YAP (yapoints[dyy + y])
|
|
|
|
static uint32_t **
|
|
__imlib_CalcYPoints(uint32_t * src, int sw, int sh, int dh, int b1, int b2)
|
|
{
|
|
uint32_t **p;
|
|
int i, j = 0;
|
|
int val, inc, rv = 0;
|
|
|
|
if (dh < 0)
|
|
{
|
|
dh = -dh;
|
|
rv = 1;
|
|
}
|
|
|
|
p = malloc((dh + 1) * sizeof(uint32_t *));
|
|
if (!p)
|
|
return NULL;
|
|
|
|
val = MIN(sh, dh);
|
|
inc = b1 + b2;
|
|
if (val < inc)
|
|
{
|
|
b1 = (val * b1 + inc / 2) / inc;
|
|
b2 = val - b1;
|
|
}
|
|
|
|
val = 0;
|
|
inc = 1 << 16;
|
|
for (i = 0; i < b1; i++)
|
|
{
|
|
p[j++] = src + ((val >> 16) * sw);
|
|
val += inc;
|
|
}
|
|
if (dh > (b1 + b2))
|
|
{
|
|
val = (b1 << 16);
|
|
inc = ((sh - b1 - b2) << 16) / (dh - (b1 + b2));
|
|
for (i = 0; i < (dh - b1 - b2); i++)
|
|
{
|
|
p[j++] = src + ((val >> 16) * sw);
|
|
val += inc;
|
|
}
|
|
}
|
|
val = (sh - b2) << 16;
|
|
inc = 1 << 16;
|
|
for (i = 0; i <= b2; i++)
|
|
{
|
|
p[j++] = src + ((val >> 16) * sw);
|
|
val += inc;
|
|
}
|
|
|
|
if (rv)
|
|
for (i = dh / 2; --i >= 0;)
|
|
{
|
|
uint32_t *tmp = p[i];
|
|
|
|
p[i] = p[dh - i - 1];
|
|
p[dh - i - 1] = tmp;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
static int *
|
|
__imlib_CalcXPoints(int sw, int dw, int b1, int b2)
|
|
{
|
|
int *p, i, j = 0;
|
|
int val, inc, rv = 0;
|
|
|
|
if (dw < 0)
|
|
{
|
|
dw = -dw;
|
|
rv = 1;
|
|
}
|
|
|
|
p = malloc((dw + 1) * sizeof(int));
|
|
if (!p)
|
|
return NULL;
|
|
|
|
val = MIN(sw, dw);
|
|
inc = b1 + b2;
|
|
if (val < inc)
|
|
{
|
|
b1 = (val * b1 + inc / 2) / inc;
|
|
b2 = val - b1;
|
|
}
|
|
|
|
val = 0;
|
|
inc = 1 << 16;
|
|
for (i = 0; i < b1; i++)
|
|
{
|
|
p[j++] = (val >> 16);
|
|
val += inc;
|
|
}
|
|
if (dw > (b1 + b2))
|
|
{
|
|
val = (b1 << 16);
|
|
inc = ((sw - b1 - b2) << 16) / (dw - (b1 + b2));
|
|
for (i = 0; i < (dw - b1 - b2); i++)
|
|
{
|
|
p[j++] = (val >> 16);
|
|
val += inc;
|
|
}
|
|
}
|
|
val = (sw - b2) << 16;
|
|
inc = 1 << 16;
|
|
for (i = 0; i <= b2; i++)
|
|
{
|
|
p[j++] = (val >> 16);
|
|
val += inc;
|
|
}
|
|
|
|
if (rv)
|
|
for (i = dw / 2; --i >= 0;)
|
|
{
|
|
int tmp = p[i];
|
|
|
|
p[i] = p[dw - i - 1];
|
|
p[dw - i - 1] = tmp;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
static int *
|
|
__imlib_CalcApoints(int s, int d, int b1, int b2, int up)
|
|
{
|
|
int *p, i, j = 0, rv = 0;
|
|
int val, inc;
|
|
|
|
if (d < 0)
|
|
{
|
|
rv = 1;
|
|
d = -d;
|
|
}
|
|
|
|
p = malloc(d * sizeof(int));
|
|
if (!p)
|
|
return NULL;
|
|
|
|
val = MIN(s, d);
|
|
inc = b1 + b2;
|
|
if (val < inc)
|
|
{
|
|
b1 = (val * b1 + inc / 2) / inc;
|
|
b2 = val - b1;
|
|
}
|
|
|
|
/* scaling up */
|
|
if (up)
|
|
{
|
|
for (i = 0; i < b1; i++)
|
|
p[j++] = 0;
|
|
if (d > (b1 + b2))
|
|
{
|
|
int ss, dd;
|
|
|
|
ss = s - b1 - b2;
|
|
dd = d - b1 - b2;
|
|
val = 0;
|
|
inc = (ss << 16) / dd;
|
|
for (i = 0; i < dd; i++)
|
|
{
|
|
p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
|
|
if (((val >> 16) + b1) >= (s - 1))
|
|
p[j - 1] = 0;
|
|
val += inc;
|
|
}
|
|
}
|
|
for (i = 0; i < b2; i++)
|
|
p[j++] = 0;
|
|
}
|
|
/* scaling down */
|
|
else
|
|
{
|
|
for (i = 0; i < b1; i++)
|
|
p[j++] = (1 << (16 + 14)) + (1 << 14);
|
|
if (d > (b1 + b2))
|
|
{
|
|
int ss, dd, ap, Cp;
|
|
|
|
ss = s - (b1 + b2);
|
|
dd = d - (b1 + b2);
|
|
val = 0;
|
|
inc = (ss << 16) / dd;
|
|
Cp = ((dd << 14) / ss) + 1;
|
|
for (i = 0; i < dd; i++)
|
|
{
|
|
ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
|
|
p[j] = ap | (Cp << 16);
|
|
j++;
|
|
val += inc;
|
|
}
|
|
}
|
|
for (i = 0; i < b2; i++)
|
|
p[j++] = (1 << (16 + 14)) + (1 << 14);
|
|
}
|
|
|
|
if (rv)
|
|
{
|
|
for (i = d / 2; --i >= 0;)
|
|
{
|
|
int tmp = p[i];
|
|
|
|
p[i] = p[d - i - 1];
|
|
p[d - i - 1] = tmp;
|
|
}
|
|
}
|
|
return p;
|
|
}
|
|
|
|
ImlibScaleInfo *
|
|
__imlib_FreeScaleInfo(ImlibScaleInfo * isi)
|
|
{
|
|
if (isi)
|
|
{
|
|
free(isi->xpoints);
|
|
free(isi->ypoints);
|
|
free(isi->xapoints);
|
|
free(isi->yapoints);
|
|
free(isi);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
ImlibScaleInfo *
|
|
__imlib_CalcScaleInfo(ImlibImage * im, int sw, int sh, int dw, int dh, char aa)
|
|
{
|
|
ImlibScaleInfo *isi;
|
|
int scw, sch;
|
|
|
|
scw = dw * im->w / sw;
|
|
sch = dh * im->h / sh;
|
|
|
|
isi = malloc(sizeof(ImlibScaleInfo));
|
|
if (!isi)
|
|
return NULL;
|
|
memset(isi, 0, sizeof(ImlibScaleInfo));
|
|
|
|
isi->pix_assert = im->data + im->w * im->h;
|
|
|
|
isi->xup_yup = (abs(dw) >= sw) + ((abs(dh) >= sh) << 1);
|
|
|
|
isi->xpoints = __imlib_CalcXPoints(im->w, scw,
|
|
im->border.left, im->border.right);
|
|
if (!isi->xpoints)
|
|
return __imlib_FreeScaleInfo(isi);
|
|
isi->ypoints = __imlib_CalcYPoints(im->data, im->w, im->h, sch,
|
|
im->border.top, im->border.bottom);
|
|
if (!isi->ypoints)
|
|
return __imlib_FreeScaleInfo(isi);
|
|
if (aa)
|
|
{
|
|
isi->xapoints = __imlib_CalcApoints(im->w, scw, im->border.left,
|
|
im->border.right, isi->xup_yup & 1);
|
|
if (!isi->xapoints)
|
|
return __imlib_FreeScaleInfo(isi);
|
|
isi->yapoints = __imlib_CalcApoints(im->h, sch, im->border.top,
|
|
im->border.bottom,
|
|
isi->xup_yup & 2);
|
|
if (!isi->yapoints)
|
|
return __imlib_FreeScaleInfo(isi);
|
|
}
|
|
return isi;
|
|
}
|
|
|
|
/* scale by pixel sampling only */
|
|
void
|
|
__imlib_ScaleSampleRGBA(ImlibScaleInfo * isi, uint32_t * dest, int dxx, int dyy,
|
|
int dx, int dy, int dw, int dh, int dow)
|
|
{
|
|
uint32_t *sptr, *dptr;
|
|
int x, y, end;
|
|
uint32_t **ypoints = isi->ypoints;
|
|
int *xpoints = isi->xpoints;
|
|
|
|
/* whats the last pixel on the line so we stop there */
|
|
end = dxx + dw;
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
/* get the pointer to the start of the destination scanline */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
/* calculate the source line we'll scan from */
|
|
sptr = ypoints[dyy + y];
|
|
/* go thru the scanline and copy across */
|
|
for (x = dxx; x < end; x++)
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
|
|
/* FIXME: NEED to optimise ScaleAARGBA - currently its "ok" but needs work*/
|
|
|
|
/* scale by area sampling */
|
|
void
|
|
__imlib_ScaleAARGBA(ImlibScaleInfo * isi, uint32_t * dest, int dxx, int dyy,
|
|
int dx, int dy, int dw, int dh, int dow, int sow)
|
|
{
|
|
uint32_t *sptr, *dptr;
|
|
int x, y, end;
|
|
uint32_t **ypoints;
|
|
int *xpoints;
|
|
int *xapoints;
|
|
int *yapoints;
|
|
|
|
#ifdef DO_MMX_ASM
|
|
if (__imlib_do_asm())
|
|
{
|
|
__imlib_Scale_mmx_AARGBA(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
ypoints = isi->ypoints;
|
|
xpoints = isi->xpoints;
|
|
xapoints = isi->xapoints;
|
|
yapoints = isi->yapoints;
|
|
|
|
end = dxx + dw;
|
|
/* scaling up both ways */
|
|
if (isi->xup_yup == 3)
|
|
{
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
/* calculate the source line we'll scan from */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
sptr = ypoints[dyy + y];
|
|
if (YAP > 0)
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r, g, b, a;
|
|
int rr, gg, bb, aa;
|
|
uint32_t *pix;
|
|
|
|
if (XAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_XAP;
|
|
g = G_VAL(pix) * INV_XAP;
|
|
b = B_VAL(pix) * INV_XAP;
|
|
a = A_VAL(pix) * INV_XAP;
|
|
pix++;
|
|
r += R_VAL(pix) * XAP;
|
|
g += G_VAL(pix) * XAP;
|
|
b += B_VAL(pix) * XAP;
|
|
a += A_VAL(pix) * XAP;
|
|
pix += sow;
|
|
rr = R_VAL(pix) * XAP;
|
|
gg = G_VAL(pix) * XAP;
|
|
bb = B_VAL(pix) * XAP;
|
|
aa = A_VAL(pix) * XAP;
|
|
pix--;
|
|
rr += R_VAL(pix) * INV_XAP;
|
|
gg += G_VAL(pix) * INV_XAP;
|
|
bb += B_VAL(pix) * INV_XAP;
|
|
aa += A_VAL(pix) * INV_XAP;
|
|
r = ((rr * YAP) + (r * INV_YAP)) >> 16;
|
|
g = ((gg * YAP) + (g * INV_YAP)) >> 16;
|
|
b = ((bb * YAP) + (b * INV_YAP)) >> 16;
|
|
a = ((aa * YAP) + (a * INV_YAP)) >> 16;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
else
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_YAP;
|
|
g = G_VAL(pix) * INV_YAP;
|
|
b = B_VAL(pix) * INV_YAP;
|
|
a = A_VAL(pix) * INV_YAP;
|
|
pix += sow;
|
|
r += R_VAL(pix) * YAP;
|
|
g += G_VAL(pix) * YAP;
|
|
b += B_VAL(pix) * YAP;
|
|
a += A_VAL(pix) * YAP;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
a >>= 8;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r, g, b, a;
|
|
uint32_t *pix;
|
|
|
|
if (XAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_XAP;
|
|
g = G_VAL(pix) * INV_XAP;
|
|
b = B_VAL(pix) * INV_XAP;
|
|
a = A_VAL(pix) * INV_XAP;
|
|
pix++;
|
|
r += R_VAL(pix) * XAP;
|
|
g += G_VAL(pix) * XAP;
|
|
b += B_VAL(pix) * XAP;
|
|
a += A_VAL(pix) * XAP;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
a >>= 8;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
else
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* if we're scaling down vertically */
|
|
else if (isi->xup_yup == 1)
|
|
#ifndef OLD_SCALE_DOWN
|
|
{
|
|
/*\ 'Correct' version, with math units prepared for MMXification \ */
|
|
int Cy, j;
|
|
uint32_t *pix;
|
|
int r, g, b, a, rr, gg, bb, aa;
|
|
int yap;
|
|
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
Cy = YAP >> 16;
|
|
yap = YAP & 0xffff;
|
|
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = (R_VAL(pix) * yap) >> 10;
|
|
g = (G_VAL(pix) * yap) >> 10;
|
|
b = (B_VAL(pix) * yap) >> 10;
|
|
a = (A_VAL(pix) * yap) >> 10;
|
|
for (j = (1 << 14) - yap; j > Cy; j -= Cy)
|
|
{
|
|
pix += sow;
|
|
r += (R_VAL(pix) * Cy) >> 10;
|
|
g += (G_VAL(pix) * Cy) >> 10;
|
|
b += (B_VAL(pix) * Cy) >> 10;
|
|
a += (A_VAL(pix) * Cy) >> 10;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
pix += sow;
|
|
r += (R_VAL(pix) * j) >> 10;
|
|
g += (G_VAL(pix) * j) >> 10;
|
|
b += (B_VAL(pix) * j) >> 10;
|
|
a += (A_VAL(pix) * j) >> 10;
|
|
}
|
|
assert(pix < isi->pix_assert);
|
|
if (XAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x] + 1;
|
|
rr = (R_VAL(pix) * yap) >> 10;
|
|
gg = (G_VAL(pix) * yap) >> 10;
|
|
bb = (B_VAL(pix) * yap) >> 10;
|
|
aa = (A_VAL(pix) * yap) >> 10;
|
|
for (j = (1 << 14) - yap; j > Cy; j -= Cy)
|
|
{
|
|
pix += sow;
|
|
rr += (R_VAL(pix) * Cy) >> 10;
|
|
gg += (G_VAL(pix) * Cy) >> 10;
|
|
bb += (B_VAL(pix) * Cy) >> 10;
|
|
aa += (A_VAL(pix) * Cy) >> 10;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
pix += sow;
|
|
rr += (R_VAL(pix) * j) >> 10;
|
|
gg += (G_VAL(pix) * j) >> 10;
|
|
bb += (B_VAL(pix) * j) >> 10;
|
|
aa += (A_VAL(pix) * j) >> 10;
|
|
}
|
|
assert(pix < isi->pix_assert);
|
|
r = r * INV_XAP;
|
|
g = g * INV_XAP;
|
|
b = b * INV_XAP;
|
|
a = a * INV_XAP;
|
|
r = (r + ((rr * XAP))) >> 12;
|
|
g = (g + ((gg * XAP))) >> 12;
|
|
b = (b + ((bb * XAP))) >> 12;
|
|
a = (a + ((aa * XAP))) >> 12;
|
|
}
|
|
else
|
|
{
|
|
r >>= 4;
|
|
g >>= 4;
|
|
b >>= 4;
|
|
a >>= 4;
|
|
}
|
|
*dptr = PIXEL_ARGB(a, r, g, b);
|
|
dptr++;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
int yap;
|
|
|
|
/* calculate the source line we'll scan from */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
sptr = ypoints[dyy + y];
|
|
|
|
yap = (ypoints[dyy + y + 1] - ypoints[dyy + y]) / sow;
|
|
if (yap > 1)
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0, a = 0;
|
|
int rr = 0, gg = 0, bb = 0, aa = 0;
|
|
uint32_t *pix;
|
|
|
|
if (XAP > 0)
|
|
{
|
|
pix = sptr + xpoints[x];
|
|
for (j = 0; j < yap; j++)
|
|
{
|
|
r += R_VAL(pix);
|
|
g += G_VAL(pix);
|
|
b += B_VAL(pix);
|
|
a += A_VAL(pix);
|
|
rr += R_VAL(pix + 1);
|
|
gg += G_VAL(pix + 1);
|
|
bb += B_VAL(pix + 1);
|
|
aa += A_VAL(pix + 1);
|
|
pix += sow;
|
|
}
|
|
r = r * INV_XAP / yap;
|
|
g = g * INV_XAP / yap;
|
|
b = b * INV_XAP / yap;
|
|
a = a * INV_XAP / yap;
|
|
r = (r + ((rr * XAP) / yap)) >> 8;
|
|
g = (g + ((gg * XAP) / yap)) >> 8;
|
|
b = (b + ((bb * XAP) / yap)) >> 8;
|
|
a = (a + ((aa * XAP) / yap)) >> 8;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
else
|
|
{
|
|
pix = sptr + xpoints[x];
|
|
for (j = 0; j < yap; j++)
|
|
{
|
|
r += R_VAL(pix);
|
|
g += G_VAL(pix);
|
|
b += B_VAL(pix);
|
|
a += A_VAL(pix);
|
|
pix += sow;
|
|
}
|
|
r /= yap;
|
|
g /= yap;
|
|
b /= yap;
|
|
a /= yap;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0, a = 0;
|
|
int count;
|
|
uint32_t *pix;
|
|
|
|
if (XAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_XAP;
|
|
g = G_VAL(pix) * INV_XAP;
|
|
b = B_VAL(pix) * INV_XAP;
|
|
a = A_VAL(pix) * INV_XAP;
|
|
pix++;
|
|
r += R_VAL(pix) * XAP;
|
|
g += G_VAL(pix) * XAP;
|
|
b += B_VAL(pix) * XAP;
|
|
a += A_VAL(pix) * XAP;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
a >>= 8;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
else
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/* if we're scaling down horizontally */
|
|
else if (isi->xup_yup == 2)
|
|
#ifndef OLD_SCALE_DOWN
|
|
{
|
|
/*\ 'Correct' version, with math units prepared for MMXification \ */
|
|
int Cx, j;
|
|
uint32_t *pix;
|
|
int r, g, b, a, rr, gg, bb, aa;
|
|
int xap;
|
|
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
Cx = XAP >> 16;
|
|
xap = XAP & 0xffff;
|
|
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = (R_VAL(pix) * xap) >> 10;
|
|
g = (G_VAL(pix) * xap) >> 10;
|
|
b = (B_VAL(pix) * xap) >> 10;
|
|
a = (A_VAL(pix) * xap) >> 10;
|
|
for (j = (1 << 14) - xap; j > Cx; j -= Cx)
|
|
{
|
|
pix++;
|
|
r += (R_VAL(pix) * Cx) >> 10;
|
|
g += (G_VAL(pix) * Cx) >> 10;
|
|
b += (B_VAL(pix) * Cx) >> 10;
|
|
a += (A_VAL(pix) * Cx) >> 10;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
pix++;
|
|
r += (R_VAL(pix) * j) >> 10;
|
|
g += (G_VAL(pix) * j) >> 10;
|
|
b += (B_VAL(pix) * j) >> 10;
|
|
a += (A_VAL(pix) * j) >> 10;
|
|
}
|
|
assert(pix < isi->pix_assert);
|
|
if (YAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x] + sow;
|
|
rr = (R_VAL(pix) * xap) >> 10;
|
|
gg = (G_VAL(pix) * xap) >> 10;
|
|
bb = (B_VAL(pix) * xap) >> 10;
|
|
aa = (A_VAL(pix) * xap) >> 10;
|
|
for (j = (1 << 14) - xap; j > Cx; j -= Cx)
|
|
{
|
|
pix++;
|
|
rr += (R_VAL(pix) * Cx) >> 10;
|
|
gg += (G_VAL(pix) * Cx) >> 10;
|
|
bb += (B_VAL(pix) * Cx) >> 10;
|
|
aa += (A_VAL(pix) * Cx) >> 10;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
pix++;
|
|
rr += (R_VAL(pix) * j) >> 10;
|
|
gg += (G_VAL(pix) * j) >> 10;
|
|
bb += (B_VAL(pix) * j) >> 10;
|
|
aa += (A_VAL(pix) * j) >> 10;
|
|
}
|
|
assert(pix < isi->pix_assert);
|
|
r = r * INV_YAP;
|
|
g = g * INV_YAP;
|
|
b = b * INV_YAP;
|
|
a = a * INV_YAP;
|
|
r = (r + ((rr * YAP))) >> 12;
|
|
g = (g + ((gg * YAP))) >> 12;
|
|
b = (b + ((bb * YAP))) >> 12;
|
|
a = (a + ((aa * YAP))) >> 12;
|
|
}
|
|
else
|
|
{
|
|
r >>= 4;
|
|
g >>= 4;
|
|
b >>= 4;
|
|
a >>= 4;
|
|
}
|
|
*dptr = PIXEL_ARGB(a, r, g, b);
|
|
dptr++;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
/* calculate the source line we'll scan from */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
sptr = ypoints[dyy + y];
|
|
if (YAP > 0)
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0, a = 0;
|
|
int rr = 0, gg = 0, bb = 0, aa = 0;
|
|
int xap;
|
|
uint32_t *pix;
|
|
|
|
xap = xpoints[x + 1] - xpoints[x];
|
|
if (xap > 1)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
for (i = 0; i < xap; i++)
|
|
{
|
|
r += R_VAL(pix + i);
|
|
g += G_VAL(pix + i);
|
|
b += B_VAL(pix + i);
|
|
a += A_VAL(pix + i);
|
|
}
|
|
r = r * INV_YAP / xap;
|
|
g = g * INV_YAP / xap;
|
|
b = b * INV_YAP / xap;
|
|
a = a * INV_YAP / xap;
|
|
pix = ypoints[dyy + y] + xpoints[x] + sow;
|
|
for (i = 0; i < xap; i++)
|
|
{
|
|
rr += R_VAL(pix + i);
|
|
gg += G_VAL(pix + i);
|
|
bb += B_VAL(pix + i);
|
|
aa += A_VAL(pix + i);
|
|
}
|
|
r = (r + ((rr * YAP) / xap)) >> 8;
|
|
g = (g + ((gg * YAP) / xap)) >> 8;
|
|
b = (b + ((bb * YAP) / xap)) >> 8;
|
|
a = (a + ((aa * YAP) / xap)) >> 8;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
else
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_YAP;
|
|
g = G_VAL(pix) * INV_YAP;
|
|
b = B_VAL(pix) * INV_YAP;
|
|
a = A_VAL(pix) * INV_YAP;
|
|
pix += sow;
|
|
r += R_VAL(pix) * YAP;
|
|
g += G_VAL(pix) * YAP;
|
|
b += B_VAL(pix) * YAP;
|
|
a += A_VAL(pix) * YAP;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
a >>= 8;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0, a = 0;
|
|
int xap;
|
|
uint32_t *pix;
|
|
|
|
xap = xpoints[x + 1] - xpoints[x];
|
|
if (xap > 1)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
for (i = 0; i < xap; i++)
|
|
{
|
|
r += R_VAL(pix + i);
|
|
g += G_VAL(pix + i);
|
|
b += B_VAL(pix + i);
|
|
a += A_VAL(pix + i);
|
|
}
|
|
r /= xap;
|
|
g /= xap;
|
|
b /= xap;
|
|
a /= xap;
|
|
*dptr++ = PIXEL_ARGB(a, r, g, b);
|
|
}
|
|
else
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/* if we're scaling down horizontally & vertically */
|
|
else
|
|
#ifndef OLD_SCALE_DOWN
|
|
{
|
|
/*\ 'Correct' version, with math units prepared for MMXification:
|
|
* |*| The operation 'b = (b * c) >> 16' translates to pmulhw,
|
|
* |*| so the operation 'b = (b * c) >> d' would translate to
|
|
* |*| psllw (16 - d), %mmb; pmulh %mmc, %mmb
|
|
* \ */
|
|
int Cx, Cy, i, j;
|
|
uint32_t *pix;
|
|
int a, r, g, b, ax, rx, gx, bx;
|
|
int xap, yap;
|
|
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
Cy = YAP >> 16;
|
|
yap = YAP & 0xffff;
|
|
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
Cx = XAP >> 16;
|
|
xap = XAP & 0xffff;
|
|
|
|
sptr = ypoints[dyy + y] + xpoints[x];
|
|
pix = sptr;
|
|
sptr += sow;
|
|
rx = (R_VAL(pix) * xap) >> 9;
|
|
gx = (G_VAL(pix) * xap) >> 9;
|
|
bx = (B_VAL(pix) * xap) >> 9;
|
|
ax = (A_VAL(pix) * xap) >> 9;
|
|
pix++;
|
|
for (i = (1 << 14) - xap; i > Cx; i -= Cx)
|
|
{
|
|
rx += (R_VAL(pix) * Cx) >> 9;
|
|
gx += (G_VAL(pix) * Cx) >> 9;
|
|
bx += (B_VAL(pix) * Cx) >> 9;
|
|
ax += (A_VAL(pix) * Cx) >> 9;
|
|
pix++;
|
|
}
|
|
if (i > 0)
|
|
{
|
|
rx += (R_VAL(pix) * i) >> 9;
|
|
gx += (G_VAL(pix) * i) >> 9;
|
|
bx += (B_VAL(pix) * i) >> 9;
|
|
ax += (A_VAL(pix) * i) >> 9;
|
|
}
|
|
|
|
r = (rx * yap) >> 14;
|
|
g = (gx * yap) >> 14;
|
|
b = (bx * yap) >> 14;
|
|
a = (ax * yap) >> 14;
|
|
|
|
for (j = (1 << 14) - yap; j > Cy; j -= Cy)
|
|
{
|
|
pix = sptr;
|
|
sptr += sow;
|
|
rx = (R_VAL(pix) * xap) >> 9;
|
|
gx = (G_VAL(pix) * xap) >> 9;
|
|
bx = (B_VAL(pix) * xap) >> 9;
|
|
ax = (A_VAL(pix) * xap) >> 9;
|
|
pix++;
|
|
for (i = (1 << 14) - xap; i > Cx; i -= Cx)
|
|
{
|
|
rx += (R_VAL(pix) * Cx) >> 9;
|
|
gx += (G_VAL(pix) * Cx) >> 9;
|
|
bx += (B_VAL(pix) * Cx) >> 9;
|
|
ax += (A_VAL(pix) * Cx) >> 9;
|
|
pix++;
|
|
}
|
|
if (i > 0)
|
|
{
|
|
rx += (R_VAL(pix) * i) >> 9;
|
|
gx += (G_VAL(pix) * i) >> 9;
|
|
bx += (B_VAL(pix) * i) >> 9;
|
|
ax += (A_VAL(pix) * i) >> 9;
|
|
}
|
|
|
|
r += (rx * Cy) >> 14;
|
|
g += (gx * Cy) >> 14;
|
|
b += (bx * Cy) >> 14;
|
|
a += (ax * Cy) >> 14;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
pix = sptr;
|
|
rx = (R_VAL(pix) * xap) >> 9;
|
|
gx = (G_VAL(pix) * xap) >> 9;
|
|
bx = (B_VAL(pix) * xap) >> 9;
|
|
ax = (A_VAL(pix) * xap) >> 9;
|
|
pix++;
|
|
for (i = (1 << 14) - xap; i > Cx; i -= Cx)
|
|
{
|
|
rx += (R_VAL(pix) * Cx) >> 9;
|
|
gx += (G_VAL(pix) * Cx) >> 9;
|
|
bx += (B_VAL(pix) * Cx) >> 9;
|
|
ax += (A_VAL(pix) * Cx) >> 9;
|
|
pix++;
|
|
}
|
|
if (i > 0)
|
|
{
|
|
rx += (R_VAL(pix) * i) >> 9;
|
|
gx += (G_VAL(pix) * i) >> 9;
|
|
bx += (B_VAL(pix) * i) >> 9;
|
|
ax += (A_VAL(pix) * i) >> 9;
|
|
}
|
|
|
|
r += (rx * j) >> 14;
|
|
g += (gx * j) >> 14;
|
|
b += (bx * j) >> 14;
|
|
a += (ax * j) >> 14;
|
|
}
|
|
|
|
R_VAL(dptr) = r >> 5;
|
|
G_VAL(dptr) = g >> 5;
|
|
B_VAL(dptr) = b >> 5;
|
|
A_VAL(dptr) = a >> 5;
|
|
dptr++;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
int count;
|
|
uint32_t *pix;
|
|
int a, r, g, b;
|
|
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
int yap =
|
|
(ypoints[dyy + y + 1] - ypoints[dyy + y]) / sow;
|
|
/* calculate the source line we'll scan from */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
sptr = ypoints[dyy + y];
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int xap = xpoints[x + 1] - xpoints[x];
|
|
|
|
if ((xap > 1) || (yap > 1))
|
|
{
|
|
r = 0;
|
|
g = 0;
|
|
b = 0;
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
for (j = yap; --j >= 0;)
|
|
{
|
|
for (i = xap; --i >= 0;)
|
|
{
|
|
r += R_VAL(pix + i);
|
|
g += G_VAL(pix + i);
|
|
b += B_VAL(pix + i);
|
|
a += A_VAL(pix + i);
|
|
}
|
|
pix += sow;
|
|
}
|
|
count = xap * yap;
|
|
R_VAL(dptr) = r / count;
|
|
G_VAL(dptr) = g / count;
|
|
B_VAL(dptr) = b / count;
|
|
A_VAL(dptr) = a / count;
|
|
dptr++;
|
|
}
|
|
else
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* scale by area sampling - IGNORE the ALPHA byte*/
|
|
void
|
|
__imlib_ScaleAARGB(ImlibScaleInfo * isi, uint32_t * dest, int dxx, int dyy,
|
|
int dx, int dy, int dw, int dh, int dow, int sow)
|
|
{
|
|
uint32_t *sptr, *dptr;
|
|
int x, y, end;
|
|
uint32_t **ypoints;
|
|
int *xpoints;
|
|
int *xapoints;
|
|
int *yapoints;
|
|
|
|
#ifdef DO_MMX_ASM
|
|
if (__imlib_do_asm())
|
|
{
|
|
__imlib_Scale_mmx_AARGBA(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
ypoints = isi->ypoints;
|
|
xpoints = isi->xpoints;
|
|
xapoints = isi->xapoints;
|
|
yapoints = isi->yapoints;
|
|
|
|
end = dxx + dw;
|
|
/* scaling up both ways */
|
|
if (isi->xup_yup == 3)
|
|
{
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
/* calculate the source line we'll scan from */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
sptr = ypoints[dyy + y];
|
|
if (YAP > 0)
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0;
|
|
int rr = 0, gg = 0, bb = 0;
|
|
uint32_t *pix;
|
|
|
|
if (XAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_XAP;
|
|
g = G_VAL(pix) * INV_XAP;
|
|
b = B_VAL(pix) * INV_XAP;
|
|
pix++;
|
|
r += R_VAL(pix) * XAP;
|
|
g += G_VAL(pix) * XAP;
|
|
b += B_VAL(pix) * XAP;
|
|
pix += sow;
|
|
rr = R_VAL(pix) * XAP;
|
|
gg = G_VAL(pix) * XAP;
|
|
bb = B_VAL(pix) * XAP;
|
|
pix--;
|
|
rr += R_VAL(pix) * INV_XAP;
|
|
gg += G_VAL(pix) * INV_XAP;
|
|
bb += B_VAL(pix) * INV_XAP;
|
|
r = ((rr * YAP) + (r * INV_YAP)) >> 16;
|
|
g = ((gg * YAP) + (g * INV_YAP)) >> 16;
|
|
b = ((bb * YAP) + (b * INV_YAP)) >> 16;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
else
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_YAP;
|
|
g = G_VAL(pix) * INV_YAP;
|
|
b = B_VAL(pix) * INV_YAP;
|
|
pix += sow;
|
|
r += R_VAL(pix) * YAP;
|
|
g += G_VAL(pix) * YAP;
|
|
b += B_VAL(pix) * YAP;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0;
|
|
uint32_t *pix;
|
|
|
|
if (XAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_XAP;
|
|
g = G_VAL(pix) * INV_XAP;
|
|
b = B_VAL(pix) * INV_XAP;
|
|
pix++;
|
|
r += R_VAL(pix) * XAP;
|
|
g += G_VAL(pix) * XAP;
|
|
b += B_VAL(pix) * XAP;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
else
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* if we're scaling down vertically */
|
|
else if (isi->xup_yup == 1)
|
|
#ifndef OLD_SCALE_DOWN
|
|
{
|
|
/*\ 'Correct' version, with math units prepared for MMXification \ */
|
|
int Cy, j;
|
|
uint32_t *pix;
|
|
int r, g, b, rr, gg, bb;
|
|
int yap;
|
|
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
Cy = YAP >> 16;
|
|
yap = YAP & 0xffff;
|
|
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = (R_VAL(pix) * yap) >> 10;
|
|
g = (G_VAL(pix) * yap) >> 10;
|
|
b = (B_VAL(pix) * yap) >> 10;
|
|
pix += sow;
|
|
for (j = (1 << 14) - yap; j > Cy; j -= Cy)
|
|
{
|
|
r += (R_VAL(pix) * Cy) >> 10;
|
|
g += (G_VAL(pix) * Cy) >> 10;
|
|
b += (B_VAL(pix) * Cy) >> 10;
|
|
pix += sow;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
r += (R_VAL(pix) * j) >> 10;
|
|
g += (G_VAL(pix) * j) >> 10;
|
|
b += (B_VAL(pix) * j) >> 10;
|
|
}
|
|
if (XAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x] + 1;
|
|
rr = (R_VAL(pix) * yap) >> 10;
|
|
gg = (G_VAL(pix) * yap) >> 10;
|
|
bb = (B_VAL(pix) * yap) >> 10;
|
|
pix += sow;
|
|
for (j = (1 << 14) - yap; j > Cy; j -= Cy)
|
|
{
|
|
rr += (R_VAL(pix) * Cy) >> 10;
|
|
gg += (G_VAL(pix) * Cy) >> 10;
|
|
bb += (B_VAL(pix) * Cy) >> 10;
|
|
pix += sow;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
rr += (R_VAL(pix) * j) >> 10;
|
|
gg += (G_VAL(pix) * j) >> 10;
|
|
bb += (B_VAL(pix) * j) >> 10;
|
|
}
|
|
r = r * INV_XAP;
|
|
g = g * INV_XAP;
|
|
b = b * INV_XAP;
|
|
r = (r + ((rr * XAP))) >> 12;
|
|
g = (g + ((gg * XAP))) >> 12;
|
|
b = (b + ((bb * XAP))) >> 12;
|
|
}
|
|
else
|
|
{
|
|
r >>= 4;
|
|
g >>= 4;
|
|
b >>= 4;
|
|
}
|
|
*dptr = PIXEL_ARGB(0xff, r, g, b);
|
|
dptr++;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
int yap;
|
|
|
|
/* calculate the source line we'll scan from */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
sptr = ypoints[dyy + y];
|
|
|
|
yap = (ypoints[dyy + y + 1] - ypoints[dyy + y]) / sow;
|
|
if (yap > 1)
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0;
|
|
int rr = 0, gg = 0, bb = 0;
|
|
uint32_t *pix;
|
|
|
|
if (XAP > 0)
|
|
{
|
|
pix = sptr + xpoints[x];
|
|
for (j = 0; j < yap; j++)
|
|
{
|
|
r += R_VAL(pix);
|
|
g += G_VAL(pix);
|
|
b += B_VAL(pix);
|
|
rr += R_VAL(pix + 1);
|
|
gg += G_VAL(pix + 1);
|
|
bb += B_VAL(pix + 1);
|
|
pix += sow;
|
|
}
|
|
r = r * INV_XAP / yap;
|
|
g = g * INV_XAP / yap;
|
|
b = b * INV_XAP / yap;
|
|
r = (r + ((rr * XAP) / yap)) >> 8;
|
|
g = (g + ((gg * XAP) / yap)) >> 8;
|
|
b = (b + ((bb * XAP) / yap)) >> 8;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
else
|
|
{
|
|
pix = sptr + xpoints[x];
|
|
for (j = 0; j < yap; j++)
|
|
{
|
|
r += R_VAL(pix);
|
|
g += G_VAL(pix);
|
|
b += B_VAL(pix);
|
|
pix += sow;
|
|
}
|
|
r /= yap;
|
|
g /= yap;
|
|
b /= yap;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0;
|
|
uint32_t *pix;
|
|
|
|
if (XAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_XAP;
|
|
g = G_VAL(pix) * INV_XAP;
|
|
b = B_VAL(pix) * INV_XAP;
|
|
pix++;
|
|
r += R_VAL(pix) * XAP;
|
|
g += G_VAL(pix) * XAP;
|
|
b += B_VAL(pix) * XAP;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
else
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/* if we're scaling down horizontally */
|
|
else if (isi->xup_yup == 2)
|
|
#ifndef OLD_SCALE_DOWN
|
|
{
|
|
/*\ 'Correct' version, with math units prepared for MMXification \ */
|
|
int Cx, j;
|
|
uint32_t *pix;
|
|
int r, g, b, rr, gg, bb;
|
|
int xap;
|
|
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
Cx = XAP >> 16;
|
|
xap = XAP & 0xffff;
|
|
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = (R_VAL(pix) * xap) >> 10;
|
|
g = (G_VAL(pix) * xap) >> 10;
|
|
b = (B_VAL(pix) * xap) >> 10;
|
|
pix++;
|
|
for (j = (1 << 14) - xap; j > Cx; j -= Cx)
|
|
{
|
|
r += (R_VAL(pix) * Cx) >> 10;
|
|
g += (G_VAL(pix) * Cx) >> 10;
|
|
b += (B_VAL(pix) * Cx) >> 10;
|
|
pix++;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
r += (R_VAL(pix) * j) >> 10;
|
|
g += (G_VAL(pix) * j) >> 10;
|
|
b += (B_VAL(pix) * j) >> 10;
|
|
}
|
|
if (YAP > 0)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x] + sow;
|
|
rr = (R_VAL(pix) * xap) >> 10;
|
|
gg = (G_VAL(pix) * xap) >> 10;
|
|
bb = (B_VAL(pix) * xap) >> 10;
|
|
pix++;
|
|
for (j = (1 << 14) - xap; j > Cx; j -= Cx)
|
|
{
|
|
rr += (R_VAL(pix) * Cx) >> 10;
|
|
gg += (G_VAL(pix) * Cx) >> 10;
|
|
bb += (B_VAL(pix) * Cx) >> 10;
|
|
pix++;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
rr += (R_VAL(pix) * j) >> 10;
|
|
gg += (G_VAL(pix) * j) >> 10;
|
|
bb += (B_VAL(pix) * j) >> 10;
|
|
}
|
|
r = r * INV_YAP;
|
|
g = g * INV_YAP;
|
|
b = b * INV_YAP;
|
|
r = (r + ((rr * YAP))) >> 12;
|
|
g = (g + ((gg * YAP))) >> 12;
|
|
b = (b + ((bb * YAP))) >> 12;
|
|
}
|
|
else
|
|
{
|
|
r >>= 4;
|
|
g >>= 4;
|
|
b >>= 4;
|
|
}
|
|
*dptr = PIXEL_ARGB(0xff, r, g, b);
|
|
dptr++;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
/* calculate the source line we'll scan from */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
sptr = ypoints[dyy + y];
|
|
if (YAP > 0)
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0;
|
|
int rr = 0, gg = 0, bb = 0;
|
|
int xap;
|
|
uint32_t *pix;
|
|
|
|
xap = xpoints[x + 1] - xpoints[x];
|
|
if (xap > 1)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
for (i = 0; i < xap; i++)
|
|
{
|
|
r += R_VAL(pix + i);
|
|
g += G_VAL(pix + i);
|
|
b += B_VAL(pix + i);
|
|
}
|
|
r = r * INV_YAP / xap;
|
|
g = g * INV_YAP / xap;
|
|
b = b * INV_YAP / xap;
|
|
pix = ypoints[dyy + y] + xpoints[x] + sow;
|
|
for (i = 0; i < xap; i++)
|
|
{
|
|
rr += R_VAL(pix + i);
|
|
gg += G_VAL(pix + i);
|
|
bb += B_VAL(pix + i);
|
|
}
|
|
r = (r + ((rr * YAP) / xap)) >> 8;
|
|
g = (g + ((gg * YAP) / xap)) >> 8;
|
|
b = (b + ((bb * YAP) / xap)) >> 8;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
else
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
r = R_VAL(pix) * INV_YAP;
|
|
g = G_VAL(pix) * INV_YAP;
|
|
b = B_VAL(pix) * INV_YAP;
|
|
pix += sow;
|
|
r += R_VAL(pix) * YAP;
|
|
g += G_VAL(pix) * YAP;
|
|
b += B_VAL(pix) * YAP;
|
|
r >>= 8;
|
|
g >>= 8;
|
|
b >>= 8;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int r = 0, g = 0, b = 0;
|
|
int xap;
|
|
uint32_t *pix;
|
|
|
|
xap = xpoints[x + 1] - xpoints[x];
|
|
if (xap > 1)
|
|
{
|
|
pix = ypoints[dyy + y] + xpoints[x];
|
|
for (i = 0; i < xap; i++)
|
|
{
|
|
r += R_VAL(pix + i);
|
|
g += G_VAL(pix + i);
|
|
b += B_VAL(pix + i);
|
|
}
|
|
r /= xap;
|
|
g /= xap;
|
|
b /= xap;
|
|
*dptr++ = PIXEL_ARGB(0xff, r, g, b);
|
|
}
|
|
else
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/* fully optimized (i think) - only change of algorithm can help */
|
|
/* if we're scaling down horizontally & vertically */
|
|
else
|
|
#ifndef OLD_SCALE_DOWN
|
|
{
|
|
/*\ 'Correct' version, with math units prepared for MMXification \ */
|
|
int Cx, Cy, i, j;
|
|
uint32_t *pix;
|
|
int r, g, b, rx, gx, bx;
|
|
int xap, yap;
|
|
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
Cy = YAP >> 16;
|
|
yap = YAP & 0xffff;
|
|
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
Cx = XAP >> 16;
|
|
xap = XAP & 0xffff;
|
|
|
|
sptr = ypoints[dyy + y] + xpoints[x];
|
|
pix = sptr;
|
|
sptr += sow;
|
|
rx = (R_VAL(pix) * xap) >> 9;
|
|
gx = (G_VAL(pix) * xap) >> 9;
|
|
bx = (B_VAL(pix) * xap) >> 9;
|
|
pix++;
|
|
for (i = (1 << 14) - xap; i > Cx; i -= Cx)
|
|
{
|
|
rx += (R_VAL(pix) * Cx) >> 9;
|
|
gx += (G_VAL(pix) * Cx) >> 9;
|
|
bx += (B_VAL(pix) * Cx) >> 9;
|
|
pix++;
|
|
}
|
|
if (i > 0)
|
|
{
|
|
rx += (R_VAL(pix) * i) >> 9;
|
|
gx += (G_VAL(pix) * i) >> 9;
|
|
bx += (B_VAL(pix) * i) >> 9;
|
|
}
|
|
|
|
r = (rx * yap) >> 14;
|
|
g = (gx * yap) >> 14;
|
|
b = (bx * yap) >> 14;
|
|
|
|
for (j = (1 << 14) - yap; j > Cy; j -= Cy)
|
|
{
|
|
pix = sptr;
|
|
sptr += sow;
|
|
rx = (R_VAL(pix) * xap) >> 9;
|
|
gx = (G_VAL(pix) * xap) >> 9;
|
|
bx = (B_VAL(pix) * xap) >> 9;
|
|
pix++;
|
|
for (i = (1 << 14) - xap; i > Cx; i -= Cx)
|
|
{
|
|
rx += (R_VAL(pix) * Cx) >> 9;
|
|
gx += (G_VAL(pix) * Cx) >> 9;
|
|
bx += (B_VAL(pix) * Cx) >> 9;
|
|
pix++;
|
|
}
|
|
if (i > 0)
|
|
{
|
|
rx += (R_VAL(pix) * i) >> 9;
|
|
gx += (G_VAL(pix) * i) >> 9;
|
|
bx += (B_VAL(pix) * i) >> 9;
|
|
}
|
|
|
|
r += (rx * Cy) >> 14;
|
|
g += (gx * Cy) >> 14;
|
|
b += (bx * Cy) >> 14;
|
|
}
|
|
if (j > 0)
|
|
{
|
|
pix = sptr;
|
|
rx = (R_VAL(pix) * xap) >> 9;
|
|
gx = (G_VAL(pix) * xap) >> 9;
|
|
bx = (B_VAL(pix) * xap) >> 9;
|
|
pix++;
|
|
for (i = (1 << 14) - xap; i > Cx; i -= Cx)
|
|
{
|
|
rx += (R_VAL(pix) * Cx) >> 9;
|
|
gx += (G_VAL(pix) * Cx) >> 9;
|
|
bx += (B_VAL(pix) * Cx) >> 9;
|
|
pix++;
|
|
}
|
|
if (i > 0)
|
|
{
|
|
rx += (R_VAL(pix) * i) >> 9;
|
|
gx += (G_VAL(pix) * i) >> 9;
|
|
bx += (B_VAL(pix) * i) >> 9;
|
|
}
|
|
|
|
r += (rx * j) >> 14;
|
|
g += (gx * j) >> 14;
|
|
b += (bx * j) >> 14;
|
|
}
|
|
|
|
R_VAL(dptr) = r >> 5;
|
|
G_VAL(dptr) = g >> 5;
|
|
B_VAL(dptr) = b >> 5;
|
|
dptr++;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
int count;
|
|
uint32_t *pix;
|
|
int r, g, b;
|
|
|
|
/* go through every scanline in the output buffer */
|
|
for (y = 0; y < dh; y++)
|
|
{
|
|
int yap =
|
|
(ypoints[dyy + y + 1] - ypoints[dyy + y]) / sow;
|
|
/* calculate the source line we'll scan from */
|
|
dptr = dest + dx + ((y + dy) * dow);
|
|
sptr = ypoints[dyy + y];
|
|
for (x = dxx; x < end; x++)
|
|
{
|
|
int xap = xpoints[x + 1] - xpoints[x];
|
|
|
|
if ((xap > 1) || (yap > 1))
|
|
{
|
|
r = 0;
|
|
g = 0;
|
|
b = 0;
|
|
pix = sptr + xpoints[x];
|
|
for (j = yap; --j >= 0;)
|
|
{
|
|
for (i = xap; --i >= 0;)
|
|
{
|
|
r += R_VAL(pix + i);
|
|
g += G_VAL(pix + i);
|
|
b += B_VAL(pix + i);
|
|
}
|
|
pix += sow;
|
|
}
|
|
count = xap * yap;
|
|
R_VAL(dptr) = r / count;
|
|
G_VAL(dptr) = g / count;
|
|
B_VAL(dptr) = b / count;
|
|
dptr++;
|
|
}
|
|
else
|
|
*dptr++ = sptr[xpoints[x]];
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|