Clean up (and slightly speed up) blinear scaling

This commit is contained in:
Peter Thoman 2013-05-03 13:17:36 +02:00
parent 655e7dbfbb
commit 75bbe9df9f

View File

@ -135,29 +135,29 @@ namespace {
}
// this is sadly much faster than an inline function with a loop, at least in VC10
#define MIX_PIXELS(p0, p1, p2, factors) \
((R(p0)*factors[0] + R(p1)*factors[1] + R(p2)*factors[2])/255 << 0 ) | \
((G(p0)*factors[0] + G(p1)*factors[1] + G(p2)*factors[2])/255 << 8 ) | \
((B(p0)*factors[0] + B(p1)*factors[1] + B(p2)*factors[2])/255 << 16 ) | \
((A(p0)*factors[0] + A(p1)*factors[1] + A(p2)*factors[2])/255 << 24 )
#define MIX_PIXELS(_p0, _p1, _factors) \
( (R(_p0)*(_factors)[0] + R(_p1)*(_factors)[1])/255 << 0 ) | \
( (G(_p0)*(_factors)[0] + G(_p1)*(_factors)[1])/255 << 8 ) | \
( (B(_p0)*(_factors)[0] + B(_p1)*(_factors)[1])/255 << 16 ) | \
( (A(_p0)*(_factors)[0] + A(_p1)*(_factors)[1])/255 << 24 )
void mix(u32* data, u32* source, u32* mask, u32 maskmax, int width, int l, int u) {
for(int y = l; y < u; ++y) {
for(int x = 0; x < width; ++x) {
int pos = y*width + x;
u8 mixFactors[3] = {0, (std::min(mask[pos], maskmax)*255)/maskmax, 0 };
u8 mixFactors[2] = { 0, (std::min(mask[pos], maskmax)*255)/maskmax };
mixFactors[0] = 255-mixFactors[1];
data[pos] = MIX_PIXELS(data[pos], source[pos], 0, mixFactors);
data[pos] = MIX_PIXELS(data[pos], source[pos], mixFactors);
if(A(source[pos]) == 0) data[pos] = data[pos] & 0x00FFFFFF; // xBRZ always does a better job with hard alpha
}
}
}
const static u8 BILINEAR_FACTORS[4][5][3] = {
{ { 76,179, 0}, { 0,179, 76}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0} }, // x2
{ { 85,170, 0}, { 0,255, 0}, { 0,170, 85}, { 0, 0, 0}, { 0, 0, 0} }, // x3
{ {102,153, 0}, { 51,204, 0}, { 0,204, 51}, { 0,153,102}, { 0, 0, 0} }, // x4
{ {102,153, 0}, { 51,204, 0}, { 0,255, 0}, { 0,204, 51}, { 0,153,102} }, // x5
const static u8 BILINEAR_FACTORS[4][3][2] = {
{ { 44,211}, { 0, 0}, { 0, 0} }, // x2
{ { 64,191}, { 0,255}, { 0, 0} }, // x3
{ { 77,178}, { 26,229}, { 0, 0} }, // x4
{ {102,153}, { 51,204}, { 0,255} }, // x5
};
// integral bilinear upscaling by factor f, horizontal part
template<int f>
@ -170,8 +170,12 @@ namespace {
u32 left = data[inpos - (x==0 ?0:1)];
u32 center = data[inpos];
u32 right = data[inpos + (x==w-1?0:1)];
for(int i=0; i<f; ++i) { // hope the compiler unrolls this
out[y*outw + x*f + i] = MIX_PIXELS(left, center, right, BILINEAR_FACTORS[f-2][i]);
int i=0;
for(; i<f/2+f%2; ++i) { // first half of the new pixels + center, hope the compiler unrolls this
out[y*outw + x*f + i] = MIX_PIXELS(left, center, BILINEAR_FACTORS[f-2][i]);
}
for(; i<f ; ++i) { // second half of the new pixels, hope the compiler unrolls this
out[y*outw + x*f + i] = MIX_PIXELS(right, center, BILINEAR_FACTORS[f-2][f-1-i]);
}
}
}
@ -192,12 +196,18 @@ namespace {
static_assert(f>1 && f<=5, "Bilinear scaling only implemented for 2x, 3x, 4x, and 5x");
int outw = w*f;
for(int y = l; y < u; ++y) {
u32 uy = y - (y==gl ?0:1);
u32 ly = y + (y==gu-1?0:1);
for(int x = 0; x < outw; ++x) {
u32 upper = data[(y - (y==gl ?0:1)) * outw + x];
u32 upper = data[uy * outw + x];
u32 center = data[y * outw + x];
u32 lower = data[(y + (y==gu-1?0:1)) * outw + x];
for(int i=0; i<f; ++i) { // hope the compiler unrolls this
out[(y*f + i)*outw + x] = MIX_PIXELS(upper, center, lower, BILINEAR_FACTORS[f-2][i]);
u32 lower = data[ly * outw + x];
int i=0;
for(; i<f/2+f%2; ++i) { // first half of the new pixels + center, hope the compiler unrolls this
out[(y*f + i)*outw + x] = MIX_PIXELS(upper, center, BILINEAR_FACTORS[f-2][i]);
}
for(; i<f ; ++i) { // second half of the new pixels, hope the compiler unrolls this
out[(y*f + i)*outw + x] = MIX_PIXELS(lower, center, BILINEAR_FACTORS[f-2][f-1-i]);
}
}
}