OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #define _USE_MATH_DEFINES | 5 #define _USE_MATH_DEFINES |
6 #include <algorithm> | 6 #include <algorithm> |
7 #include <cmath> | 7 #include <cmath> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "skia/ext/image_operations.h" | 10 #include "skia/ext/image_operations.h" |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 } // namespace | 335 } // namespace |
336 | 336 |
337 // Resize ---------------------------------------------------------------------- | 337 // Resize ---------------------------------------------------------------------- |
338 | 338 |
339 // static | 339 // static |
340 SkBitmap ImageOperations::Resize(const SkBitmap& source, | 340 SkBitmap ImageOperations::Resize(const SkBitmap& source, |
341 ResizeMethod method, | 341 ResizeMethod method, |
342 int dest_width, int dest_height, | 342 int dest_width, int dest_height, |
343 const SkIRect& dest_subset, | 343 const SkIRect& dest_subset, |
344 SkBitmap::Allocator* allocator) { | 344 SkBitmap::Allocator* allocator) { |
345 if (method == ImageOperations::RESIZE_SUBPIXEL) { | 345 TRACE_EVENT2("disabled-by-default-skia", "ImageOperations::Resize", |
346 return ResizeSubpixel(source, dest_width, dest_height, | 346 "src_pixels", source.width() * source.height(), "dst_pixels", |
347 dest_subset, allocator); | 347 dest_width * dest_height); |
348 } else { | |
349 return ResizeBasic(source, method, dest_width, dest_height, dest_subset, | |
350 allocator); | |
351 } | |
352 } | |
353 | |
354 // static | |
355 SkBitmap ImageOperations::ResizeSubpixel(const SkBitmap& source, | |
356 int dest_width, int dest_height, | |
357 const SkIRect& dest_subset, | |
358 SkBitmap::Allocator* allocator) { | |
359 TRACE_EVENT2("skia", "ImageOperations::ResizeSubpixel", | |
360 "src_pixels", source.width()*source.height(), | |
361 "dst_pixels", dest_width*dest_height); | |
362 // Currently only works on Linux/BSD because these are the only platforms | |
363 // where SkFontHost::GetSubpixelOrder is defined. | |
364 #if defined(OS_LINUX) && !defined(GTV) | |
365 // Understand the display. | |
366 const SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder(); | |
367 const SkFontHost::LCDOrientation orientation = | |
368 SkFontHost::GetSubpixelOrientation(); | |
369 | |
370 // Decide on which dimension, if any, to deploy subpixel rendering. | |
371 int w = 1; | |
372 int h = 1; | |
373 switch (orientation) { | |
374 case SkFontHost::kHorizontal_LCDOrientation: | |
375 w = dest_width < source.width() ? 3 : 1; | |
376 break; | |
377 case SkFontHost::kVertical_LCDOrientation: | |
378 h = dest_height < source.height() ? 3 : 1; | |
379 break; | |
380 } | |
381 | |
382 // Resize the image. | |
383 const int width = dest_width * w; | |
384 const int height = dest_height * h; | |
385 SkIRect subset = { dest_subset.fLeft, dest_subset.fTop, | |
386 dest_subset.fLeft + dest_subset.width() * w, | |
387 dest_subset.fTop + dest_subset.height() * h }; | |
388 SkBitmap img = ResizeBasic(source, ImageOperations::RESIZE_LANCZOS3, width, | |
389 height, subset, allocator); | |
390 const int row_words = img.rowBytes() / 4; | |
391 if (w == 1 && h == 1) | |
392 return img; | |
393 | |
394 // Render into subpixels. | |
395 SkBitmap result; | |
396 result.setInfo(SkImageInfo::MakeN32(dest_subset.width(), dest_subset.height(), | |
397 img.alphaType())); | |
398 result.allocPixels(allocator, NULL); | |
399 if (!result.readyToDraw()) | |
400 return img; | |
401 | |
402 SkAutoLockPixels locker(img); | |
403 if (!img.readyToDraw()) | |
404 return img; | |
405 | |
406 uint32* src_row = img.getAddr32(0, 0); | |
407 uint32* dst_row = result.getAddr32(0, 0); | |
408 for (int y = 0; y < dest_subset.height(); y++) { | |
409 uint32* src = src_row; | |
410 uint32* dst = dst_row; | |
411 for (int x = 0; x < dest_subset.width(); x++, src += w, dst++) { | |
412 uint8 r = 0, g = 0, b = 0, a = 0; | |
413 switch (order) { | |
414 case SkFontHost::kRGB_LCDOrder: | |
415 switch (orientation) { | |
416 case SkFontHost::kHorizontal_LCDOrientation: | |
417 r = SkGetPackedR32(src[0]); | |
418 g = SkGetPackedG32(src[1]); | |
419 b = SkGetPackedB32(src[2]); | |
420 a = SkGetPackedA32(src[1]); | |
421 break; | |
422 case SkFontHost::kVertical_LCDOrientation: | |
423 r = SkGetPackedR32(src[0 * row_words]); | |
424 g = SkGetPackedG32(src[1 * row_words]); | |
425 b = SkGetPackedB32(src[2 * row_words]); | |
426 a = SkGetPackedA32(src[1 * row_words]); | |
427 break; | |
428 } | |
429 break; | |
430 case SkFontHost::kBGR_LCDOrder: | |
431 switch (orientation) { | |
432 case SkFontHost::kHorizontal_LCDOrientation: | |
433 b = SkGetPackedB32(src[0]); | |
434 g = SkGetPackedG32(src[1]); | |
435 r = SkGetPackedR32(src[2]); | |
436 a = SkGetPackedA32(src[1]); | |
437 break; | |
438 case SkFontHost::kVertical_LCDOrientation: | |
439 b = SkGetPackedB32(src[0 * row_words]); | |
440 g = SkGetPackedG32(src[1 * row_words]); | |
441 r = SkGetPackedR32(src[2 * row_words]); | |
442 a = SkGetPackedA32(src[1 * row_words]); | |
443 break; | |
444 } | |
445 break; | |
446 case SkFontHost::kNONE_LCDOrder: | |
447 NOTREACHED(); | |
448 } | |
449 // Premultiplied alpha is very fragile. | |
450 a = a > r ? a : r; | |
451 a = a > g ? a : g; | |
452 a = a > b ? a : b; | |
453 *dst = SkPackARGB32(a, r, g, b); | |
454 } | |
455 src_row += h * row_words; | |
456 dst_row += result.rowBytes() / 4; | |
457 } | |
458 return result; | |
459 #else | |
460 return SkBitmap(); | |
461 #endif // OS_POSIX && !OS_MACOSX && !defined(OS_ANDROID) | |
462 } | |
463 | |
464 // static | |
465 SkBitmap ImageOperations::ResizeBasic(const SkBitmap& source, | |
466 ResizeMethod method, | |
467 int dest_width, int dest_height, | |
468 const SkIRect& dest_subset, | |
469 SkBitmap::Allocator* allocator) { | |
470 TRACE_EVENT2("skia", "ImageOperations::ResizeBasic", | |
471 "src_pixels", source.width()*source.height(), | |
472 "dst_pixels", dest_width*dest_height); | |
473 // Ensure that the ResizeMethod enumeration is sound. | 348 // Ensure that the ResizeMethod enumeration is sound. |
474 SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) && | 349 SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) && |
475 (method <= RESIZE_LAST_QUALITY_METHOD)) || | 350 (method <= RESIZE_LAST_QUALITY_METHOD)) || |
476 ((RESIZE_FIRST_ALGORITHM_METHOD <= method) && | 351 ((RESIZE_FIRST_ALGORITHM_METHOD <= method) && |
477 (method <= RESIZE_LAST_ALGORITHM_METHOD))); | 352 (method <= RESIZE_LAST_ALGORITHM_METHOD))); |
478 | 353 |
479 // Time how long this takes to see if it's a problem for users. | 354 // Time how long this takes to see if it's a problem for users. |
480 base::TimeTicks resize_start = base::TimeTicks::Now(); | 355 base::TimeTicks resize_start = base::TimeTicks::Now(); |
481 | 356 |
482 SkIRect dest = { 0, 0, dest_width, dest_height }; | 357 SkIRect dest = { 0, 0, dest_width, dest_height }; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 SkBitmap ImageOperations::Resize(const SkBitmap& source, | 405 SkBitmap ImageOperations::Resize(const SkBitmap& source, |
531 ResizeMethod method, | 406 ResizeMethod method, |
532 int dest_width, int dest_height, | 407 int dest_width, int dest_height, |
533 SkBitmap::Allocator* allocator) { | 408 SkBitmap::Allocator* allocator) { |
534 SkIRect dest_subset = { 0, 0, dest_width, dest_height }; | 409 SkIRect dest_subset = { 0, 0, dest_width, dest_height }; |
535 return Resize(source, method, dest_width, dest_height, dest_subset, | 410 return Resize(source, method, dest_width, dest_height, dest_subset, |
536 allocator); | 411 allocator); |
537 } | 412 } |
538 | 413 |
539 } // namespace skia | 414 } // namespace skia |
OLD | NEW |