diff options
author | humper <humper@google.com> | 2014-08-28 14:27:42 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-08-28 14:27:42 -0700 |
commit | d73c169637f1ab0b96bae43269da7216bb93a7e1 (patch) | |
tree | 673a5affaf7d1db167e8f759b10b16bf3ecf9d35 /src/core | |
parent | 0209e95cc2625a445c1cb6c4213d2182e5c832d7 (diff) |
Second attempt to land the integral image scaling change.
Scale all images to the nearest rounded integer, and if there's still
any scaling factor left over, pass it on to the subsequent bilerp code.
Should avoid artifacts when tiling scaled images.
Original CL received an LGTM from reed; new version disabled tiling
in the downsamplebitmap GM; I verified that this fixes the issue
we were seeing there on non-neon androids.
BUG=skia:2888
R=reed@android.com
TBR=reed
Author: humper@google.com
Review URL: https://codereview.chromium.org/514383003
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkBitmapProcState.cpp | 46 | ||||
-rw-r--r-- | src/core/SkBitmapProcState.h | 1 |
2 files changed, 34 insertions, 13 deletions
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp index 52a2ecf25c..a269170422 100644 --- a/src/core/SkBitmapProcState.cpp +++ b/src/core/SkBitmapProcState.cpp @@ -129,21 +129,34 @@ static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { bool SkBitmapProcState::possiblyScaleImage() { SkASSERT(NULL == fBitmap); + fAdjustedMatrix = false; + if (fFilterLevel <= SkPaint::kLow_FilterLevel) { return false; } // Check to see if the transformation matrix is simple, and if we're // doing high quality scaling. If so, do the bitmap scale here and - // remove the scaling component from the matrix. + // remove the (non-fractional) scaling component from the matrix. + + SkScalar invScaleX = fInvMatrix.getScaleX(); + SkScalar invScaleY = fInvMatrix.getScaleY(); + + float trueDestWidth = fOrigBitmap.width() / invScaleX; + float trueDestHeight = fOrigBitmap.height() / invScaleY; + +#ifndef SK_IGNORE_PROPER_FRACTIONAL_SCALING + float roundedDestWidth = SkScalarRoundToScalar(trueDestWidth); + float roundedDestHeight = SkScalarRoundToScalar(trueDestHeight); +#else + float roundedDestWidth = trueDestWidth; + float roundedDestHeight = trueDestHeight; +#endif if (SkPaint::kHigh_FilterLevel == fFilterLevel && fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) && kN32_SkColorType == fOrigBitmap.colorType() && cache_size_okay(fOrigBitmap, fInvMatrix)) { - SkScalar invScaleX = fInvMatrix.getScaleX(); - SkScalar invScaleY = fInvMatrix.getScaleY(); - if (SkScalarNearlyEqual(invScaleX,1.0f) && SkScalarNearlyEqual(invScaleY,1.0f)) { // short-circuit identity scaling; the output is supposed to @@ -160,17 +173,14 @@ bool SkBitmapProcState::possiblyScaleImage() { return false; } - if (!SkBitmapCache::Find(fOrigBitmap, invScaleX, invScaleY, &fScaledBitmap)) { - float dest_width = fOrigBitmap.width() / invScaleX; - float dest_height = fOrigBitmap.height() / invScaleY; - + if (!SkBitmapCache::Find(fOrigBitmap, roundedDestWidth, roundedDestHeight, &fScaledBitmap)) { // All the criteria are met; let's make a new bitmap. if (!SkBitmapScaler::Resize(&fScaledBitmap, fOrigBitmap, SkBitmapScaler::RESIZE_BEST, - dest_width, - dest_height, + roundedDestWidth, + roundedDestHeight, SkResourceCache::GetAllocator())) { // we failed to create fScaledBitmap, so just return and let // the scanline proc handle it. @@ -179,7 +189,7 @@ bool SkBitmapProcState::possiblyScaleImage() { } SkASSERT(NULL != fScaledBitmap.getPixels()); - SkBitmapCache::Add(fOrigBitmap, invScaleX, invScaleY, fScaledBitmap); + SkBitmapCache::Add(fOrigBitmap, roundedDestWidth, roundedDestHeight, fScaledBitmap); } SkASSERT(NULL != fScaledBitmap.getPixels()); @@ -189,9 +199,19 @@ bool SkBitmapProcState::possiblyScaleImage() { fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScaleX(), fInvMatrix.getTranslateY() / fInvMatrix.getScaleY()); +#ifndef SK_IGNORE_PROPER_FRACTIONAL_SCALING + // reintroduce any fractional scaling missed by our integral scale done above. + + float fractionalScaleX = roundedDestWidth/trueDestWidth; + float fractionalScaleY = roundedDestHeight/trueDestHeight; + + fInvMatrix.postScale(fractionalScaleX, fractionalScaleY); +#endif + fAdjustedMatrix = true; + // Set our filter level to low -- the only post-filtering this // image might require is some interpolation if the translation - // is fractional. + // is fractional or if there's any remaining scaling to be done. fFilterLevel = SkPaint::kLow_FilterLevel; return true; } @@ -347,7 +367,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && SkShader::kClamp_TileMode == fTileModeY; - if (!(clampClamp || trivialMatrix)) { + if (!(fAdjustedMatrix || clampClamp || trivialMatrix)) { fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); } diff --git a/src/core/SkBitmapProcState.h b/src/core/SkBitmapProcState.h index 289e308eed..ac4f1a4710 100644 --- a/src/core/SkBitmapProcState.h +++ b/src/core/SkBitmapProcState.h @@ -141,6 +141,7 @@ private: SkBitmap fScaledBitmap; // chooseProcs SkAutoTUnref<const SkMipMap> fCurrMip; + bool fAdjustedMatrix; // set by possiblyScaleImage MatrixProc chooseMatrixProc(bool trivial_matrix); bool chooseProcs(const SkMatrix& inv, const SkPaint&); |