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