| 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 |