Index: src/core/SkBitmapScaler.cpp |
diff --git a/src/core/SkBitmapScaler.cpp b/src/core/SkBitmapScaler.cpp |
index 4bd3cc732db7949a8eb330297ed7b2d55a3ecac6..9ce4171879a1bdb39a268ab626f741bd47da2389 100644 |
--- a/src/core/SkBitmapScaler.cpp |
+++ b/src/core/SkBitmapScaler.cpp |
@@ -1,3 +1,10 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
#include "SkBitmapScaler.h" |
#include "SkBitmapFilter.h" |
#include "SkRect.h" |
@@ -241,74 +248,78 @@ static SkBitmapScaler::ResizeMethod ResizeMethodToAlgorithmMethod( |
} |
} |
-// static |
+static bool resize(const SkPixmap& pmap, SkBitmap* resultPtr, SkBitmapScaler::ResizeMethod method, |
+ float destWidth, float destHeight, SkBitmap::Allocator* allocator, |
+ const SkConvolutionProcs& convolveProcs) { |
+ const SkRect destSubset = SkRect::MakeWH(destWidth, destHeight); |
+ SkResizeFilter filter(method, pmap.width(), pmap.height(), |
+ destWidth, destHeight, destSubset, convolveProcs); |
+ |
+ // Get a source bitmap encompassing this touched area. We construct the |
+ // offsets and row strides such that it looks like a new bitmap, while |
+ // referring to the old data. |
+ const uint8_t* sourceSubset = reinterpret_cast<const uint8_t*>(pmap.addr()); |
+ |
+ // Convolve into the result. |
+ SkBitmap result; |
+ result.setInfo(SkImageInfo::MakeN32(SkScalarCeilToInt(destSubset.width()), |
+ SkScalarCeilToInt(destSubset.height()), |
+ pmap.alphaType())); |
+ result.allocPixels(allocator, NULL); |
+ if (!result.readyToDraw()) { |
+ return false; |
+ } |
+ |
+ BGRAConvolve2D(sourceSubset, static_cast<int>(pmap.rowBytes()), |
+ !pmap.isOpaque(), filter.xFilter(), filter.yFilter(), |
+ static_cast<int>(result.rowBytes()), |
+ static_cast<unsigned char*>(result.getPixels()), |
+ convolveProcs, true); |
+ |
+ *resultPtr = result; |
+ resultPtr->lockPixels(); |
+ SkASSERT(resultPtr->getPixels()); |
+ return true; |
+} |
+ |
bool SkBitmapScaler::Resize(SkBitmap* resultPtr, |
const SkBitmap& source, |
ResizeMethod method, |
float destWidth, float destHeight, |
SkBitmap::Allocator* allocator) { |
+ if (source.colorType() != kN32_SkColorType) { |
+ return false; |
+ } |
- SkConvolutionProcs convolveProcs= { 0, NULL, NULL, NULL, NULL }; |
- PlatformConvolutionProcs(&convolveProcs); |
- |
- SkRect destSubset = { 0, 0, destWidth, destHeight }; |
+ SkConvolutionProcs convolveProcs= { 0, NULL, NULL, NULL, NULL }; |
+ PlatformConvolutionProcs(&convolveProcs); |
- // Ensure that the ResizeMethod enumeration is sound. |
- SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) && |
+ // Ensure that the ResizeMethod enumeration is sound. |
+ SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) && |
(method <= RESIZE_LAST_QUALITY_METHOD)) || |
((RESIZE_FIRST_ALGORITHM_METHOD <= method) && |
(method <= RESIZE_LAST_ALGORITHM_METHOD))); |
- // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just |
- // return empty. |
- if (source.width() < 1 || source.height() < 1 || |
- destWidth < 1 || destHeight < 1) { |
- // todo: seems like we could handle negative dstWidth/Height, since that |
- // is just a negative scale (flip) |
- return false; |
- } |
+ // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just |
+ // return empty. |
+ if (source.width() < 1 || source.height() < 1 || destWidth < 1 || destHeight < 1) { |
+ // todo: seems like we could handle negative dstWidth/Height, since that |
+ // is just a negative scale (flip) |
+ return false; |
+ } |
- method = ResizeMethodToAlgorithmMethod(method); |
+ method = ResizeMethodToAlgorithmMethod(method); |
- // Check that we deal with an "algorithm methods" from this point onward. |
- SkASSERT((SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD <= method) && |
+ // Check that we deal with an "algorithm methods" from this point onward. |
+ SkASSERT((SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD <= method) && |
(method <= SkBitmapScaler::RESIZE_LAST_ALGORITHM_METHOD)); |
- SkAutoLockPixels locker(source); |
- if (!source.readyToDraw() || |
- source.colorType() != kN32_SkColorType) { |
- return false; |
- } |
- |
- SkResizeFilter filter(method, source.width(), source.height(), |
- destWidth, destHeight, destSubset, convolveProcs); |
- |
- // Get a source bitmap encompassing this touched area. We construct the |
- // offsets and row strides such that it looks like a new bitmap, while |
- // referring to the old data. |
- const unsigned char* sourceSubset = |
- reinterpret_cast<const unsigned char*>(source.getPixels()); |
- |
- // Convolve into the result. |
- SkBitmap result; |
- result.setInfo(SkImageInfo::MakeN32(SkScalarCeilToInt(destSubset.width()), |
- SkScalarCeilToInt(destSubset.height()), |
- source.alphaType())); |
- result.allocPixels(allocator, NULL); |
- if (!result.readyToDraw()) { |
- return false; |
- } |
- |
- BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()), |
- !source.isOpaque(), filter.xFilter(), filter.yFilter(), |
- static_cast<int>(result.rowBytes()), |
- static_cast<unsigned char*>(result.getPixels()), |
- convolveProcs, true); |
- |
- *resultPtr = result; |
- resultPtr->lockPixels(); |
- SkASSERT(resultPtr->getPixels()); |
- return true; |
+ SkAutoPixmapUnlock result; |
+ if (!source.requestLock(&result)) { |
+ return false; |
+ } |
+ return resize(result.pixmap(), resultPtr, method, destWidth, destHeight, allocator, |
+ convolveProcs); |
} |
// static -- simpler interface to the resizer; returns a default bitmap if scaling |