ultimatepp/uppsrc/Draw/BiCubic.cpp
cxl ef8ddd537c .cosmetics
git-svn-id: svn://ultimatepp.org/upp/trunk@11881 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2018-04-09 22:27:58 +00:00

73 lines
1.8 KiB
C++

#include "Draw.h"
namespace Upp {
double BicubicKernel(double x)
{
double r = 0;
double xp2 = x + 2;
double xp1 = x + 1;
double xm1 = x - 1;
if(xp2 > 0)
r += xp2 * xp2 * xp2;
if(xp1 > 0)
r -= 4 * xp1 * xp1 * xp1;
if(x > 0)
r += 6 * x * x * x;
if(xm1 > 0)
r -= 4 * xm1 * xm1 * xm1;
return 0.16666666666666666 * r;
}
Image RescaleBicubic(const Image& img, Size sz, const Rect& sr, Gate<int, int> progress)
{
ASSERT(sr.top >= 0 && sr.left >= 0 && sr.right <= img.GetWidth() && sr.bottom <= img.GetHeight());
Size isz = sr.GetSize();
ImageBuffer ib(sz);
RGBA *t = ~ib;
double inv_cx = 1.0 / sz.cx;
for(int y = 0; y < sz.cy; y++) {
if(progress(y, sz.cy))
return ib;
int sy = y * isz.cy / sz.cy;
double dy = y * isz.cy / (double)sz.cy - sy;
for(int x = 0; x < sz.cx; x++) {
int sx = x * isz.cx / sz.cx;
double dx = x * isz.cx * inv_cx - sx;
double red = 0;
double green = 0;
double blue = 0;
double alpha = 0;
for(int yy = -1; yy <= 2; yy++) {
double ky = BicubicKernel(yy - dy);
const RGBA *l = img[minmax(sy + yy + sr.top, sr.top, sr.bottom - 1)];
for(int xx = -1; xx <= 2; xx++) {
const RGBA& s = l[minmax(sx + xx + sr.left, sr.left, sr.right - 1)];
double weight = ky * BicubicKernel(xx - dx);
red += weight * s.r;
green += weight * s.g;
blue += weight * s.b;
alpha += weight * s.a;
}
}
t->r = (int)fround(red);
t->g = (int)fround(green);
t->b = (int)fround(blue);
t->a = (int)fround(alpha);
t++;
}
}
return ib;
}
Image RescaleBicubic(const Image& img, int cx, int cy, Gate<int, int> progress)
{
return RescaleBicubic(img, Size(cx, cy), img.GetSize(), progress);
}
Image RescaleBicubic(const Image& img, Size sz, Gate<int, int> progress)
{
return RescaleBicubic(img, sz, img.GetSize(), progress);
}
}