summaryrefslogtreecommitdiffstats
path: root/src/libs/dimg/dimgscale.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dimg/dimgscale.cpp')
-rw-r--r--src/libs/dimg/dimgscale.cpp2127
1 files changed, 2127 insertions, 0 deletions
diff --git a/src/libs/dimg/dimgscale.cpp b/src/libs/dimg/dimgscale.cpp
new file mode 100644
index 00000000..850e36de
--- /dev/null
+++ b/src/libs/dimg/dimgscale.cpp
@@ -0,0 +1,2127 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-06-14
+ * Description : This is the normal smoothscale method,
+ * based on Imlib2's smoothscale. Added
+ * smoothScaleSection - Scaling only of a
+ * section of a image. Added 16bit image support
+ *
+ * Copyright (C) 2005 by Renchi Raju <[email protected]>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Ported to C++/TQImage by Daniel M. Duley
+ * Following modification are (C) Daniel M. Duley
+ * Changes include formatting, namespaces and other C++'ings, removal of old
+ * #ifdef'ed code, and removal of unneeded border calculation code.
+ *
+ * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
+ * is by Willem Monsuwe <[email protected]>.
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C ansi includes.
+
+extern "C"
+{
+#include <stdint.h>
+}
+
+// C++ includes.
+
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+
+// Local includes.
+
+#include "dimgprivate.h"
+#include "dimg.h"
+
+typedef uint64_t ullong;
+typedef int64_t llong;
+
+namespace Digikam
+{
+
+namespace DImgScale
+{
+ typedef struct __dimg_scale_info
+ {
+ int *xpoints;
+ uint **ypoints;
+ ullong **ypoints16;
+ int *xapoints;
+ int *yapoints;
+ int xup_yup;
+ } DImgScaleInfo;
+
+ uint** dimgCalcYPoints(uint *src, int sw, int sh, int dh);
+ ullong** dimgCalcYPoints16(ullong *src, int sw, int sh, int dh);
+ int* dimgCalcXPoints(int sw, int dw);
+ int* dimgCalcApoints(int s, int d, int up);
+
+ DImgScaleInfo* dimgFreeScaleInfo(DImgScaleInfo *isi);
+ DImgScaleInfo *dimgCalcScaleInfo(const DImg &img,
+ int sw, int sh,
+ int dw, int dh,
+ bool sixteenBit,
+ bool aa);
+
+ void dimgSampleRGBA(DImgScaleInfo *isi, unsigned int *dest, int dxx,
+ int dyy, int dx, int dy, int dw, int dh, int dow);
+ void dimgScaleAARGBA(DImgScaleInfo *isi, unsigned int *dest, int dxx,
+ int dyy, int dx, int dy, int dw, int dh, int dow,
+ int sow);
+ void dimgScaleAARGB(DImgScaleInfo *isi, unsigned int *dest, int dxx,
+ int dyy, int dx, int dy, int dw, int dh, int dow, int
+ sow);
+
+ void dimgScaleAARGBA16(DImgScaleInfo *isi, ullong *dest,
+ int dxx, int dyy, int dw, int dh,
+ int dow, int sow);
+ void dimgScaleAARGB16(DImgScaleInfo *isi, ullong *dest,
+ int dxx, int dyy, int dw, int dh,
+ int dow, int sow);
+};
+
+using namespace DImgScale;
+
+DImg DImg::smoothScale(int dw, int dh, TQSize::ScaleMode scaleMode)
+{
+ if (dw < 0 || dh < 0 || isNull())
+ return DImg();
+
+ uint w = width();
+ uint h = height();
+
+ if (w <= 0 || h <= 0)
+ return DImg();
+
+ TQSize newSize(w, h);
+ newSize.scale( TQSize(dw, dh), scaleMode );
+ if (!newSize.isValid())
+ return DImg();
+
+ dw = newSize.width();
+ dh = newSize.height();
+
+ // do we actually need to scale?
+ if ((w == (uint)dw) && (h == (uint)dh))
+ {
+ return copy();
+ }
+
+ DImgScale::DImgScaleInfo *scaleinfo = dimgCalcScaleInfo(*this, w, h, dw, dh, sixteenBit(), true);
+ if (!scaleinfo)
+ return *this;
+
+ DImg buffer(*this, dw, dh);
+
+ if (sixteenBit())
+ {
+ if (hasAlpha())
+ {
+ dimgScaleAARGBA16(scaleinfo, (ullong*) buffer.bits(),
+ 0, 0, dw, dh, dw, w);
+ }
+ else
+ {
+ dimgScaleAARGB16(scaleinfo, (ullong*) buffer.bits(),
+ 0, 0, dw, dh, dw, w);
+ }
+ }
+ else
+ {
+ if (hasAlpha())
+ {
+ dimgScaleAARGBA(scaleinfo, (unsigned int *)buffer.bits(),
+ 0, 0, 0, 0, dw, dh, dw, w);
+ }
+ else
+ {
+ dimgScaleAARGB(scaleinfo, (unsigned int *)buffer.bits(),
+ 0, 0, 0, 0, dw, dh, dw, w);
+ }
+ }
+
+ dimgFreeScaleInfo(scaleinfo);
+
+ return buffer;
+}
+
+#define CLIP(x, y, w, h, xx, yy, ww, hh) \
+if (x < (xx)) {w += (x - (xx)); x = (xx);} \
+if (y < (yy)) {h += (y - (yy)); y = (yy);} \
+if ((x + w) > ((xx) + (ww))) {w = (ww) - (x - xx);} \
+if ((y + h) > ((yy) + (hh))) {h = (hh) - (y - yy);}
+
+DImg DImg::smoothScaleSection(int sx, int sy,
+ int sw, int sh,
+ int dw, int dh)
+{
+ uint w = width();
+ uint h = height();
+
+ // sanity checks
+ if ((dw <= 0) || (dh <= 0))
+ return DImg();
+
+ if ((sw <= 0) || (sh <= 0))
+ return DImg();
+
+ // clip the source rect to be within the actual image
+ int psx, psy, psw, psh;
+ psx = sx;
+ psy = sy;
+ psw = sw;
+ psh = sh;
+ CLIP(sx, sy, sw, sh, 0, 0, (int)w, (int)h);
+
+ // clip output coords to clipped input coords
+ if (psw != sw)
+ dw = (dw * sw) / psw;
+ if (psh != sh)
+ dh = (dh * sh) / psh;
+
+ // do a second check to see if we now have invalid coords
+ // do not do anything if we have a 0 widht or height image to render
+ if ((dw <= 0) || (dh <= 0))
+ return DImg();
+
+ // if the input rect size < 0 do not render either
+ if ((sw <= 0) || (sh <= 0))
+ return DImg();
+
+ // do we actually need to scale?
+ if ((sw == dw) && (sh == dh))
+ {
+ return copy(sx, sy, sw, sh);
+ }
+
+ // calculate scaleinfo
+ DImgScaleInfo *scaleinfo = dimgCalcScaleInfo(*this, sw, sh, dw, dh, sixteenBit(), true);
+ if (!scaleinfo)
+ return DImg();
+
+ DImg buffer(*this, dw, dh);
+
+ if (sixteenBit())
+ {
+ if (hasAlpha())
+ {
+ dimgScaleAARGBA16(scaleinfo, (ullong*) buffer.bits(),
+ ((sx * dw) / sw),
+ ((sy * dh) / sh),
+ dw, dh,
+ dw, w);
+ }
+ else
+ {
+ dimgScaleAARGB16(scaleinfo, (ullong*) buffer.bits(),
+ ((sx * dw) / sw),
+ ((sy * dh) / sh),
+ dw, dh,
+ dw, w);
+ }
+ }
+ else
+ {
+ if (hasAlpha())
+ {
+ dimgScaleAARGBA(scaleinfo,
+ (uint *)buffer.bits(),
+ ((sx * dw) / sw),
+ ((sy * dh) / sh),
+ 0, 0,
+ dw, dh,
+ dw, w);
+ }
+ else
+ {
+ dimgScaleAARGB(scaleinfo,
+ (uint *)buffer.bits(),
+ ((sx * dw) / sw),
+ ((sy * dh) / sh),
+ 0, 0,
+ dw, dh,
+ dw, w);
+ }
+ }
+
+ dimgFreeScaleInfo(scaleinfo);
+
+ return buffer;
+}
+
+
+//
+// Code ported from Imlib2...
+//
+
+// FIXME: replace with mRed, etc... These work on pointers to pixels, not
+// pixel values
+#define A_VAL(p) ((unsigned char *)(p))[3]
+#define R_VAL(p) ((unsigned char *)(p))[2]
+#define G_VAL(p) ((unsigned char *)(p))[1]
+#define B_VAL(p) ((unsigned char *)(p))[0]
+
+#define INV_XAP (256 - xapoints[x])
+#define XAP (xapoints[x])
+#define INV_YAP (256 - yapoints[dyy + y])
+#define YAP (yapoints[dyy + y])
+
+unsigned int** DImgScale::dimgCalcYPoints(unsigned int *src, int sw, int sh, int dh)
+{
+ unsigned int **p;
+ int i, j = 0;
+ int val, inc;
+
+ p = new unsigned int* [dh+1];
+
+ val = 0;
+ inc = (sh << 16) / dh;
+ for(i = 0; i < dh; i++)
+ {
+ p[j++] = src + ((val >> 16) * sw);
+ val += inc;
+ }
+
+ return(p);
+}
+
+ullong** DImgScale::dimgCalcYPoints16(ullong* src, int sw, int sh, int dh)
+{
+ ullong** p;
+ int i, j = 0;
+ int val, inc;
+
+ p = new ullong*[(dh+1)];
+
+ val = 0;
+ inc = (sh << 16) / dh;
+ for(i = 0; i < dh; i++)
+ {
+ p[j++] = src + ((val >> 16) * sw);
+ val += inc;
+ }
+
+ return p;
+}
+
+int* DImgScale::dimgCalcXPoints(int sw, int dw)
+{
+ int *p, i, j = 0;
+ int val, inc;
+
+ p = new int[dw+1];
+
+ val = 0;
+ inc = (sw << 16) / dw;
+ for(i = 0; i < dw; i++)
+ {
+ p[j++] = (val >> 16);
+ val += inc;
+ }
+
+ return(p);
+}
+
+int* DImgScale::dimgCalcApoints(int s, int d, int up)
+{
+ int *p, i, j = 0;
+
+ p = new int[d];
+
+ /* scaling up */
+ if(up)
+ {
+ int val, inc;
+
+ val = 0;
+ inc = (s << 16) / d;
+ for(i = 0; i < d; i++)
+ {
+ p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
+ if((val >> 16) >= (s - 1))
+ p[j - 1] = 0;
+ val += inc;
+ }
+ }
+ /* scaling down */
+ else
+ {
+ int val, inc, ap, Cp;
+ val = 0;
+ inc = (s << 16) / d;
+ Cp = ((d << 14) / s) + 1;
+
+ for(i = 0; i < d; i++)
+ {
+ ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
+ p[j] = ap | (Cp << 16);
+ j++;
+ val += inc;
+ }
+ }
+
+ return(p);
+}
+
+DImgScaleInfo* DImgScale::dimgCalcScaleInfo(const DImg &img,
+ int sw, int sh,
+ int dw, int dh,
+ bool /*sixteenBit*/,
+ bool aa)
+{
+ DImgScaleInfo *isi;
+ int scw, sch;
+
+ scw = dw * img.width() / sw;
+ sch = dh * img.height() / sh;
+
+ isi = new DImgScaleInfo;
+ if(!isi)
+ return(NULL);
+
+ memset(isi, 0, sizeof(DImgScaleInfo));
+
+ isi->xup_yup = (abs(dw) >= sw) + ((abs(dh) >= sh) << 1);
+
+ isi->xpoints = dimgCalcXPoints(img.width(), scw);
+ if(!isi->xpoints)
+ return(dimgFreeScaleInfo(isi));
+
+ if (img.sixteenBit())
+ {
+ isi->ypoints = 0;
+ isi->ypoints16 = dimgCalcYPoints16((ullong*)img.bits(), img.width(), img.height(), sch);
+ if (!isi->ypoints16) return(dimgFreeScaleInfo(isi));
+ }
+ else
+ {
+ isi->ypoints16 = 0;
+ isi->ypoints = dimgCalcYPoints((uint*)img.bits(), img.width(), img.height(), sch);
+ if (!isi->ypoints) return(dimgFreeScaleInfo(isi));
+ }
+
+ if (aa)
+ {
+ isi->xapoints = dimgCalcApoints(img.width(), scw, isi->xup_yup & 1);
+ if(!isi->xapoints) return(dimgFreeScaleInfo(isi));
+
+ isi->yapoints = dimgCalcApoints(img.height(), sch, isi->xup_yup & 2);
+ if(!isi->yapoints) return(dimgFreeScaleInfo(isi));
+ }
+/* It doesn't work...
+ else
+ {
+ isi->xapoints = new int[scw];
+ if(!isi->xapoints) return(dimgFreeScaleInfo(isi));
+ for(int i = 0; i < scw; i++) isi->xapoints[i] = 0;
+
+ isi->yapoints = new int[sch];
+ if(!isi->yapoints) return(dimgFreeScaleInfo(isi));
+ for(int i = 0; i < sch; i++) isi->yapoints[i] = 0;
+ }*/
+
+ return(isi);
+}
+
+DImgScaleInfo* DImgScale::dimgFreeScaleInfo(DImgScaleInfo *isi)
+{
+ if(isi)
+ {
+ delete [] isi->xpoints;
+ delete [] isi->ypoints;
+ delete [] isi->ypoints16;
+ delete [] isi->xapoints;
+ delete [] isi->yapoints;
+ delete isi;
+ }
+
+ return 0;
+}
+
+/** scale by pixel sampling only */
+void DImgScale::dimgSampleRGBA(DImgScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow)
+{
+ unsigned int *sptr, *dptr;
+ int x, y, end;
+ unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+
+ /* whats the last pixel ont he 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 DImgScale::dimgScaleAARGBA(DImgScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ unsigned int *sptr, *dptr;
+ int x, y, end;
+ unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *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;
+ unsigned int *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;
+
+ A_VAL(dptr) = a;
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+
+ dptr++;
+ }
+ 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;
+
+ A_VAL(dptr) = a;
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+
+ dptr++;
+ }
+ }
+ }
+ else
+ {
+ for(x = dxx; x < end; x++)
+ {
+ int r, g, b, a;
+ unsigned int *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;
+
+ A_VAL(dptr) = a;
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+
+ dptr++;
+ }
+ else
+ *dptr++ = sptr[xpoints[x] ];
+ }
+ }
+ }
+ }
+ /* if we're scaling down vertically */
+ else if(isi->xup_yup == 1)
+ {
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cy, j;
+ unsigned int *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;
+ }
+ 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;
+ }
+ 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;
+ }
+
+ A_VAL(dptr) = a;
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+
+ dptr++;
+ }
+ }
+ }
+ /* if we're scaling down horizontally */
+ else if(isi->xup_yup == 2)
+ {
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cx, j;
+ unsigned int *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;
+ }
+ 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;
+ }
+ 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;
+ }
+
+ A_VAL(dptr) = a;
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+
+ dptr++;
+ }
+ }
+ }
+ /* if we're scaling down horizontally & vertically */
+ else
+ {
+ /*\ '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;
+ unsigned int *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;
+ 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 * 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++;
+ }
+ }
+ }
+}
+
+/** scale by area sampling - IGNORE the ALPHA byte */
+void DImgScale::dimgScaleAARGB(DImgScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ unsigned int *sptr, *dptr;
+ int x, y, end;
+ unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *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;
+ unsigned int *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;
+
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+ A_VAL(dptr) = 0xFF;
+
+ dptr++;
+ }
+ 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;
+
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+ A_VAL(dptr) = 0xFF;
+
+ dptr++;
+ }
+ }
+ }
+ else
+ {
+ for(x = dxx; x < end; x++)
+ {
+ int r = 0, g = 0, b = 0;
+ unsigned int *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;
+
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+ A_VAL(dptr) = 0xFF;
+
+ dptr++;
+ }
+ else
+ *dptr++ = sptr[xpoints[x] ];
+ }
+ }
+ }
+ }
+ /* if we're scaling down vertically */
+ else if(isi->xup_yup == 1)
+ {
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cy, j;
+ unsigned int *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;
+ }
+
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+ A_VAL(dptr) = 0xFF;
+
+ dptr++;
+ }
+ }
+ }
+ /* if we're scaling down horizontally */
+ else if(isi->xup_yup == 2)
+ {
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cx, j;
+ unsigned int *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;
+ }
+
+ R_VAL(dptr) = r;
+ G_VAL(dptr) = g;
+ B_VAL(dptr) = b;
+ A_VAL(dptr) = 0xFF;
+
+ dptr++;
+ }
+ }
+ }
+ /* fully optimized (i think) - onyl change of algorithm can help */
+ /* if we're scaling down horizontally & vertically */
+ else
+ {
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cx, Cy, i, j;
+ unsigned int *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;
+ 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 * 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;
+ A_VAL(dptr) = 0xFF;
+ dptr++;
+ }
+ }
+ }
+}
+
+#define A_VAL16(p) ((ushort *)(p))[3]
+#define R_VAL16(p) ((ushort *)(p))[2]
+#define G_VAL16(p) ((ushort *)(p))[1]
+#define B_VAL16(p) ((ushort *)(p))[0]
+
+/** scale by area sampling - IGNORE the ALPHA byte*/
+void DImgScale::dimgScaleAARGB16(DImgScaleInfo *isi, ullong *dest,
+ int dxx, int dyy, int dw, int dh,
+ int dow, int sow)
+{
+ ullong *sptr, *dptr;
+ int x, y, end;
+ ullong **ypoints = isi->ypoints16;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *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 + (y * dow);
+ sptr = ypoints[dyy + y];
+ if(YAP > 0)
+ {
+ for(x = dxx; x < end; x++)
+ {
+ llong r = 0, g = 0, b = 0;
+ llong rr = 0, gg = 0, bb = 0;
+ ullong *pix;
+
+ if(XAP > 0)
+ {
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL16(pix) * INV_XAP;
+ g = G_VAL16(pix) * INV_XAP;
+ b = B_VAL16(pix) * INV_XAP;
+ pix++;
+ r += R_VAL16(pix) * XAP;
+ g += G_VAL16(pix) * XAP;
+ b += B_VAL16(pix) * XAP;
+ pix += sow;
+ rr = R_VAL16(pix) * XAP;
+ gg = G_VAL16(pix) * XAP;
+ bb = B_VAL16(pix) * XAP;
+ pix --;
+ rr += R_VAL16(pix) * INV_XAP;
+ gg += G_VAL16(pix) * INV_XAP;
+ bb += B_VAL16(pix) * INV_XAP;
+ r = ((rr * YAP) + (r * INV_YAP)) >> 16;
+ g = ((gg * YAP) + (g * INV_YAP)) >> 16;
+ b = ((bb * YAP) + (b * INV_YAP)) >> 16;
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = 0xFFFF;
+
+ dptr++;
+ }
+ else
+ {
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL16(pix) * INV_YAP;
+ g = G_VAL16(pix) * INV_YAP;
+ b = B_VAL16(pix) * INV_YAP;
+ pix += sow;
+ r += R_VAL16(pix) * YAP;
+ g += G_VAL16(pix) * YAP;
+ b += B_VAL16(pix) * YAP;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = 0xFFFF;
+
+ dptr++;
+ }
+ }
+ }
+ else
+ {
+ for(x = dxx; x < end; x++)
+ {
+ llong r = 0, g = 0, b = 0;
+ ullong *pix;
+
+ if(XAP > 0)
+ {
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL16(pix) * INV_XAP;
+ g = G_VAL16(pix) * INV_XAP;
+ b = B_VAL16(pix) * INV_XAP;
+ pix++;
+ r += R_VAL16(pix) * XAP;
+ g += G_VAL16(pix) * XAP;
+ b += B_VAL16(pix) * XAP;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = 0xFFFF;
+
+ dptr++;
+ }
+ else
+ *dptr++ = sptr[xpoints[x] ];
+ }
+ }
+ }
+ }
+ // if we're scaling down vertically
+ else if(isi->xup_yup == 1)
+ {
+ // 'Correct' version, with math units prepared for MMXification
+ int Cy, j;
+ ullong *pix;
+ llong 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 + y * dow;
+ for(x = dxx; x < end; x++)
+ {
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = (R_VAL16(pix) * yap) >> 10;
+ g = (G_VAL16(pix) * yap) >> 10;
+ b = (B_VAL16(pix) * yap) >> 10;
+ pix += sow;
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy)
+ {
+ r += (R_VAL16(pix) * Cy) >> 10;
+ g += (G_VAL16(pix) * Cy) >> 10;
+ b += (B_VAL16(pix) * Cy) >> 10;
+ pix += sow;
+ }
+ if(j > 0)
+ {
+ r += (R_VAL16(pix) * j) >> 10;
+ g += (G_VAL16(pix) * j) >> 10;
+ b += (B_VAL16(pix) * j) >> 10;
+ }
+ if(XAP > 0)
+ {
+ pix = ypoints[dyy + y] + xpoints[x] + 1;
+ rr = (R_VAL16(pix) * yap) >> 10;
+ gg = (G_VAL16(pix) * yap) >> 10;
+ bb = (B_VAL16(pix) * yap) >> 10;
+ pix += sow;
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy)
+ {
+ rr += (R_VAL16(pix) * Cy) >> 10;
+ gg += (G_VAL16(pix) * Cy) >> 10;
+ bb += (B_VAL16(pix) * Cy) >> 10;
+ pix += sow;
+ }
+ if(j > 0)
+ {
+ rr += (R_VAL16(pix) * j) >> 10;
+ gg += (G_VAL16(pix) * j) >> 10;
+ bb += (B_VAL16(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;
+ }
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = 0xFFFF;
+ dptr++;
+ }
+ }
+ }
+ // if we're scaling down horizontally
+ else if(isi->xup_yup == 2)
+ {
+ // 'Correct' version, with math units prepared for MMXification
+ int Cx, j;
+ ullong *pix;
+ llong r, g, b, rr, gg, bb;
+ int xap;
+
+ // go through every scanline in the output buffer
+ for(y = 0; y < dh; y++)
+ {
+ dptr = dest + y * dow;
+ for(x = dxx; x < end; x++)
+ {
+ Cx = XAP >> 16;
+ xap = XAP & 0xffff;
+
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = (R_VAL16(pix) * xap) >> 10;
+ g = (G_VAL16(pix) * xap) >> 10;
+ b = (B_VAL16(pix) * xap) >> 10;
+ pix++;
+ for(j = (1 << 14) - xap; j > Cx; j -= Cx)
+ {
+ r += (R_VAL16(pix) * Cx) >> 10;
+ g += (G_VAL16(pix) * Cx) >> 10;
+ b += (B_VAL16(pix) * Cx) >> 10;
+ pix++;
+ }
+ if(j > 0)
+ {
+ r += (R_VAL16(pix) * j) >> 10;
+ g += (G_VAL16(pix) * j) >> 10;
+ b += (B_VAL16(pix) * j) >> 10;
+ }
+ if(YAP > 0)
+ {
+ pix = ypoints[dyy + y] + xpoints[x] + sow;
+ rr = (R_VAL16(pix) * xap) >> 10;
+ gg = (G_VAL16(pix) * xap) >> 10;
+ bb = (B_VAL16(pix) * xap) >> 10;
+ pix++;
+ for(j = (1 << 14) - xap; j > Cx; j -= Cx)
+ {
+ rr += (R_VAL16(pix) * Cx) >> 10;
+ gg += (G_VAL16(pix) * Cx) >> 10;
+ bb += (B_VAL16(pix) * Cx) >> 10;
+ pix++;
+ }
+ if(j > 0)
+ {
+ rr += (R_VAL16(pix) * j) >> 10;
+ gg += (G_VAL16(pix) * j) >> 10;
+ bb += (B_VAL16(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;
+ }
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = 0xFFFF;
+ dptr++;
+ }
+ }
+ }
+ // fully optimized (i think) - onyl change of algorithm can help
+ // if we're scaling down horizontally & vertically
+ else
+ {
+ // 'Correct' version, with math units prepared for MMXification
+ int Cx, Cy, i, j;
+ ullong *pix;
+ llong r, g, b, rx, gx, bx;
+ int xap, yap;
+
+ for(y = 0; y < dh; y++)
+ {
+ Cy = YAP >> 16;
+ yap = YAP & 0xffff;
+ dptr = dest + y * 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_VAL16(pix) * xap) >> 9;
+ gx = (G_VAL16(pix) * xap) >> 9;
+ bx = (B_VAL16(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx)
+ {
+ rx += (R_VAL16(pix) * Cx) >> 9;
+ gx += (G_VAL16(pix) * Cx) >> 9;
+ bx += (B_VAL16(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0)
+ {
+ rx += (R_VAL16(pix) * i) >> 9;
+ gx += (G_VAL16(pix) * i) >> 9;
+ bx += (B_VAL16(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_VAL16(pix) * xap) >> 9;
+ gx = (G_VAL16(pix) * xap) >> 9;
+ bx = (B_VAL16(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx)
+ {
+ rx += (R_VAL16(pix) * Cx) >> 9;
+ gx += (G_VAL16(pix) * Cx) >> 9;
+ bx += (B_VAL16(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0)
+ {
+ rx += (R_VAL16(pix) * i) >> 9;
+ gx += (G_VAL16(pix) * i) >> 9;
+ bx += (B_VAL16(pix) * i) >> 9;
+ }
+
+ r += (rx * Cy) >> 14;
+ g += (gx * Cy) >> 14;
+ b += (bx * Cy) >> 14;
+ }
+ if(j > 0)
+ {
+ pix = sptr;
+ sptr += sow;
+ rx = (R_VAL16(pix) * xap) >> 9;
+ gx = (G_VAL16(pix) * xap) >> 9;
+ bx = (B_VAL16(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx)
+ {
+ rx += (R_VAL16(pix) * Cx) >> 9;
+ gx += (G_VAL16(pix) * Cx) >> 9;
+ bx += (B_VAL16(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0)
+ {
+ rx += (R_VAL16(pix) * i) >> 9;
+ gx += (G_VAL16(pix) * i) >> 9;
+ bx += (B_VAL16(pix) * i) >> 9;
+ }
+
+ r += (rx * j) >> 14;
+ g += (gx * j) >> 14;
+ b += (bx * j) >> 14;
+ }
+
+ R_VAL16(dptr) = r >> 5;
+ G_VAL16(dptr) = g >> 5;
+ B_VAL16(dptr) = b >> 5;
+ A_VAL16(dptr) = 0xFFFF;
+ dptr++;
+ }
+ }
+ }
+}
+
+/* scale by area sampling */
+void DImgScale::dimgScaleAARGBA16(DImgScaleInfo *isi, ullong *dest,
+ int dxx, int dyy,
+ int dw, int dh,
+ int dow, int sow)
+{
+ ullong *sptr, *dptr;
+ int x, y, end;
+ ullong **ypoints = isi->ypoints16;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *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 + (y * dow);
+ sptr = ypoints[dyy + y];
+ if(YAP > 0)
+ {
+ for(x = dxx; x < end; x++)
+ {
+ llong r, g, b, a;
+ llong rr, gg, bb, aa;
+ ullong *pix;
+
+ if(XAP > 0)
+ {
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL16(pix) * INV_XAP;
+ g = G_VAL16(pix) * INV_XAP;
+ b = B_VAL16(pix) * INV_XAP;
+ a = A_VAL16(pix) * INV_XAP;
+ pix++;
+ r += R_VAL16(pix) * XAP;
+ g += G_VAL16(pix) * XAP;
+ b += B_VAL16(pix) * XAP;
+ a += A_VAL16(pix) * XAP;
+ pix += sow;
+ rr = R_VAL16(pix) * XAP;
+ gg = G_VAL16(pix) * XAP;
+ bb = B_VAL16(pix) * XAP;
+ aa = A_VAL16(pix) * XAP;
+ pix--;
+ rr += R_VAL16(pix) * INV_XAP;
+ gg += G_VAL16(pix) * INV_XAP;
+ bb += B_VAL16(pix) * INV_XAP;
+ aa += A_VAL16(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;
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = a;
+
+ dptr++;
+ }
+ else
+ {
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL16(pix) * INV_YAP;
+ g = G_VAL16(pix) * INV_YAP;
+ b = B_VAL16(pix) * INV_YAP;
+ a = A_VAL16(pix) * INV_YAP;
+ pix += sow;
+ r += R_VAL16(pix) * YAP;
+ g += G_VAL16(pix) * YAP;
+ b += B_VAL16(pix) * YAP;
+ a += A_VAL16(pix) * YAP;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+ a >>= 8;
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = a;
+
+ dptr++;
+ }
+ }
+ }
+ else
+ {
+ for(x = dxx; x < end; x++)
+ {
+ llong r, g, b, a;
+ ullong *pix;
+
+ if(XAP > 0)
+ {
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = R_VAL16(pix) * INV_XAP;
+ g = G_VAL16(pix) * INV_XAP;
+ b = B_VAL16(pix) * INV_XAP;
+ a = A_VAL16(pix) * INV_XAP;
+ pix++;
+ r += R_VAL16(pix) * XAP;
+ g += G_VAL16(pix) * XAP;
+ b += B_VAL16(pix) * XAP;
+ a += A_VAL16(pix) * XAP;
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+ a >>= 8;
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = a;
+
+ dptr++;
+ }
+ else
+ *dptr++ = sptr[xpoints[x] ];
+ }
+ }
+ }
+ }
+ /* if we're scaling down vertically */
+ else if(isi->xup_yup == 1)
+ {
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cy, j;
+ ullong *pix;
+ llong 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 + (y * dow);
+ for(x = dxx; x < end; x++)
+ {
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = (R_VAL16(pix) * yap) >> 10;
+ g = (G_VAL16(pix) * yap) >> 10;
+ b = (B_VAL16(pix) * yap) >> 10;
+ a = (A_VAL16(pix) * yap) >> 10;
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy)
+ {
+ pix += sow;
+ r += (R_VAL16(pix) * Cy) >> 10;
+ g += (G_VAL16(pix) * Cy) >> 10;
+ b += (B_VAL16(pix) * Cy) >> 10;
+ a += (A_VAL16(pix) * Cy) >> 10;
+ }
+ if(j > 0)
+ {
+ pix += sow;
+ r += (R_VAL16(pix) * j) >> 10;
+ g += (G_VAL16(pix) * j) >> 10;
+ b += (B_VAL16(pix) * j) >> 10;
+ a += (A_VAL16(pix) * j) >> 10;
+ }
+ if(XAP > 0)
+ {
+ pix = ypoints[dyy + y] + xpoints[x] + 1;
+ rr = (R_VAL16(pix) * yap) >> 10;
+ gg = (G_VAL16(pix) * yap) >> 10;
+ bb = (B_VAL16(pix) * yap) >> 10;
+ aa = (A_VAL16(pix) * yap) >> 10;
+ for(j = (1 << 14) - yap; j > Cy; j -= Cy)
+ {
+ pix += sow;
+ rr += (R_VAL16(pix) * Cy) >> 10;
+ gg += (G_VAL16(pix) * Cy) >> 10;
+ bb += (B_VAL16(pix) * Cy) >> 10;
+ aa += (A_VAL16(pix) * Cy) >> 10;
+ }
+ if(j > 0)
+ {
+ pix += sow;
+ rr += (R_VAL16(pix) * j) >> 10;
+ gg += (G_VAL16(pix) * j) >> 10;
+ bb += (B_VAL16(pix) * j) >> 10;
+ aa += (A_VAL16(pix) * j) >> 10;
+ }
+ 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;
+ }
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = a;
+
+ dptr++;
+ }
+ }
+ }
+ /* if we're scaling down horizontally */
+ else if(isi->xup_yup == 2)
+ {
+ /*\ 'Correct' version, with math units prepared for MMXification \*/
+ int Cx, j;
+ ullong *pix;
+ llong 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 + y * dow;
+ for(x = dxx; x < end; x++)
+ {
+ Cx = XAP >> 16;
+ xap = XAP & 0xffff;
+
+ pix = ypoints[dyy + y] + xpoints[x];
+ r = (R_VAL16(pix) * xap) >> 10;
+ g = (G_VAL16(pix) * xap) >> 10;
+ b = (B_VAL16(pix) * xap) >> 10;
+ a = (A_VAL16(pix) * xap) >> 10;
+ for(j = (1 << 14) - xap; j > Cx; j -= Cx)
+ {
+ pix++;
+ r += (R_VAL16(pix) * Cx) >> 10;
+ g += (G_VAL16(pix) * Cx) >> 10;
+ b += (B_VAL16(pix) * Cx) >> 10;
+ a += (A_VAL16(pix) * Cx) >> 10;
+ }
+ if(j > 0)
+ {
+ pix++;
+ r += (R_VAL16(pix) * j) >> 10;
+ g += (G_VAL16(pix) * j) >> 10;
+ b += (B_VAL16(pix) * j) >> 10;
+ a += (A_VAL16(pix) * j) >> 10;
+ }
+ if(YAP > 0)
+ {
+ pix = ypoints[dyy + y] + xpoints[x] + sow;
+ rr = (R_VAL16(pix) * xap) >> 10;
+ gg = (G_VAL16(pix) * xap) >> 10;
+ bb = (B_VAL16(pix) * xap) >> 10;
+ aa = (A_VAL16(pix) * xap) >> 10;
+ for(j = (1 << 14) - xap; j > Cx; j -= Cx)
+ {
+ pix++;
+ rr += (R_VAL16(pix) * Cx) >> 10;
+ gg += (G_VAL16(pix) * Cx) >> 10;
+ bb += (B_VAL16(pix) * Cx) >> 10;
+ aa += (A_VAL16(pix) * Cx) >> 10;
+ }
+ if(j > 0)
+ {
+ pix++;
+ rr += (R_VAL16(pix) * j) >> 10;
+ gg += (G_VAL16(pix) * j) >> 10;
+ bb += (B_VAL16(pix) * j) >> 10;
+ aa += (A_VAL16(pix) * j) >> 10;
+ }
+ 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;
+ }
+
+ R_VAL16(dptr) = r;
+ G_VAL16(dptr) = g;
+ B_VAL16(dptr) = b;
+ A_VAL16(dptr) = a;
+
+ dptr++;
+ }
+ }
+ }
+ /* if we're scaling down horizontally & vertically */
+ else{
+ /*\ '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;
+ ullong *pix;
+ llong 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 + y * 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_VAL16(pix) * xap) >> 9;
+ gx = (G_VAL16(pix) * xap) >> 9;
+ bx = (B_VAL16(pix) * xap) >> 9;
+ ax = (A_VAL16(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx)
+ {
+ rx += (R_VAL16(pix) * Cx) >> 9;
+ gx += (G_VAL16(pix) * Cx) >> 9;
+ bx += (B_VAL16(pix) * Cx) >> 9;
+ ax += (A_VAL16(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0)
+ {
+ rx += (R_VAL16(pix) * i) >> 9;
+ gx += (G_VAL16(pix) * i) >> 9;
+ bx += (B_VAL16(pix) * i) >> 9;
+ ax += (A_VAL16(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_VAL16(pix) * xap) >> 9;
+ gx = (G_VAL16(pix) * xap) >> 9;
+ bx = (B_VAL16(pix) * xap) >> 9;
+ ax = (A_VAL16(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx)
+ {
+ rx += (R_VAL16(pix) * Cx) >> 9;
+ gx += (G_VAL16(pix) * Cx) >> 9;
+ bx += (B_VAL16(pix) * Cx) >> 9;
+ ax += (A_VAL16(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0)
+ {
+ rx += (R_VAL16(pix) * i) >> 9;
+ gx += (G_VAL16(pix) * i) >> 9;
+ bx += (B_VAL16(pix) * i) >> 9;
+ ax += (A_VAL16(pix) * i) >> 9;
+ }
+
+ r += (rx * Cy) >> 14;
+ g += (gx * Cy) >> 14;
+ b += (bx * Cy) >> 14;
+ a += (ax * Cy) >> 14;
+ }
+ if(j > 0)
+ {
+ pix = sptr;
+ sptr += sow;
+ rx = (R_VAL16(pix) * xap) >> 9;
+ gx = (G_VAL16(pix) * xap) >> 9;
+ bx = (B_VAL16(pix) * xap) >> 9;
+ ax = (A_VAL16(pix) * xap) >> 9;
+ pix++;
+ for(i = (1 << 14) - xap; i > Cx; i -= Cx)
+ {
+ rx += (R_VAL16(pix) * Cx) >> 9;
+ gx += (G_VAL16(pix) * Cx) >> 9;
+ bx += (B_VAL16(pix) * Cx) >> 9;
+ ax += (A_VAL16(pix) * Cx) >> 9;
+ pix++;
+ }
+ if(i > 0)
+ {
+ rx += (R_VAL16(pix) * i) >> 9;
+ gx += (G_VAL16(pix) * i) >> 9;
+ bx += (B_VAL16(pix) * i) >> 9;
+ ax += (A_VAL16(pix) * i) >> 9;
+ }
+
+ r += (rx * j) >> 14;
+ g += (gx * j) >> 14;
+ b += (bx * j) >> 14;
+ a += (ax * j) >> 14;
+ }
+
+ R_VAL16(dptr) = r >> 5;
+ G_VAL16(dptr) = g >> 5;
+ B_VAL16(dptr) = b >> 5;
+ A_VAL16(dptr) = a >> 5;
+ dptr++;
+ }
+ }
+ }
+}
+
+/**
+//Documentation of the cryptic dimgScaleAARGBA
+dimgScaleAARGBA(
+DImgScaleInfo *isi, // scaleinfo
+unsigned int *dest, // destination img data
+int dxx, // destination x location corresponding to start x of src section
+int dyy, // destination y location corresponding to start y of src section
+int dx, // destination x start location
+int dy, // destination y start location
+int dw, // destination width
+int dh, // destination height
+int dow, // destination scanline width
+int sow); // src scanline width
+*/
+
+} // NameSpace Digikam