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 "chrome/browser/thumbnails/content_analysis.h" | 5 #include "chrome/browser/thumbnails/content_analysis.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <cmath> | 11 #include <cmath> |
12 #include <cstdlib> | 12 #include <cstdlib> |
13 #include <functional> | 13 #include <functional> |
14 #include <limits> | 14 #include <limits> |
15 #include <memory> | 15 #include <memory> |
16 #include <numeric> | 16 #include <numeric> |
17 #include <vector> | 17 #include <vector> |
18 | 18 |
19 #include "skia/ext/platform_canvas.h" | 19 #include "skia/ext/platform_canvas.h" |
20 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
21 #include "third_party/skia/include/core/SkBitmap.h" | 21 #include "third_party/skia/include/core/SkBitmap.h" |
22 #include "third_party/skia/include/core/SkColor.h" | 22 #include "third_party/skia/include/core/SkColor.h" |
23 #include "ui/gfx/canvas.h" | 23 #include "ui/gfx/canvas.h" |
24 #include "ui/gfx/color_analysis.h" | 24 #include "ui/gfx/color_analysis.h" |
25 #include "ui/gfx/color_utils.h" | 25 #include "ui/gfx/color_utils.h" |
26 #include "ui/gfx/geometry/rect.h" | 26 #include "ui/gfx/geometry/rect.h" |
| 27 #include "ui/gfx/geometry/rect_f.h" |
27 #include "ui/gfx/geometry/size.h" | 28 #include "ui/gfx/geometry/size.h" |
28 #include "ui/gfx/image/image.h" | 29 #include "ui/gfx/image/image.h" |
29 | 30 |
30 namespace { | 31 namespace { |
31 | 32 |
32 #ifndef M_PI | 33 #ifndef M_PI |
33 #define M_PI 3.14159265358979323846 | 34 #define M_PI 3.14159265358979323846 |
34 #endif | 35 #endif |
35 | 36 |
36 unsigned long ImagePixelSum(const SkBitmap& bitmap, const gfx::Rect& rect) { | 37 unsigned long ImagePixelSum(const SkBitmap& bitmap, const gfx::Rect& rect) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 data_sum = ImagePixelSum(reduced_color, echo_rect); | 121 data_sum = ImagePixelSum(reduced_color, echo_rect); |
121 all_sum = ImagePixelSum(reduced_color, gfx::Rect(800, 600)); | 122 all_sum = ImagePixelSum(reduced_color, gfx::Rect(800, 600)); |
122 EXPECT_GT(data_sum, 0U); | 123 EXPECT_GT(data_sum, 0U); |
123 EXPECT_EQ(data_sum, all_sum); | 124 EXPECT_EQ(data_sum, all_sum); |
124 } | 125 } |
125 | 126 |
126 TEST_F(ThumbnailContentAnalysisTest, ApplyGradientMagnitudeOnFrame) { | 127 TEST_F(ThumbnailContentAnalysisTest, ApplyGradientMagnitudeOnFrame) { |
127 gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); | 128 gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); |
128 | 129 |
129 // The image consists of a single white block in the centre. | 130 // The image consists of a single white block in the centre. |
130 gfx::Rect draw_rect(300, 200, 200, 200); | 131 gfx::RectF draw_rect(300, 200, 200, 200); |
131 canvas.FillRect(gfx::Rect(0, 0, 800, 600), SkColorSetRGB(0, 0, 0)); | 132 canvas.FillRect(gfx::Rect(0, 0, 800, 600), SkColorSetRGB(0, 0, 0)); |
132 canvas.DrawRect(draw_rect, SkColorSetRGB(255, 255, 255)); | 133 canvas.DrawRect(draw_rect, SkColorSetRGB(255, 255, 255)); |
133 | 134 |
134 SkBitmap source = canvas.GetBitmap(); | 135 SkBitmap source = canvas.GetBitmap(); |
135 | 136 |
136 SkBitmap reduced_color; | 137 SkBitmap reduced_color; |
137 reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), | 138 reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), |
138 source.height())); | 139 source.height())); |
139 | 140 |
140 gfx::Vector3dF transform(0.299f, 0.587f, 0.114f); | 141 gfx::Vector3dF transform(0.299f, 0.587f, 0.114f); |
(...skipping 16 matching lines...) Expand all Loading... |
157 unsigned long all_sum = ImagePixelSum(reduced_color, gfx::Rect(800, 600)); | 158 unsigned long all_sum = ImagePixelSum(reduced_color, gfx::Rect(800, 600)); |
158 EXPECT_GT(data_sum, 0U); | 159 EXPECT_GT(data_sum, 0U); |
159 EXPECT_EQ(data_sum, all_sum); | 160 EXPECT_EQ(data_sum, all_sum); |
160 EXPECT_EQ(ImagePixelSum(reduced_color, inner_rect), 0U); | 161 EXPECT_EQ(ImagePixelSum(reduced_color, inner_rect), 0U); |
161 } | 162 } |
162 | 163 |
163 TEST_F(ThumbnailContentAnalysisTest, ExtractImageProfileInformation) { | 164 TEST_F(ThumbnailContentAnalysisTest, ExtractImageProfileInformation) { |
164 gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); | 165 gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); |
165 | 166 |
166 // The image consists of a white frame drawn in the centre. | 167 // The image consists of a white frame drawn in the centre. |
167 gfx::Rect draw_rect(100, 100, 200, 100); | 168 gfx::RectF draw_rect(100, 100, 200, 100); |
168 gfx::Rect image_rect(0, 0, 800, 600); | 169 gfx::Rect image_rect(0, 0, 800, 600); |
169 canvas.FillRect(image_rect, SkColorSetRGB(0, 0, 0)); | 170 canvas.FillRect(image_rect, SkColorSetRGB(0, 0, 0)); |
170 canvas.DrawRect(draw_rect, SkColorSetRGB(255, 255, 255)); | 171 canvas.DrawRect(draw_rect, SkColorSetRGB(255, 255, 255)); |
171 | 172 |
172 SkBitmap source = canvas.GetBitmap(); | 173 SkBitmap source = canvas.GetBitmap(); |
173 SkBitmap reduced_color; | 174 SkBitmap reduced_color; |
174 reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), | 175 reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), |
175 source.height())); | 176 source.height())); |
176 | 177 |
177 gfx::Vector3dF transform(1, 0, 0); | 178 gfx::Vector3dF transform(1, 0, 0); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 } | 223 } |
223 | 224 |
224 TEST_F(ThumbnailContentAnalysisTest, | 225 TEST_F(ThumbnailContentAnalysisTest, |
225 ExtractImageProfileInformationWithClosing) { | 226 ExtractImageProfileInformationWithClosing) { |
226 gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); | 227 gfx::Canvas canvas(gfx::Size(800, 600), 1.0f, true); |
227 | 228 |
228 // The image consists of a two white frames drawn side by side, with a | 229 // The image consists of a two white frames drawn side by side, with a |
229 // single-pixel vertical gap in between. | 230 // single-pixel vertical gap in between. |
230 gfx::Rect image_rect(0, 0, 800, 600); | 231 gfx::Rect image_rect(0, 0, 800, 600); |
231 canvas.FillRect(image_rect, SkColorSetRGB(0, 0, 0)); | 232 canvas.FillRect(image_rect, SkColorSetRGB(0, 0, 0)); |
232 canvas.DrawRect(gfx::Rect(300, 250, 99, 100), SkColorSetRGB(255, 255, 255)); | 233 canvas.DrawRect(gfx::RectF(300, 250, 99, 100), SkColorSetRGB(255, 255, 255)); |
233 canvas.DrawRect(gfx::Rect(401, 250, 99, 100), SkColorSetRGB(255, 255, 255)); | 234 canvas.DrawRect(gfx::RectF(401, 250, 99, 100), SkColorSetRGB(255, 255, 255)); |
234 | 235 |
235 SkBitmap source = canvas.GetBitmap(); | 236 SkBitmap source = canvas.GetBitmap(); |
236 SkBitmap reduced_color; | 237 SkBitmap reduced_color; |
237 reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), | 238 reduced_color.allocPixels(SkImageInfo::MakeA8(source.width(), |
238 source.height())); | 239 source.height())); |
239 | 240 |
240 gfx::Vector3dF transform(1, 0, 0); | 241 gfx::Vector3dF transform(1, 0, 0); |
241 EXPECT_TRUE(color_utils::ApplyColorReduction( | 242 EXPECT_TRUE(color_utils::ApplyColorReduction( |
242 source, transform, true, &reduced_color)); | 243 source, transform, true, &reduced_color)); |
243 std::vector<float> column_profile; | 244 std::vector<float> column_profile; |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 | 615 |
615 // 'Fine print' at the bottom. | 616 // 'Fine print' at the bottom. |
616 const int fine_print = 8; | 617 const int fine_print = 8; |
617 const SkColor print_color = SkColorSetRGB(45, 30, 30); | 618 const SkColor print_color = SkColorSetRGB(45, 30, 30); |
618 for (int y = footer_rect.y() + fine_print; | 619 for (int y = footer_rect.y() + fine_print; |
619 y < footer_rect.bottom() - fine_print; | 620 y < footer_rect.bottom() - fine_print; |
620 y += 2 * fine_print) { | 621 y += 2 * fine_print) { |
621 for (int x = footer_rect.x() + fine_print; | 622 for (int x = footer_rect.x() + fine_print; |
622 x < footer_rect.right() - fine_print; | 623 x < footer_rect.right() - fine_print; |
623 x += 2 * fine_print) { | 624 x += 2 * fine_print) { |
624 canvas.DrawRect(gfx::Rect(x, y, fine_print, fine_print), print_color); | 625 canvas.DrawRect(gfx::RectF(x, y, fine_print, fine_print), print_color); |
625 } | 626 } |
626 } | 627 } |
627 | 628 |
628 // Blocky content at the top. | 629 // Blocky content at the top. |
629 const int block_size = header_rect.height() - margin_vertical; | 630 const int block_size = header_rect.height() - margin_vertical; |
630 for (int x = header_rect.x() + margin_horizontal; | 631 for (int x = header_rect.x() + margin_horizontal; |
631 x < header_rect.right() - block_size; | 632 x < header_rect.right() - block_size; |
632 x += block_size + margin_horizontal) { | 633 x += block_size + margin_horizontal) { |
633 const int half_block = block_size / 2 - 5; | 634 const int half_block = block_size / 2 - 5; |
634 const SkColor block_color = SkColorSetRGB(255, 255, 255); | 635 const SkColor block_color = SkColorSetRGB(255, 255, 255); |
635 const int y = header_rect.y() + margin_vertical / 2; | 636 const int y = header_rect.y() + margin_vertical / 2; |
636 int second_col = x + half_block + 10; | 637 int second_col = x + half_block + 10; |
637 int second_row = y + half_block + 10; | 638 int second_row = y + half_block + 10; |
638 canvas.FillRect(gfx::Rect(x, y, half_block, block_size), block_color); | 639 canvas.FillRect(gfx::Rect(x, y, half_block, block_size), block_color); |
639 canvas.FillRect(gfx::Rect(second_col, y, half_block, half_block), | 640 canvas.FillRect(gfx::Rect(second_col, y, half_block, half_block), |
640 block_color); | 641 block_color); |
641 canvas.FillRect(gfx::Rect(second_col, second_row, half_block, half_block), | 642 canvas.FillRect(gfx::Rect(second_col, second_row, half_block, half_block), |
642 block_color); | 643 block_color); |
643 } | 644 } |
644 | 645 |
645 // Now the main body. Mostly text with some 'pictures'. | 646 // Now the main body. Mostly text with some 'pictures'. |
646 for (int y = body_rect.y() + fine_print; | 647 for (int y = body_rect.y() + fine_print; |
647 y < body_rect.bottom() - fine_print; | 648 y < body_rect.bottom() - fine_print; |
648 y += 2 * fine_print) { | 649 y += 2 * fine_print) { |
649 for (int x = body_rect.x() + fine_print; | 650 for (int x = body_rect.x() + fine_print; |
650 x < body_rect.right() - fine_print; | 651 x < body_rect.right() - fine_print; |
651 x += 2 * fine_print) { | 652 x += 2 * fine_print) { |
652 canvas.DrawRect(gfx::Rect(x, y, fine_print, fine_print), print_color); | 653 canvas.DrawRect(gfx::RectF(x, y, fine_print, fine_print), print_color); |
653 } | 654 } |
654 } | 655 } |
655 | 656 |
656 for (int line = 0; line < 3; ++line) { | 657 for (int line = 0; line < 3; ++line) { |
657 int alignment = line % 2; | 658 int alignment = line % 2; |
658 const int y = body_rect.y() + | 659 const int y = body_rect.y() + |
659 body_rect.height() / 3 * line + margin_vertical; | 660 body_rect.height() / 3 * line + margin_vertical; |
660 const int x = body_rect.x() + | 661 const int x = body_rect.x() + |
661 alignment * body_rect.width() / 2 + margin_vertical; | 662 alignment * body_rect.width() / 2 + margin_vertical; |
662 gfx::Rect pict_rect(x, y, | 663 gfx::Rect pict_rect(x, y, body_rect.width() / 2 - 2 * margin_vertical, |
663 body_rect.width() / 2 - 2 * margin_vertical, | |
664 body_rect.height() / 3 - 2 * margin_vertical); | 664 body_rect.height() / 3 - 2 * margin_vertical); |
665 canvas.FillRect(pict_rect, SkColorSetRGB(255, 255, 255)); | 665 canvas.FillRect(pict_rect, SkColorSetRGB(255, 255, 255)); |
666 canvas.DrawRect(pict_rect, SkColorSetRGB(0, 0, 0)); | 666 canvas.DrawRect(gfx::RectF(pict_rect), SkColorSetRGB(0, 0, 0)); |
667 } | 667 } |
668 | 668 |
669 SkBitmap source = canvas.GetBitmap(); | 669 SkBitmap source = canvas.GetBitmap(); |
670 | 670 |
671 SkBitmap result = CreateRetargetedThumbnailImage( | 671 SkBitmap result = CreateRetargetedThumbnailImage( |
672 source, gfx::Size(424, 264), 2.5); | 672 source, gfx::Size(424, 264), 2.5); |
673 EXPECT_FALSE(result.empty()); | 673 EXPECT_FALSE(result.empty()); |
674 | 674 |
675 // Given the nature of computation We can't really assert much here about the | 675 // Given the nature of computation We can't really assert much here about the |
676 // image itself. We know it should have been computed, should be smaller than | 676 // image itself. We know it should have been computed, should be smaller than |
677 // the original and it must not be zero. | 677 // the original and it must not be zero. |
678 EXPECT_LT(result.width(), image_size.width()); | 678 EXPECT_LT(result.width(), image_size.width()); |
679 EXPECT_LT(result.height(), image_size.height()); | 679 EXPECT_LT(result.height(), image_size.height()); |
680 | 680 |
681 int histogram[256] = {}; | 681 int histogram[256] = {}; |
682 color_utils::BuildLumaHistogram(result, histogram); | 682 color_utils::BuildLumaHistogram(result, histogram); |
683 int non_zero_color_count = std::count_if( | 683 int non_zero_color_count = std::count_if( |
684 histogram, histogram + 256, [](int value) { return value > 0; }); | 684 histogram, histogram + 256, [](int value) { return value > 0; }); |
685 EXPECT_GT(non_zero_color_count, 4); | 685 EXPECT_GT(non_zero_color_count, 4); |
686 | 686 |
687 } | 687 } |
688 | 688 |
689 } // namespace thumbnailing_utils | 689 } // namespace thumbnailing_utils |
OLD | NEW |