| OLD | NEW |
| 1 /* |
| 2 * Copyright 2015 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 1 #include "SkBitmapScaler.h" | 8 #include "SkBitmapScaler.h" |
| 2 #include "SkBitmapFilter.h" | 9 #include "SkBitmapFilter.h" |
| 3 #include "SkRect.h" | 10 #include "SkRect.h" |
| 4 #include "SkTArray.h" | 11 #include "SkTArray.h" |
| 5 #include "SkErrorInternals.h" | 12 #include "SkErrorInternals.h" |
| 6 #include "SkConvolver.h" | 13 #include "SkConvolver.h" |
| 7 | 14 |
| 8 // SkResizeFilter --------------------------------------------------------------
-- | 15 // SkResizeFilter --------------------------------------------------------------
-- |
| 9 | 16 |
| 10 // Encapsulates computation and storage of the filters required for one complete | 17 // Encapsulates computation and storage of the filters required for one complete |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 return SkBitmapScaler::RESIZE_HAMMING; | 241 return SkBitmapScaler::RESIZE_HAMMING; |
| 235 default: | 242 default: |
| 236 #ifdef SK_HIGH_QUALITY_IS_LANCZOS | 243 #ifdef SK_HIGH_QUALITY_IS_LANCZOS |
| 237 return SkBitmapScaler::RESIZE_LANCZOS3; | 244 return SkBitmapScaler::RESIZE_LANCZOS3; |
| 238 #else | 245 #else |
| 239 return SkBitmapScaler::RESIZE_MITCHELL; | 246 return SkBitmapScaler::RESIZE_MITCHELL; |
| 240 #endif | 247 #endif |
| 241 } | 248 } |
| 242 } | 249 } |
| 243 | 250 |
| 244 // static | 251 static bool resize(const SkPixmap& pmap, SkBitmap* resultPtr, SkBitmapScaler::Re
sizeMethod method, |
| 252 float destWidth, float destHeight, SkBitmap::Allocator* alloc
ator, |
| 253 const SkConvolutionProcs& convolveProcs) { |
| 254 const SkRect destSubset = SkRect::MakeWH(destWidth, destHeight); |
| 255 SkResizeFilter filter(method, pmap.width(), pmap.height(), |
| 256 destWidth, destHeight, destSubset, convolveProcs); |
| 257 |
| 258 // Get a source bitmap encompassing this touched area. We construct the |
| 259 // offsets and row strides such that it looks like a new bitmap, while |
| 260 // referring to the old data. |
| 261 const uint8_t* sourceSubset = reinterpret_cast<const uint8_t*>(pmap.addr()); |
| 262 |
| 263 // Convolve into the result. |
| 264 SkBitmap result; |
| 265 result.setInfo(SkImageInfo::MakeN32(SkScalarCeilToInt(destSubset.width()), |
| 266 SkScalarCeilToInt(destSubset.height()), |
| 267 pmap.alphaType())); |
| 268 result.allocPixels(allocator, NULL); |
| 269 if (!result.readyToDraw()) { |
| 270 return false; |
| 271 } |
| 272 |
| 273 BGRAConvolve2D(sourceSubset, static_cast<int>(pmap.rowBytes()), |
| 274 !pmap.isOpaque(), filter.xFilter(), filter.yFilter(), |
| 275 static_cast<int>(result.rowBytes()), |
| 276 static_cast<unsigned char*>(result.getPixels()), |
| 277 convolveProcs, true); |
| 278 |
| 279 *resultPtr = result; |
| 280 resultPtr->lockPixels(); |
| 281 SkASSERT(resultPtr->getPixels()); |
| 282 return true; |
| 283 } |
| 284 |
| 245 bool SkBitmapScaler::Resize(SkBitmap* resultPtr, | 285 bool SkBitmapScaler::Resize(SkBitmap* resultPtr, |
| 246 const SkBitmap& source, | 286 const SkBitmap& source, |
| 247 ResizeMethod method, | 287 ResizeMethod method, |
| 248 float destWidth, float destHeight, | 288 float destWidth, float destHeight, |
| 249 SkBitmap::Allocator* allocator) { | 289 SkBitmap::Allocator* allocator) { |
| 290 if (source.colorType() != kN32_SkColorType) { |
| 291 return false; |
| 292 } |
| 250 | 293 |
| 251 SkConvolutionProcs convolveProcs= { 0, NULL, NULL, NULL, NULL }; | 294 SkConvolutionProcs convolveProcs= { 0, NULL, NULL, NULL, NULL }; |
| 252 PlatformConvolutionProcs(&convolveProcs); | 295 PlatformConvolutionProcs(&convolveProcs); |
| 253 | 296 |
| 254 SkRect destSubset = { 0, 0, destWidth, destHeight }; | 297 // Ensure that the ResizeMethod enumeration is sound. |
| 255 | 298 SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) && |
| 256 // Ensure that the ResizeMethod enumeration is sound. | |
| 257 SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) && | |
| 258 (method <= RESIZE_LAST_QUALITY_METHOD)) || | 299 (method <= RESIZE_LAST_QUALITY_METHOD)) || |
| 259 ((RESIZE_FIRST_ALGORITHM_METHOD <= method) && | 300 ((RESIZE_FIRST_ALGORITHM_METHOD <= method) && |
| 260 (method <= RESIZE_LAST_ALGORITHM_METHOD))); | 301 (method <= RESIZE_LAST_ALGORITHM_METHOD))); |
| 261 | 302 |
| 262 // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just | 303 // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just |
| 263 // return empty. | 304 // return empty. |
| 264 if (source.width() < 1 || source.height() < 1 || | 305 if (source.width() < 1 || source.height() < 1 || destWidth < 1 || destHeight
< 1) { |
| 265 destWidth < 1 || destHeight < 1) { | 306 // todo: seems like we could handle negative dstWidth/Height, since that |
| 266 // todo: seems like we could handle negative dstWidth/Height, since that | 307 // is just a negative scale (flip) |
| 267 // is just a negative scale (flip) | 308 return false; |
| 268 return false; | 309 } |
| 269 } | |
| 270 | 310 |
| 271 method = ResizeMethodToAlgorithmMethod(method); | 311 method = ResizeMethodToAlgorithmMethod(method); |
| 272 | 312 |
| 273 // Check that we deal with an "algorithm methods" from this point onward. | 313 // Check that we deal with an "algorithm methods" from this point onward. |
| 274 SkASSERT((SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD <= method) && | 314 SkASSERT((SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD <= method) && |
| 275 (method <= SkBitmapScaler::RESIZE_LAST_ALGORITHM_METHOD)); | 315 (method <= SkBitmapScaler::RESIZE_LAST_ALGORITHM_METHOD)); |
| 276 | 316 |
| 277 SkAutoLockPixels locker(source); | 317 SkAutoPixmapUnlock result; |
| 278 if (!source.readyToDraw() || | 318 if (!source.requestLock(&result)) { |
| 279 source.colorType() != kN32_SkColorType) { | 319 return false; |
| 280 return false; | 320 } |
| 281 } | 321 return resize(result.pixmap(), resultPtr, method, destWidth, destHeight, all
ocator, |
| 282 | 322 convolveProcs); |
| 283 SkResizeFilter filter(method, source.width(), source.height(), | |
| 284 destWidth, destHeight, destSubset, convolveProcs); | |
| 285 | |
| 286 // Get a source bitmap encompassing this touched area. We construct the | |
| 287 // offsets and row strides such that it looks like a new bitmap, while | |
| 288 // referring to the old data. | |
| 289 const unsigned char* sourceSubset = | |
| 290 reinterpret_cast<const unsigned char*>(source.getPixels()); | |
| 291 | |
| 292 // Convolve into the result. | |
| 293 SkBitmap result; | |
| 294 result.setInfo(SkImageInfo::MakeN32(SkScalarCeilToInt(destSubset.width()), | |
| 295 SkScalarCeilToInt(destSubset.height()), | |
| 296 source.alphaType())); | |
| 297 result.allocPixels(allocator, NULL); | |
| 298 if (!result.readyToDraw()) { | |
| 299 return false; | |
| 300 } | |
| 301 | |
| 302 BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()), | |
| 303 !source.isOpaque(), filter.xFilter(), filter.yFilter(), | |
| 304 static_cast<int>(result.rowBytes()), | |
| 305 static_cast<unsigned char*>(result.getPixels()), | |
| 306 convolveProcs, true); | |
| 307 | |
| 308 *resultPtr = result; | |
| 309 resultPtr->lockPixels(); | |
| 310 SkASSERT(resultPtr->getPixels()); | |
| 311 return true; | |
| 312 } | 323 } |
| 313 | 324 |
| 314 // static -- simpler interface to the resizer; returns a default bitmap if scali
ng | 325 // static -- simpler interface to the resizer; returns a default bitmap if scali
ng |
| 315 // fails for any reason. This is the interface that Chrome expects. | 326 // fails for any reason. This is the interface that Chrome expects. |
| 316 SkBitmap SkBitmapScaler::Resize(const SkBitmap& source, | 327 SkBitmap SkBitmapScaler::Resize(const SkBitmap& source, |
| 317 ResizeMethod method, | 328 ResizeMethod method, |
| 318 float destWidth, float destHeight, | 329 float destWidth, float destHeight, |
| 319 SkBitmap::Allocator* allocator) { | 330 SkBitmap::Allocator* allocator) { |
| 320 SkBitmap result; | 331 SkBitmap result; |
| 321 if (!Resize(&result, source, method, destWidth, destHeight, allocator)) { | 332 if (!Resize(&result, source, method, destWidth, destHeight, allocator)) { |
| 322 return SkBitmap(); | 333 return SkBitmap(); |
| 323 } | 334 } |
| 324 return result; | 335 return result; |
| 325 } | 336 } |
| OLD | NEW |