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/favicon/select_favicon_frames.h" | 5 #include "chrome/browser/favicon/select_favicon_frames.h" |
6 | 6 |
7 #include "skia/ext/image_operations.h" | 7 #include "skia/ext/image_operations.h" |
8 #include "ui/gfx/image/image.h" | 8 #include "ui/gfx/image/image.h" |
9 #include "ui/gfx/image/image_skia.h" | 9 #include "ui/gfx/image/image_skia.h" |
10 #include "third_party/skia/include/core/SkCanvas.h" | 10 #include "third_party/skia/include/core/SkCanvas.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 SkCanvas canvas(bitmap); | 53 SkCanvas canvas(bitmap); |
54 SkRect dest(SkRect::MakeWH(desired_size, desired_size)); | 54 SkRect dest(SkRect::MakeWH(desired_size, desired_size)); |
55 canvas.drawBitmapRect(contents, NULL, dest); | 55 canvas.drawBitmapRect(contents, NULL, dest); |
56 } | 56 } |
57 | 57 |
58 return bitmap; | 58 return bitmap; |
59 } | 59 } |
60 | 60 |
61 SkBitmap SelectCandidate(const std::vector<SkBitmap>& bitmaps, | 61 SkBitmap SelectCandidate(const std::vector<SkBitmap>& bitmaps, |
62 int desired_size, | 62 int desired_size, |
63 ui::ScaleFactor scale_factor) { | 63 ui::ScaleFactor scale_factor, |
| 64 float* score) { |
64 float scale = GetScaleFactorScale(scale_factor); | 65 float scale = GetScaleFactorScale(scale_factor); |
65 desired_size = static_cast<int>(desired_size * scale + 0.5f); | 66 desired_size = static_cast<int>(desired_size * scale + 0.5f); |
66 | 67 |
67 // Try to find an exact match. | 68 // Try to find an exact match. |
68 for (size_t i = 0; i < bitmaps.size(); ++i) { | 69 for (size_t i = 0; i < bitmaps.size(); ++i) { |
69 if (bitmaps[i].width() == desired_size && | 70 if (bitmaps[i].width() == desired_size && |
70 bitmaps[i].height() == desired_size) { | 71 bitmaps[i].height() == desired_size) { |
| 72 *score = 1; |
71 return bitmaps[i]; | 73 return bitmaps[i]; |
72 } | 74 } |
73 } | 75 } |
74 | 76 |
75 // If that failed, the following special rules apply: | 77 // If that failed, the following special rules apply: |
76 // 1. 17px-24px images are built from 16px images by adding | 78 // 1. 17px-24px images are built from 16px images by adding |
77 // a transparent border. | 79 // a transparent border. |
78 if (desired_size > 16 * scale && desired_size <= 24 * scale) { | 80 if (desired_size > 16 * scale && desired_size <= 24 * scale) { |
79 int source_size = static_cast<int>(16 * scale + 0.5f); | 81 int source_size = static_cast<int>(16 * scale + 0.5f); |
80 for (size_t i = 0; i < bitmaps.size(); ++i) { | 82 for (size_t i = 0; i < bitmaps.size(); ++i) { |
81 if (bitmaps[i].width() == source_size && | 83 if (bitmaps[i].width() == source_size && |
82 bitmaps[i].height() == source_size) { | 84 bitmaps[i].height() == source_size) { |
| 85 *score = 0.2; |
83 return PadWithBorder(bitmaps[i], desired_size, source_size); | 86 return PadWithBorder(bitmaps[i], desired_size, source_size); |
84 } | 87 } |
85 } | 88 } |
86 // Try again, with upsizing the base variant. | 89 // Try again, with upsizing the base variant. |
87 for (size_t i = 0; i < bitmaps.size(); ++i) { | 90 for (size_t i = 0; i < bitmaps.size(); ++i) { |
88 if (bitmaps[i].width() * scale == source_size && | 91 if (bitmaps[i].width() * scale == source_size && |
89 bitmaps[i].height() * scale == source_size) { | 92 bitmaps[i].height() * scale == source_size) { |
| 93 *score = 0.15; |
90 return PadWithBorder(bitmaps[i], desired_size, source_size); | 94 return PadWithBorder(bitmaps[i], desired_size, source_size); |
91 } | 95 } |
92 } | 96 } |
93 } | 97 } |
94 | 98 |
95 // 2. Integer multiples are built using nearest neighbor sampling. | 99 // 2. Integer multiples are built using nearest neighbor sampling. |
96 // 3. Else, use Lancosz scaling: | 100 // 3. Else, use Lancosz scaling: |
97 // b) If available, from the next bigger variant. | 101 // b) If available, from the next bigger variant. |
98 int candidate = -1; | 102 int candidate = -1; |
99 int min_area = INT_MAX; | 103 int min_area = INT_MAX; |
100 for (size_t i = 0; i < bitmaps.size(); ++i) { | 104 for (size_t i = 0; i < bitmaps.size(); ++i) { |
101 int area = bitmaps[i].width() * bitmaps[i].height(); | 105 int area = bitmaps[i].width() * bitmaps[i].height(); |
102 if (bitmaps[i].width() > desired_size && | 106 if (bitmaps[i].width() > desired_size && |
103 bitmaps[i].height() > desired_size && | 107 bitmaps[i].height() > desired_size && |
104 (candidate == -1 || area < min_area)) { | 108 (candidate == -1 || area < min_area)) { |
105 candidate = i; | 109 candidate = i; |
106 min_area = area; | 110 min_area = area; |
107 } | 111 } |
108 } | 112 } |
| 113 *score = 0.1; |
109 // c) Else, from the biggest smaller variant. | 114 // c) Else, from the biggest smaller variant. |
110 if (candidate == -1) | 115 if (candidate == -1) { |
| 116 *score = 0; |
111 candidate = BiggestCandidate(bitmaps); | 117 candidate = BiggestCandidate(bitmaps); |
| 118 } |
112 | 119 |
113 const SkBitmap& bitmap = bitmaps[candidate]; | 120 const SkBitmap& bitmap = bitmaps[candidate]; |
114 bool is_integer_multiple = desired_size % bitmap.width() == 0 && | 121 bool is_integer_multiple = desired_size % bitmap.width() == 0 && |
115 desired_size % bitmap.height() == 0; | 122 desired_size % bitmap.height() == 0; |
116 if (is_integer_multiple) | 123 if (is_integer_multiple) |
117 return SampleNearestNeighbor(bitmap, desired_size); | 124 return SampleNearestNeighbor(bitmap, desired_size); |
118 return skia::ImageOperations::Resize( | 125 return skia::ImageOperations::Resize( |
119 bitmap, skia::ImageOperations::RESIZE_LANCZOS3, | 126 bitmap, skia::ImageOperations::RESIZE_LANCZOS3, |
120 desired_size, desired_size); | 127 desired_size, desired_size); |
121 } | 128 } |
122 | 129 |
123 } // namespace | 130 } // namespace |
124 | 131 |
125 gfx::ImageSkia SelectFaviconFrames( | 132 gfx::ImageSkia SelectFaviconFrames( |
126 const std::vector<SkBitmap>& bitmaps, | 133 const std::vector<SkBitmap>& bitmaps, |
127 const std::vector<ui::ScaleFactor>& scale_factors, | 134 const std::vector<ui::ScaleFactor>& scale_factors, |
128 int desired_size) { | 135 int desired_size, |
| 136 float* match_score) { |
129 gfx::ImageSkia multi_image; | 137 gfx::ImageSkia multi_image; |
130 if (bitmaps.empty()) | 138 if (bitmaps.empty()) |
131 return multi_image; | 139 return multi_image; |
132 | 140 |
133 if (desired_size == 0) { | 141 if (desired_size == 0) { |
134 // Just return the biggest image available. | 142 // Just return the biggest image available. |
135 size_t max_index = BiggestCandidate(bitmaps); | 143 size_t max_index = BiggestCandidate(bitmaps); |
136 multi_image.AddRepresentation( | 144 multi_image.AddRepresentation( |
137 gfx::ImageSkiaRep(bitmaps[max_index], ui::SCALE_FACTOR_100P)); | 145 gfx::ImageSkiaRep(bitmaps[max_index], ui::SCALE_FACTOR_100P)); |
| 146 if (match_score) |
| 147 *match_score = 0.8; |
138 return multi_image; | 148 return multi_image; |
139 } | 149 } |
140 | 150 |
| 151 float total_score = 0; |
141 for (size_t i = 0; i < scale_factors.size(); ++i) { | 152 for (size_t i = 0; i < scale_factors.size(); ++i) { |
| 153 float score; |
142 multi_image.AddRepresentation(gfx::ImageSkiaRep( | 154 multi_image.AddRepresentation(gfx::ImageSkiaRep( |
143 SelectCandidate(bitmaps, desired_size, scale_factors[i]), | 155 SelectCandidate(bitmaps, desired_size, scale_factors[i], &score), |
144 scale_factors[i])); | 156 scale_factors[i])); |
| 157 total_score += score; |
145 } | 158 } |
146 | 159 |
| 160 if (match_score) |
| 161 *match_score = total_score / scale_factors.size(); |
147 return multi_image; | 162 return multi_image; |
148 } | 163 } |
OLD | NEW |