double sxc;
double offset = 0.5;
double ratio = (double)dst_x / src_x;
+ double sum, nc;
+ int i, ci;
SFilter sFilter = filters[filter_id];
int i1 = int(__rfbmin(sxc+sFilter.radius+0.5, src_x));
weightTabs[x].i0 = i0; weightTabs[x].i1 = i1;
- weightTabs[x].weight = new double[i1-i0];
+ weightTabs[x].weight = new short[i1-i0];
+
+ // Calculate coeff to normalize the filter weights
+ for (sum = 0, i = i0; i < i1; i++) sum += sFilter.func(double(i)-sxc+0.5);
+ if (sum == 0.) nc = (double)(WEIGHT_OF_ONE); else nc = (double)(WEIGHT_OF_ONE)/sum;
+
// Calculate the weight coeffs on the scale filter interval
- for (int ci = 0, i = i0; i < i1; i++) {
- weightTabs[x].weight[ci++] = (double)sFilter.func(double(i)-sxc+0.5);
+ for (ci = 0, i = i0; i < i1; i++) {
+ weightTabs[x].weight[ci++] = (short)floor((sFilter.func(double(i)-sxc+0.5) * nc) + 0.5);
}
}
}
namespace rfb {
+ #define BITS_OF_CHANEL 8
+ #define BITS_OF_WEIGHT 14
+ #define FINALSHIFT 2 * BITS_OF_WEIGHT - BITS_OF_CHANEL
+ #define WEIGHT_OF_ONE 1 << BITS_OF_WEIGHT
+
typedef double (*filter_func)(double x);
const double pi = 3.14159265358979;
// Scale filter weight table
typedef struct {
- short int i0, i1; // Filter function interval, [i0..i1)
- double *weight; // Weight coefficients on the filter function interval
+ short i0, i1; // Filter function interval, [i0..i1)
+ short *weight; // Weight coefficients on the filter function interval
} SFilterWeightTab;
void ScaledPixelBuffer::scaleRect(const Rect& rect) {
Rect changed_rect;
U8 *ptr, *ptrs, *px, *pxs;
- double rx, gx, bx, red, green, blue, *xweight, *yweight, xWeight, yWeight;
- int r, g, b, xwi, ywi;
+ int r, g, b, rx, gx, bx, red, green, blue, xwi, ywi;
+ short *xweight, *yweight, xWeight, yWeight;
// Calculate the changed pixel rect in the scaled image
changed_rect = calculateScaleBoundary(rect);
yweight = yWeightTabs[y].weight;
for (int x = changed_rect.tl.x; x < changed_rect.br.x; x++) {
- ywi = 0; red = 0; green = 0; blue = 0;
+ // Init the sum of colors with (1 << (shift-1)) for rounding
+ ywi = 0; red = green = blue = 1 << (FINALSHIFT-1);
xweight = xWeightTabs[x].weight;
// Calculate the scaled pixel value at (x, y) coordinates by
for (int xs = xWeightTabs[x].i0; xs < xWeightTabs[x].i1; xs++) {
rgbFromPixel(*((U32*)px), r, g, b);
xWeight = xweight[xwi++];
- rx += r * xWeight;
- gx += g * xWeight;
- bx += b * xWeight;
+ rx += (int)xWeight * r;
+ gx += (int)xWeight * g;
+ bx += (int)xWeight * b;
px += bytesPerSrcPixel;
}
yWeight = yweight[ywi++];
- red += rx * yWeight;
- green += gx * yWeight;
- blue += bx * yWeight;
+ red += (int)yWeight * (rx >> BITS_OF_CHANEL);
+ green += (int)yWeight * (gx >> BITS_OF_CHANEL);
+ blue += (int)yWeight * (bx >> BITS_OF_CHANEL);
pxs += bytesPerSrcRow;
}
- *ptr++ = U8(blue);
- *ptr++ = U8(green);
- *ptr++ = U8(red);
+ *ptr++ = U8(blue >> FINALSHIFT);
+ *ptr++ = U8(green >> FINALSHIFT);
+ *ptr++ = U8(red >> FINALSHIFT);
ptr++;
}
ptrs += bytesPerScaledRow;