/* Class which describes a single colour channel of an image in a generalized * way allowing for easy and accurate scaling to any size. * * Written by: Chris Studholme * Copyright: GPL (http://www.fsf.org/copyleft/gpl.html) * $Id: GImageComponent.cpp,v 1.8 2003/05/28 02:30:01 cvs Exp $ */ #include #include #include #include "GImageComponent.h" //#define SHOW_STATS #define DEFAULT_ERROR 0.1 #define MAXITTER 20 #define MINITTER 3 inline short boundcheck(int x) { if (x<-32768) return -32768; if (x>32767) return 32767; return x; } template inline T MAX(T a, T b) { return (a>b ? a : b); } template inline T MAX(T a, T b, T c) { if (b>a) a=b; if (c>a) a=c; return a; } template inline T MAX(T a, T b, T c, T d) { if (b>a) a=b; if (c>a) a=c; if (d>a) a=d; return a; } template inline T MAX(T a, T b, T c, T d, T e, T f, T g, T h) { if (b>a) a=b; if (c>a) a=c; if (d>a) a=d; if (e>a) a=e; if (f>a) a=f; if (g>a) a=g; if (h>a) a=h; return a; } template inline T MIN(T a, T b) { return (a inline T MIN(T a, T b, T c) { if (b inline T MIN(T a, T b, T c, T d) { if (b inline T MIN(T a, T b, T c, T d, T e, T f, T g, T h) { if (b0 ? error : DEFAULT_ERROR; totalerror=0; } /* x1>8; int ix2 = x2>>8; int iy1 = y1>>8; int iy2 = y2>>8; if (ix1<0) ix1=0; else if (ix1>=w-1) ix1=w-2; if (iy1<0) iy1=0; else if (iy1>=h-1) iy1=h-2; if (ix2<0) ix2=0; else if (ix2>=w-1) ix2=w-2; if (iy2<0) iy2=0; else if (iy2>=h-1) iy2=h-2; int logx=0; for (int i=ix2-ix1; i!=0; ++logx,i>>=1) ; // calculate log2(ix2-ix1) int logy=0; for (int i=iy2-iy1; i!=0; ++logy,i>>=1) ; // calculate log2(iy2-iy1) logy = logy>logx ? logy-logx : 0; int result=0; int by1 = y1 - (iy1<<8); for (int y=iy1; y<=iy2; ++y) { int by2 = y2 - (y<<8); if ((y<(h-2))&&(by2>256)) by2=256; int sy = by2+by1; int bx1 = x1 - (ix1<<8); int r1=0; for (int x=ix1; x<=ix2; ++x) { int bx2 = x2 - (x<<8); if ((x<(w-2))&&(bx2>256)) bx2=256; int sx = bx2+bx1; int p1 = (512-sx)*tl[y*w+x] +sx*tl[y*w+x+1]; // 24 bits int p2 = (512-sx)*tl[(y+1)*w+x] +sx*tl[(y+1)*w+x+1]; // 24 bits int p3 = (p1*512>>4) + ((8+p2-p1)>>4)*sy; // net shift right 4, 31 bits int dx = bx2-bx1; r1 += (((256+p3)>>9)*dx)>>logx; bx1=0; } int dy = by2-by1; result += (r1/(x2-x1)*dy)>>logy; // 31-logx bits by1=0; } return ( result/(y2-y1) )/4; } /* x1=w-1) ix1=w-2; if (iy1<0) iy1=0; else if (iy1>=h-1) iy1=h-2; if (ix2<0) ix2=0; else if (ix2>=w-1) ix2=w-2; if (iy2<0) iy2=0; else if (iy2>=h-1) iy2=h-2; double result=0; double by1 = y1-iy1; for (int y=iy1; y<=iy2; ++y) { double by2 = y2-y; if ((y<(h-2))&&(by2>1)) by2=1; double sy = by2+by1; double dy = by2-by1; double bx1 = x1-ix1; for (int x=ix1; x<=ix2; ++x) { double bx2 = x2-x; if ((x<(w-2))&&(bx2>1)) bx2=1; double sx = bx2+bx1; double dx = bx2-bx1; result += ( (sx-2)*(sy-2)*tl[y*w+x] -sx*(sy-2)*tl[y*w+x+1] -(sx-2)*sy*tl[(y+1)*w+x] +sx*sy*tl[(y+1)*w+x+1] )*dx*dy; bx1=0; } by1=0; } return ((int)(result/(x2-x1)/(y2-y1)))/4; } /* y10) for (int i=0; i0) for (int i=0; imax) { tl[y*w+x]=max; continue; } // check if central pixel is too dim int min = (extra ? MIN(tl[y*w+x-1],tl[y*w+x+1],tl[(y-1)*w+x],tl[(y+1)*w+x]) : MIN(tl[y*w+x-1],tl[y*w+x+1],tl[(y-1)*w+x], tl[(y+1)*w+x],tl[(y-1)*w+x-1],tl[(y-1)*w+x+1], tl[(y+1)*w+x-1],tl[(y+1)*w+x+1])); if (tl[y*w+x]werror)&&(itterwerror)&&(itterherror)&&(itterherror)&&(itter=tail; --y) for (int x=1; x=2)) { ++tail; --itter; totalerror+=werror; } // check answer at tail (accurate method) else while ((itter>=MINITTER)&&(tailwerror)&&(ittermitter) mitter=itter; --itter; } // advance head if (head