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 #include "ui/gfx/skbitmap_operations.h" | 5 #include "ui/gfx/skbitmap_operations.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <string.h> | 9 #include <string.h> |
10 #include <algorithm> | 10 #include <algorithm> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "third_party/skia/include/core/SkBitmap.h" | 13 #include "third_party/skia/include/core/SkBitmap.h" |
14 #include "third_party/skia/include/core/SkCanvas.h" | 14 #include "third_party/skia/include/core/SkCanvas.h" |
15 #include "third_party/skia/include/core/SkColorFilter.h" | 15 #include "third_party/skia/include/core/SkColorFilter.h" |
16 #include "third_party/skia/include/core/SkColorPriv.h" | 16 #include "third_party/skia/include/core/SkColorPriv.h" |
17 #include "third_party/skia/include/core/SkUnPreMultiply.h" | 17 #include "third_party/skia/include/core/SkUnPreMultiply.h" |
18 #include "third_party/skia/include/effects/SkBlurImageFilter.h" | 18 #include "third_party/skia/include/effects/SkBlurImageFilter.h" |
19 #include "ui/gfx/geometry/insets.h" | 19 #include "ui/gfx/geometry/insets.h" |
20 #include "ui/gfx/geometry/point.h" | 20 #include "ui/gfx/geometry/point.h" |
21 #include "ui/gfx/geometry/size.h" | 21 #include "ui/gfx/geometry/size.h" |
22 | 22 |
23 // static | 23 // static |
24 SkBitmap SkBitmapOperations::CreateInvertedBitmap(const SkBitmap& image) { | 24 SkBitmap SkBitmapOperations::CreateInvertedBitmap(const SkBitmap& image) { |
25 DCHECK(image.colorType() == kN32_SkColorType); | 25 DCHECK(image.colorType() == kN32_SkColorType); |
26 | 26 |
27 SkAutoLockPixels lock_image(image); | |
28 | |
29 SkBitmap inverted; | 27 SkBitmap inverted; |
30 inverted.allocN32Pixels(image.width(), image.height()); | 28 inverted.allocN32Pixels(image.width(), image.height()); |
31 | 29 |
32 for (int y = 0; y < image.height(); ++y) { | 30 for (int y = 0; y < image.height(); ++y) { |
33 uint32_t* image_row = image.getAddr32(0, y); | 31 uint32_t* image_row = image.getAddr32(0, y); |
34 uint32_t* dst_row = inverted.getAddr32(0, y); | 32 uint32_t* dst_row = inverted.getAddr32(0, y); |
35 | 33 |
36 for (int x = 0; x < image.width(); ++x) { | 34 for (int x = 0; x < image.width(); ++x) { |
37 uint32_t image_pixel = image_row[x]; | 35 uint32_t image_pixel = image_row[x]; |
38 dst_row[x] = (image_pixel & 0xFF000000) | | 36 dst_row[x] = (image_pixel & 0xFF000000) | |
(...skipping 15 matching lines...) Expand all Loading... |
54 DCHECK(first.colorType() == kN32_SkColorType); | 52 DCHECK(first.colorType() == kN32_SkColorType); |
55 | 53 |
56 // Optimize for case where we won't need to blend anything. | 54 // Optimize for case where we won't need to blend anything. |
57 static const double alpha_min = 1.0 / 255; | 55 static const double alpha_min = 1.0 / 255; |
58 static const double alpha_max = 254.0 / 255; | 56 static const double alpha_max = 254.0 / 255; |
59 if (alpha < alpha_min) | 57 if (alpha < alpha_min) |
60 return first; | 58 return first; |
61 else if (alpha > alpha_max) | 59 else if (alpha > alpha_max) |
62 return second; | 60 return second; |
63 | 61 |
64 SkAutoLockPixels lock_first(first); | |
65 SkAutoLockPixels lock_second(second); | |
66 | |
67 SkBitmap blended; | 62 SkBitmap blended; |
68 blended.allocN32Pixels(first.width(), first.height()); | 63 blended.allocN32Pixels(first.width(), first.height()); |
69 | 64 |
70 double first_alpha = 1 - alpha; | 65 double first_alpha = 1 - alpha; |
71 | 66 |
72 for (int y = 0; y < first.height(); ++y) { | 67 for (int y = 0; y < first.height(); ++y) { |
73 uint32_t* first_row = first.getAddr32(0, y); | 68 uint32_t* first_row = first.getAddr32(0, y); |
74 uint32_t* second_row = second.getAddr32(0, y); | 69 uint32_t* second_row = second.getAddr32(0, y); |
75 uint32_t* dst_row = blended.getAddr32(0, y); | 70 uint32_t* dst_row = blended.getAddr32(0, y); |
76 | 71 |
(...skipping 22 matching lines...) Expand all Loading... |
99 const SkBitmap& alpha) { | 94 const SkBitmap& alpha) { |
100 DCHECK(rgb.width() == alpha.width()); | 95 DCHECK(rgb.width() == alpha.width()); |
101 DCHECK(rgb.height() == alpha.height()); | 96 DCHECK(rgb.height() == alpha.height()); |
102 DCHECK(rgb.bytesPerPixel() == alpha.bytesPerPixel()); | 97 DCHECK(rgb.bytesPerPixel() == alpha.bytesPerPixel()); |
103 DCHECK(rgb.colorType() == kN32_SkColorType); | 98 DCHECK(rgb.colorType() == kN32_SkColorType); |
104 DCHECK(alpha.colorType() == kN32_SkColorType); | 99 DCHECK(alpha.colorType() == kN32_SkColorType); |
105 | 100 |
106 SkBitmap masked; | 101 SkBitmap masked; |
107 masked.allocN32Pixels(rgb.width(), rgb.height()); | 102 masked.allocN32Pixels(rgb.width(), rgb.height()); |
108 | 103 |
109 SkAutoLockPixels lock_rgb(rgb); | |
110 SkAutoLockPixels lock_alpha(alpha); | |
111 SkAutoLockPixels lock_masked(masked); | |
112 | |
113 for (int y = 0; y < masked.height(); ++y) { | 104 for (int y = 0; y < masked.height(); ++y) { |
114 uint32_t* rgb_row = rgb.getAddr32(0, y); | 105 uint32_t* rgb_row = rgb.getAddr32(0, y); |
115 uint32_t* alpha_row = alpha.getAddr32(0, y); | 106 uint32_t* alpha_row = alpha.getAddr32(0, y); |
116 uint32_t* dst_row = masked.getAddr32(0, y); | 107 uint32_t* dst_row = masked.getAddr32(0, y); |
117 | 108 |
118 for (int x = 0; x < masked.width(); ++x) { | 109 for (int x = 0; x < masked.width(); ++x) { |
119 unsigned alpha = SkGetPackedA32(alpha_row[x]); | 110 unsigned alpha = SkGetPackedA32(alpha_row[x]); |
120 unsigned scale = SkAlpha255To256(alpha); | 111 unsigned scale = SkAlpha255To256(alpha); |
121 dst_row[x] = SkAlphaMulQ(rgb_row[x], scale); | 112 dst_row[x] = SkAlphaMulQ(rgb_row[x], scale); |
122 } | 113 } |
(...skipping 13 matching lines...) Expand all Loading... |
136 DCHECK(mask.colorType() == kN32_SkColorType); | 127 DCHECK(mask.colorType() == kN32_SkColorType); |
137 | 128 |
138 SkBitmap background; | 129 SkBitmap background; |
139 background.allocN32Pixels(mask.width(), mask.height()); | 130 background.allocN32Pixels(mask.width(), mask.height()); |
140 | 131 |
141 double bg_a = SkColorGetA(color); | 132 double bg_a = SkColorGetA(color); |
142 double bg_r = SkColorGetR(color) * (bg_a / 255.0); | 133 double bg_r = SkColorGetR(color) * (bg_a / 255.0); |
143 double bg_g = SkColorGetG(color) * (bg_a / 255.0); | 134 double bg_g = SkColorGetG(color) * (bg_a / 255.0); |
144 double bg_b = SkColorGetB(color) * (bg_a / 255.0); | 135 double bg_b = SkColorGetB(color) * (bg_a / 255.0); |
145 | 136 |
146 SkAutoLockPixels lock_mask(mask); | |
147 SkAutoLockPixels lock_image(image); | |
148 SkAutoLockPixels lock_background(background); | |
149 | |
150 for (int y = 0; y < mask.height(); ++y) { | 137 for (int y = 0; y < mask.height(); ++y) { |
151 uint32_t* dst_row = background.getAddr32(0, y); | 138 uint32_t* dst_row = background.getAddr32(0, y); |
152 uint32_t* image_row = image.getAddr32(0, y % image.height()); | 139 uint32_t* image_row = image.getAddr32(0, y % image.height()); |
153 uint32_t* mask_row = mask.getAddr32(0, y); | 140 uint32_t* mask_row = mask.getAddr32(0, y); |
154 | 141 |
155 for (int x = 0; x < mask.width(); ++x) { | 142 for (int x = 0; x < mask.width(); ++x) { |
156 uint32_t image_pixel = image_row[x % image.width()]; | 143 uint32_t image_pixel = image_row[x % image.width()]; |
157 | 144 |
158 double img_a = SkColorGetA(image_pixel); | 145 double img_a = SkColorGetA(image_pixel); |
159 double img_r = SkColorGetR(image_pixel); | 146 double img_r = SkColorGetR(image_pixel); |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 | 498 |
512 HSLShift::LineProcessor line_proc = | 499 HSLShift::LineProcessor line_proc = |
513 HSLShift::kLineProcessors[H_op][S_op][L_op]; | 500 HSLShift::kLineProcessors[H_op][S_op][L_op]; |
514 | 501 |
515 DCHECK(bitmap.empty() == false); | 502 DCHECK(bitmap.empty() == false); |
516 DCHECK(bitmap.colorType() == kN32_SkColorType); | 503 DCHECK(bitmap.colorType() == kN32_SkColorType); |
517 | 504 |
518 SkBitmap shifted; | 505 SkBitmap shifted; |
519 shifted.allocN32Pixels(bitmap.width(), bitmap.height()); | 506 shifted.allocN32Pixels(bitmap.width(), bitmap.height()); |
520 | 507 |
521 SkAutoLockPixels lock_bitmap(bitmap); | |
522 SkAutoLockPixels lock_shifted(shifted); | |
523 | |
524 // Loop through the pixels of the original bitmap. | 508 // Loop through the pixels of the original bitmap. |
525 for (int y = 0; y < bitmap.height(); ++y) { | 509 for (int y = 0; y < bitmap.height(); ++y) { |
526 SkPMColor* pixels = bitmap.getAddr32(0, y); | 510 SkPMColor* pixels = bitmap.getAddr32(0, y); |
527 SkPMColor* tinted_pixels = shifted.getAddr32(0, y); | 511 SkPMColor* tinted_pixels = shifted.getAddr32(0, y); |
528 | 512 |
529 (*line_proc)(hsl_shift, pixels, tinted_pixels, bitmap.width()); | 513 (*line_proc)(hsl_shift, pixels, tinted_pixels, bitmap.width()); |
530 } | 514 } |
531 | 515 |
532 return shifted; | 516 return shifted; |
533 } | 517 } |
534 | 518 |
535 // static | 519 // static |
536 SkBitmap SkBitmapOperations::CreateTiledBitmap(const SkBitmap& source, | 520 SkBitmap SkBitmapOperations::CreateTiledBitmap(const SkBitmap& source, |
537 int src_x, int src_y, | 521 int src_x, int src_y, |
538 int dst_w, int dst_h) { | 522 int dst_w, int dst_h) { |
539 DCHECK(source.colorType() == kN32_SkColorType); | 523 DCHECK(source.colorType() == kN32_SkColorType); |
540 | 524 |
541 SkBitmap cropped; | 525 SkBitmap cropped; |
542 cropped.allocN32Pixels(dst_w, dst_h); | 526 cropped.allocN32Pixels(dst_w, dst_h); |
543 | 527 |
544 SkAutoLockPixels lock_source(source); | |
545 SkAutoLockPixels lock_cropped(cropped); | |
546 | |
547 // Loop through the pixels of the original bitmap. | 528 // Loop through the pixels of the original bitmap. |
548 for (int y = 0; y < dst_h; ++y) { | 529 for (int y = 0; y < dst_h; ++y) { |
549 int y_pix = (src_y + y) % source.height(); | 530 int y_pix = (src_y + y) % source.height(); |
550 while (y_pix < 0) | 531 while (y_pix < 0) |
551 y_pix += source.height(); | 532 y_pix += source.height(); |
552 | 533 |
553 uint32_t* source_row = source.getAddr32(0, y_pix); | 534 uint32_t* source_row = source.getAddr32(0, y_pix); |
554 uint32_t* dst_row = cropped.getAddr32(0, y); | 535 uint32_t* dst_row = cropped.getAddr32(0, y); |
555 | 536 |
556 for (int x = 0; x < dst_w; ++x) { | 537 for (int x = 0; x < dst_w; ++x) { |
(...skipping 25 matching lines...) Expand all Loading... |
582 | 563 |
583 // static | 564 // static |
584 SkBitmap SkBitmapOperations::DownsampleByTwo(const SkBitmap& bitmap) { | 565 SkBitmap SkBitmapOperations::DownsampleByTwo(const SkBitmap& bitmap) { |
585 // Handle the nop case. | 566 // Handle the nop case. |
586 if ((bitmap.width() <= 1) || (bitmap.height() <= 1)) | 567 if ((bitmap.width() <= 1) || (bitmap.height() <= 1)) |
587 return bitmap; | 568 return bitmap; |
588 | 569 |
589 SkBitmap result; | 570 SkBitmap result; |
590 result.allocN32Pixels((bitmap.width() + 1) / 2, (bitmap.height() + 1) / 2); | 571 result.allocN32Pixels((bitmap.width() + 1) / 2, (bitmap.height() + 1) / 2); |
591 | 572 |
592 SkAutoLockPixels lock(bitmap); | |
593 | |
594 const int resultLastX = result.width() - 1; | 573 const int resultLastX = result.width() - 1; |
595 const int srcLastX = bitmap.width() - 1; | 574 const int srcLastX = bitmap.width() - 1; |
596 | 575 |
597 for (int dest_y = 0; dest_y < result.height(); ++dest_y) { | 576 for (int dest_y = 0; dest_y < result.height(); ++dest_y) { |
598 const int src_y = dest_y << 1; | 577 const int src_y = dest_y << 1; |
599 const SkPMColor* SK_RESTRICT cur_src0 = bitmap.getAddr32(0, src_y); | 578 const SkPMColor* SK_RESTRICT cur_src0 = bitmap.getAddr32(0, src_y); |
600 const SkPMColor* SK_RESTRICT cur_src1 = cur_src0; | 579 const SkPMColor* SK_RESTRICT cur_src1 = cur_src0; |
601 if (src_y + 1 < bitmap.height()) | 580 if (src_y + 1 < bitmap.height()) |
602 cur_src1 = bitmap.getAddr32(0, src_y + 1); | 581 cur_src1 = bitmap.getAddr32(0, src_y + 1); |
603 | 582 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 if (bitmap.isNull()) | 629 if (bitmap.isNull()) |
651 return bitmap; | 630 return bitmap; |
652 if (bitmap.isOpaque()) | 631 if (bitmap.isOpaque()) |
653 return bitmap; | 632 return bitmap; |
654 | 633 |
655 const SkImageInfo& opaque_info = | 634 const SkImageInfo& opaque_info = |
656 bitmap.info().makeAlphaType(kOpaque_SkAlphaType); | 635 bitmap.info().makeAlphaType(kOpaque_SkAlphaType); |
657 SkBitmap opaque_bitmap; | 636 SkBitmap opaque_bitmap; |
658 opaque_bitmap.allocPixels(opaque_info); | 637 opaque_bitmap.allocPixels(opaque_info); |
659 | 638 |
660 { | 639 for (int y = 0; y < opaque_bitmap.height(); y++) { |
661 SkAutoLockPixels bitmap_lock(bitmap); | 640 for (int x = 0; x < opaque_bitmap.width(); x++) { |
662 SkAutoLockPixels opaque_bitmap_lock(opaque_bitmap); | 641 uint32_t src_pixel = *bitmap.getAddr32(x, y); |
663 for (int y = 0; y < opaque_bitmap.height(); y++) { | 642 uint32_t* dst_pixel = opaque_bitmap.getAddr32(x, y); |
664 for (int x = 0; x < opaque_bitmap.width(); x++) { | 643 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(src_pixel); |
665 uint32_t src_pixel = *bitmap.getAddr32(x, y); | 644 *dst_pixel = unmultiplied; |
666 uint32_t* dst_pixel = opaque_bitmap.getAddr32(x, y); | |
667 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(src_pixel); | |
668 *dst_pixel = unmultiplied; | |
669 } | |
670 } | 645 } |
671 } | 646 } |
672 | 647 |
673 return opaque_bitmap; | 648 return opaque_bitmap; |
674 } | 649 } |
675 | 650 |
676 // static | 651 // static |
677 SkBitmap SkBitmapOperations::CreateTransposedBitmap(const SkBitmap& image) { | 652 SkBitmap SkBitmapOperations::CreateTransposedBitmap(const SkBitmap& image) { |
678 DCHECK(image.colorType() == kN32_SkColorType); | 653 DCHECK(image.colorType() == kN32_SkColorType); |
679 | 654 |
680 SkBitmap transposed; | 655 SkBitmap transposed; |
681 transposed.allocN32Pixels(image.height(), image.width()); | 656 transposed.allocN32Pixels(image.height(), image.width()); |
682 | 657 |
683 SkAutoLockPixels lock_image(image); | |
684 SkAutoLockPixels lock_transposed(transposed); | |
685 | |
686 for (int y = 0; y < image.height(); ++y) { | 658 for (int y = 0; y < image.height(); ++y) { |
687 uint32_t* image_row = image.getAddr32(0, y); | 659 uint32_t* image_row = image.getAddr32(0, y); |
688 for (int x = 0; x < image.width(); ++x) { | 660 for (int x = 0; x < image.width(); ++x) { |
689 uint32_t* dst = transposed.getAddr32(y, x); | 661 uint32_t* dst = transposed.getAddr32(y, x); |
690 *dst = image_row[x]; | 662 *dst = image_row[x]; |
691 } | 663 } |
692 } | 664 } |
693 | 665 |
694 return transposed; | 666 return transposed; |
695 } | 667 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 canvas.translate(SkFloatToScalar(result.width() * 0.5f), | 755 canvas.translate(SkFloatToScalar(result.width() * 0.5f), |
784 SkFloatToScalar(result.height() * 0.5f)); | 756 SkFloatToScalar(result.height() * 0.5f)); |
785 canvas.rotate(angle); | 757 canvas.rotate(angle); |
786 canvas.translate(-SkFloatToScalar(source.width() * 0.5f), | 758 canvas.translate(-SkFloatToScalar(source.width() * 0.5f), |
787 -SkFloatToScalar(source.height() * 0.5f)); | 759 -SkFloatToScalar(source.height() * 0.5f)); |
788 canvas.drawBitmap(source, 0, 0); | 760 canvas.drawBitmap(source, 0, 0); |
789 canvas.flush(); | 761 canvas.flush(); |
790 | 762 |
791 return result; | 763 return result; |
792 } | 764 } |
OLD | NEW |