| OLD | NEW |
| 1 #include "SkBitmapScaler.h" | 1 #include "SkBitmapScaler.h" |
| 2 #include "SkBitmapFilter.h" | 2 #include "SkBitmapFilter.h" |
| 3 #include "SkRect.h" | 3 #include "SkRect.h" |
| 4 #include "SkTArray.h" | 4 #include "SkTArray.h" |
| 5 #include "SkErrorInternals.h" | 5 #include "SkErrorInternals.h" |
| 6 #include "SkConvolver.h" | 6 #include "SkConvolver.h" |
| 7 | 7 |
| 8 // SkResizeFilter --------------------------------------------------------------
-- | 8 // SkResizeFilter --------------------------------------------------------------
-- |
| 9 | 9 |
| 10 // Encapsulates computation and storage of the filters required for one complete | 10 // Encapsulates computation and storage of the filters required for one complete |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 // about 30% faster than Lanczos-3. The use of Hamming-1 has been deemed | 226 // about 30% faster than Lanczos-3. The use of Hamming-1 has been deemed |
| 227 // an acceptable trade-off between quality and speed. | 227 // an acceptable trade-off between quality and speed. |
| 228 case SkBitmapScaler::RESIZE_BETTER: | 228 case SkBitmapScaler::RESIZE_BETTER: |
| 229 return SkBitmapScaler::RESIZE_HAMMING; | 229 return SkBitmapScaler::RESIZE_HAMMING; |
| 230 default: | 230 default: |
| 231 return SkBitmapScaler::RESIZE_MITCHELL; | 231 return SkBitmapScaler::RESIZE_MITCHELL; |
| 232 } | 232 } |
| 233 } | 233 } |
| 234 | 234 |
| 235 // static | 235 // static |
| 236 SkBitmap SkBitmapScaler::Resize(const SkBitmap& source, | 236 bool SkBitmapScaler::Resize(SkBitmap* resultPtr, |
| 237 ResizeMethod method, | 237 const SkBitmap& source, |
| 238 int destWidth, int destHeight, | 238 ResizeMethod method, |
| 239 const SkIRect& destSubset, | 239 int destWidth, int destHeight, |
| 240 SkConvolutionProcs* convolveProcs, | 240 const SkIRect& destSubset, |
| 241 SkBitmap::Allocator* allocator) { | 241 SkConvolutionProcs* convolveProcs, |
| 242 SkBitmap::Allocator* allocator) { |
| 242 // Ensure that the ResizeMethod enumeration is sound. | 243 // Ensure that the ResizeMethod enumeration is sound. |
| 243 SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) && | 244 SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) && |
| 244 (method <= RESIZE_LAST_QUALITY_METHOD)) || | 245 (method <= RESIZE_LAST_QUALITY_METHOD)) || |
| 245 ((RESIZE_FIRST_ALGORITHM_METHOD <= method) && | 246 ((RESIZE_FIRST_ALGORITHM_METHOD <= method) && |
| 246 (method <= RESIZE_LAST_ALGORITHM_METHOD))); | 247 (method <= RESIZE_LAST_ALGORITHM_METHOD))); |
| 247 | 248 |
| 248 SkIRect dest = { 0, 0, destWidth, destHeight }; | 249 SkIRect dest = { 0, 0, destWidth, destHeight }; |
| 249 if (!dest.contains(destSubset)) { | 250 if (!dest.contains(destSubset)) { |
| 250 SkErrorInternals::SetError( kInvalidArgument_SkError, | 251 SkErrorInternals::SetError( kInvalidArgument_SkError, |
| 251 "Sorry, you passed me a bitmap resize " | 252 "Sorry, you passed me a bitmap resize " |
| 252 " method I have never heard of: %d", | 253 " method I have never heard of: %d", |
| 253 method ); | 254 method ); |
| 254 } | 255 } |
| 255 | 256 |
| 256 // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just | 257 // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just |
| 257 // return empty. | 258 // return empty. |
| 258 if (source.width() < 1 || source.height() < 1 || | 259 if (source.width() < 1 || source.height() < 1 || |
| 259 destWidth < 1 || destHeight < 1) { | 260 destWidth < 1 || destHeight < 1) { |
| 260 return SkBitmap(); | 261 // todo: seems like we could handle negative dstWidth/Height, since that |
| 262 // is just a negative scale (flip) |
| 263 return false; |
| 261 } | 264 } |
| 262 | 265 |
| 263 method = ResizeMethodToAlgorithmMethod(method); | 266 method = ResizeMethodToAlgorithmMethod(method); |
| 264 | 267 |
| 265 // Check that we deal with an "algorithm methods" from this point onward. | 268 // Check that we deal with an "algorithm methods" from this point onward. |
| 266 SkASSERT((SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD <= method) && | 269 SkASSERT((SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD <= method) && |
| 267 (method <= SkBitmapScaler::RESIZE_LAST_ALGORITHM_METHOD)); | 270 (method <= SkBitmapScaler::RESIZE_LAST_ALGORITHM_METHOD)); |
| 268 | 271 |
| 269 SkAutoLockPixels locker(source); | 272 SkAutoLockPixels locker(source); |
| 270 if (!source.readyToDraw() || source.config() != SkBitmap::kARGB_8888_Config) | 273 if (!source.readyToDraw() || |
| 271 return SkBitmap(); | 274 source.config() != SkBitmap::kARGB_8888_Config) { |
| 275 return false; |
| 276 } |
| 272 | 277 |
| 273 SkResizeFilter filter(method, source.width(), source.height(), | 278 SkResizeFilter filter(method, source.width(), source.height(), |
| 274 destWidth, destHeight, destSubset, convolveProcs); | 279 destWidth, destHeight, destSubset, convolveProcs); |
| 275 | 280 |
| 276 // Get a source bitmap encompassing this touched area. We construct the | 281 // Get a source bitmap encompassing this touched area. We construct the |
| 277 // offsets and row strides such that it looks like a new bitmap, while | 282 // offsets and row strides such that it looks like a new bitmap, while |
| 278 // referring to the old data. | 283 // referring to the old data. |
| 279 const unsigned char* sourceSubset = | 284 const unsigned char* sourceSubset = |
| 280 reinterpret_cast<const unsigned char*>(source.getPixels()); | 285 reinterpret_cast<const unsigned char*>(source.getPixels()); |
| 281 | 286 |
| 282 // Convolve into the result. | 287 // Convolve into the result. |
| 283 SkBitmap result; | 288 SkBitmap result; |
| 284 result.setConfig(SkBitmap::kARGB_8888_Config, | 289 result.setConfig(SkBitmap::kARGB_8888_Config, |
| 285 destSubset.width(), destSubset.height()); | 290 destSubset.width(), destSubset.height()); |
| 286 result.allocPixels(allocator, NULL); | 291 result.allocPixels(allocator, NULL); |
| 287 if (!result.readyToDraw()) | 292 if (!result.readyToDraw()) { |
| 288 return SkBitmap(); | 293 return false; |
| 294 } |
| 289 | 295 |
| 290 BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()), | 296 BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()), |
| 291 !source.isOpaque(), filter.xFilter(), filter.yFilter(), | 297 !source.isOpaque(), filter.xFilter(), filter.yFilter(), |
| 292 static_cast<int>(result.rowBytes()), | 298 static_cast<int>(result.rowBytes()), |
| 293 static_cast<unsigned char*>(result.getPixels()), | 299 static_cast<unsigned char*>(result.getPixels()), |
| 294 convolveProcs, true); | 300 convolveProcs, true); |
| 295 | 301 |
| 296 // Preserve the "opaque" flag for use as an optimization later. | 302 // Preserve the "opaque" flag for use as an optimization later. |
| 297 result.setIsOpaque(source.isOpaque()); | 303 result.setIsOpaque(source.isOpaque()); |
| 298 | 304 *resultPtr = result; |
| 299 return result; | 305 return true; |
| 300 } | 306 } |
| 301 | 307 |
| 302 // static | 308 // static |
| 303 SkBitmap SkBitmapScaler::Resize(const SkBitmap& source, | 309 bool SkBitmapScaler::Resize(SkBitmap* resultPtr, |
| 304 ResizeMethod method, | 310 const SkBitmap& source, |
| 305 int destWidth, int destHeight, | 311 ResizeMethod method, |
| 306 SkConvolutionProcs* convolveProcs, | 312 int destWidth, int destHeight, |
| 307 SkBitmap::Allocator* allocator) { | 313 SkConvolutionProcs* convolveProcs, |
| 314 SkBitmap::Allocator* allocator) { |
| 308 SkIRect destSubset = { 0, 0, destWidth, destHeight }; | 315 SkIRect destSubset = { 0, 0, destWidth, destHeight }; |
| 309 return Resize(source, method, destWidth, destHeight, destSubset, | 316 return Resize(resultPtr, source, method, destWidth, destHeight, destSubset, |
| 310 convolveProcs, allocator); | 317 convolveProcs, allocator); |
| 311 } | 318 } |
| OLD | NEW |