/* Compared to operator(), this method avoids 2 floating point operations (we use average=0 and sigma=1 most of the time). The speed difference is noticeable. */ static Real standard_value(Real x) { Real z; if (x < x_low_ || x_high_ < x) { z = tail_value(x); } else { z = x - 0.5; Real r = z*z; z = (((((a1_*r+a2_)*r+a3_)*r+a4_)*r+a5_)*r+a6_)*z / (((((b1_*r+b2_)*r+b3_)*r+b4_)*r+b5_)*r+1.0); } // The relative error of the approximation has absolute value less // than 1.15e-9. One iteration of Halley's rational method (third // order) gives full machine precision. // #define REFINE_TO_FULL_MACHINE_PRECISION_USING_HALLEYS_METHOD #ifdef REFINE_TO_FULL_MACHINE_PRECISION_USING_HALLEYS_METHOD // error (f_(z) - x) divided by the cumulative's derivative const Real r = (f_(z) - x) * M_SQRT2 * M_SQRTPI * exp(0.5 * z*z); // Halley's method z -= r/(1+0.5*z*r); #endif return z; }
void Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) { BBitmap* src; BBitmap* dest; intType srcW, srcH; intType destW, destH; intType x, y, i; ColumnDataFP* columnData; ColumnDataFP* cd; const uchar* srcBits; uchar* destBits; intType srcBPR, destBPR; const uchar* srcData; uchar* destDataRow; uchar* destData; const int32 kBPP = 4; src = GetSrcImage(); dest = fScaledImage; srcW = src->Bounds().IntegerWidth(); srcH = src->Bounds().IntegerHeight(); destW = dest->Bounds().IntegerWidth(); destH = dest->Bounds().IntegerHeight(); srcBits = (uchar*)src->Bits(); destBits = (uchar*)dest->Bits(); srcBPR = src->BytesPerRow(); destBPR = dest->BytesPerRow(); fixed_point fpSrcW = to_fixed_point(srcW); fixed_point fpDestW = to_fixed_point(destW); fixed_point fpSrcH = to_fixed_point(srcH); fixed_point fpDestH = to_fixed_point(destH); columnData = new ColumnDataFP[destW]; cd = columnData; for (i = 0; i < destW; i ++, cd++) { fixed_point column = to_fixed_point(i) * (long_fixed_point)fpSrcW / fpDestW; cd->srcColumn = from_fixed_point(column); cd->alpha1 = tail_value(column); // weigth for left pixel value cd->alpha0 = kFPOne - cd->alpha1; // weigth for right pixel value } destDataRow = destBits + fromRow * destBPR; for (y = fromRow; IsRunning() && y <= toRow; y ++, destDataRow += destBPR) { fixed_point row; intType srcRow; fixed_point alpha0, alpha1; if (fpDestH == 0) { row = 0; } else { row = to_fixed_point(y) * (long_fixed_point)fpSrcH / fpDestH; } srcRow = from_fixed_point(row); alpha1 = tail_value(row); // weight for row y+1 alpha0 = kFPOne - alpha1; // weight for row y srcData = srcBits + srcRow * srcBPR; destData = destDataRow; // Need mult_correction for "outer" multiplication only #define I4(i) from_fixed_point(mult_correction(\ (a[i] * a0 + b[i] * a1) * alpha0 + \ (c[i] * a0 + d[i] * a1) * alpha1)) #define V2(i) from_fixed_point(a[i] * alpha0 + c[i] * alpha1); #define H2(i) from_fixed_point(a[i] * a0 + b[i] * a1); if (y < destH) { fixed_point a0, a1; const uchar *a, *b, *c, *d; for (x = 0; x < destW; x ++, destData += kBPP) { a = srcData + columnData[x].srcColumn * kBPP; b = a + kBPP; c = a + srcBPR; d = c + kBPP; a0 = columnData[x].alpha0; a1 = columnData[x].alpha1; destData[0] = I4(0); destData[1] = I4(1); destData[2] = I4(2); destData[3] = I4(3); } // right column a = srcData + srcW * kBPP; c = a + srcBPR; destData[0] = V2(0); destData[1] = V2(1); destData[2] = V2(2); destData[3] = V2(3); } else { fixed_point a0, a1; const uchar *a, *b; for (x = 0; x < destW; x ++, destData += kBPP) { a = srcData + columnData[x].srcColumn * kBPP; b = a + kBPP; a0 = columnData[x].alpha0; a1 = columnData[x].alpha1; destData[0] = H2(0); destData[1] = H2(1); destData[2] = H2(2); destData[3] = H2(3); } // bottom, right pixel a = srcData + srcW * kBPP; destData[0] = a[0]; destData[1] = a[1]; destData[2] = a[2]; destData[3] = a[3]; } } delete[] columnData; }