OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/favicon_base/select_favicon_frames.h" | 5 #include "components/favicon_base/select_favicon_frames.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "skia/ext/image_operations.h" | 10 #include "skia/ext/image_operations.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 canvas.drawBitmapRect(contents, NULL, dest); | 41 canvas.drawBitmapRect(contents, NULL, dest); |
42 } | 42 } |
43 | 43 |
44 return bitmap; | 44 return bitmap; |
45 } | 45 } |
46 | 46 |
47 enum ResizeMethod { NONE, SAMPLE_NEAREST_NEIGHBOUR, LANCZOS }; | 47 enum ResizeMethod { NONE, SAMPLE_NEAREST_NEIGHBOUR, LANCZOS }; |
48 | 48 |
49 size_t GetCandidateIndexWithBestScore( | 49 size_t GetCandidateIndexWithBestScore( |
50 const std::vector<gfx::Size>& candidate_sizes_in_pixel, | 50 const std::vector<gfx::Size>& candidate_sizes_in_pixel, |
51 ui::ScaleFactor scale_factor, | 51 float scale, |
52 int desired_size_in_dip, | 52 int desired_size_in_dip, |
53 float* score, | 53 float* score, |
54 ResizeMethod* resize_method) { | 54 ResizeMethod* resize_method) { |
55 DCHECK_NE(desired_size_in_dip, 0); | 55 DCHECK_NE(desired_size_in_dip, 0); |
56 | 56 |
57 float scale = ui::GetScaleForScaleFactor(scale_factor); | |
58 int desired_size_in_pixel = | 57 int desired_size_in_pixel = |
59 static_cast<int>(desired_size_in_dip * scale + 0.5f); | 58 static_cast<int>(desired_size_in_dip * scale + 0.5f); |
60 | 59 |
61 // Try to find an exact match. | 60 // Try to find an exact match. |
62 for (size_t i = 0; i < candidate_sizes_in_pixel.size(); ++i) { | 61 for (size_t i = 0; i < candidate_sizes_in_pixel.size(); ++i) { |
63 if (candidate_sizes_in_pixel[i].width() == desired_size_in_pixel && | 62 if (candidate_sizes_in_pixel[i].width() == desired_size_in_pixel && |
64 candidate_sizes_in_pixel[i].height() == desired_size_in_pixel) { | 63 candidate_sizes_in_pixel[i].height() == desired_size_in_pixel) { |
65 *score = 1; | 64 *score = 1; |
66 *resize_method = NONE; | 65 *resize_method = NONE; |
67 return i; | 66 return i; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 return candidate_index; | 120 return candidate_index; |
122 } | 121 } |
123 | 122 |
124 // Represents the index of the best candidate for a |scale_factor| from the | 123 // Represents the index of the best candidate for a |scale_factor| from the |
125 // |candidate_sizes| passed into GetCandidateIndicesWithBestScores(). | 124 // |candidate_sizes| passed into GetCandidateIndicesWithBestScores(). |
126 struct SelectionResult { | 125 struct SelectionResult { |
127 // index in |candidate_sizes| of the best candidate. | 126 // index in |candidate_sizes| of the best candidate. |
128 size_t index; | 127 size_t index; |
129 | 128 |
130 // The ScaleFactor for which |index| is the best candidate. | 129 // The ScaleFactor for which |index| is the best candidate. |
131 ui::ScaleFactor scale_factor; | 130 float scale; |
132 | 131 |
133 // How the bitmap data that the bitmap with |candidate_sizes[index]| should | 132 // How the bitmap data that the bitmap with |candidate_sizes[index]| should |
134 // be resized for displaying in the UI. | 133 // be resized for displaying in the UI. |
135 ResizeMethod resize_method; | 134 ResizeMethod resize_method; |
136 }; | 135 }; |
137 | 136 |
138 void GetCandidateIndicesWithBestScores( | 137 void GetCandidateIndicesWithBestScores( |
139 const std::vector<gfx::Size>& candidate_sizes, | 138 const std::vector<gfx::Size>& candidate_sizes, |
140 const std::vector<ui::ScaleFactor>& scale_factors, | 139 const std::vector<float>& scales, |
141 int desired_size, | 140 int desired_size, |
142 float* match_score, | 141 float* match_score, |
143 std::vector<SelectionResult>* results) { | 142 std::vector<SelectionResult>* results) { |
144 if (candidate_sizes.empty()) { | 143 if (candidate_sizes.empty()) { |
145 if (match_score) | 144 if (match_score) |
146 *match_score = 0.0f; | 145 *match_score = 0.0f; |
147 return; | 146 return; |
148 } | 147 } |
149 | 148 |
150 if (desired_size == 0) { | 149 if (desired_size == 0) { |
151 // Just return the biggest image available. | 150 // Just return the biggest image available. |
152 SelectionResult result; | 151 SelectionResult result; |
153 result.index = BiggestCandidate(candidate_sizes); | 152 result.index = BiggestCandidate(candidate_sizes); |
154 result.scale_factor = ui::SCALE_FACTOR_100P; | 153 result.scale = 1.0f; |
155 result.resize_method = NONE; | 154 result.resize_method = NONE; |
156 results->push_back(result); | 155 results->push_back(result); |
157 if (match_score) | 156 if (match_score) |
158 *match_score = 1.0f; | 157 *match_score = 1.0f; |
159 return; | 158 return; |
160 } | 159 } |
161 | 160 |
162 float total_score = 0; | 161 float total_score = 0; |
163 for (size_t i = 0; i < scale_factors.size(); ++i) { | 162 for (size_t i = 0; i < scales.size(); ++i) { |
164 float score; | 163 float score; |
165 SelectionResult result; | 164 SelectionResult result; |
166 result.scale_factor = scale_factors[i]; | 165 result.scale = scales[i]; |
167 result.index = GetCandidateIndexWithBestScore(candidate_sizes, | 166 result.index = GetCandidateIndexWithBestScore(candidate_sizes, |
168 result.scale_factor, | 167 result.scale, |
169 desired_size, | 168 desired_size, |
170 &score, | 169 &score, |
171 &result.resize_method); | 170 &result.resize_method); |
172 results->push_back(result); | 171 results->push_back(result); |
173 total_score += score; | 172 total_score += score; |
174 } | 173 } |
175 | 174 |
176 if (match_score) | 175 if (match_score) |
177 *match_score = total_score / scale_factors.size(); | 176 *match_score = total_score / scales.size(); |
178 } | 177 } |
179 | 178 |
180 // Resize |source_bitmap| using |resize_method|. | 179 // Resize |source_bitmap| using |resize_method|. |
181 SkBitmap GetResizedBitmap(const SkBitmap& source_bitmap, | 180 SkBitmap GetResizedBitmap(const SkBitmap& source_bitmap, |
182 int desired_size_in_dip, | 181 int desired_size_in_dip, |
183 ui::ScaleFactor scale_factor, | 182 float scale, |
184 ResizeMethod resize_method) { | 183 ResizeMethod resize_method) { |
185 float scale = ui::GetScaleForScaleFactor(scale_factor); | |
186 int desired_size_in_pixel = | 184 int desired_size_in_pixel = |
187 static_cast<int>(desired_size_in_dip * scale + 0.5f); | 185 static_cast<int>(desired_size_in_dip * scale + 0.5f); |
188 | 186 |
189 switch (resize_method) { | 187 switch (resize_method) { |
190 case NONE: | 188 case NONE: |
191 return source_bitmap; | 189 return source_bitmap; |
192 case SAMPLE_NEAREST_NEIGHBOUR: | 190 case SAMPLE_NEAREST_NEIGHBOUR: |
193 return SampleNearestNeighbor(source_bitmap, desired_size_in_pixel); | 191 return SampleNearestNeighbor(source_bitmap, desired_size_in_pixel); |
194 case LANCZOS: | 192 case LANCZOS: |
195 return skia::ImageOperations::Resize( | 193 return skia::ImageOperations::Resize( |
196 source_bitmap, | 194 source_bitmap, |
197 skia::ImageOperations::RESIZE_LANCZOS3, | 195 skia::ImageOperations::RESIZE_LANCZOS3, |
198 desired_size_in_pixel, | 196 desired_size_in_pixel, |
199 desired_size_in_pixel); | 197 desired_size_in_pixel); |
200 } | 198 } |
201 return source_bitmap; | 199 return source_bitmap; |
202 } | 200 } |
203 | 201 |
204 } // namespace | 202 } // namespace |
205 | 203 |
206 const float kSelectFaviconFramesInvalidScore = -1.0f; | 204 const float kSelectFaviconFramesInvalidScore = -1.0f; |
207 | 205 |
208 gfx::ImageSkia SelectFaviconFrames( | 206 gfx::ImageSkia SelectFaviconFrames(const std::vector<SkBitmap>& bitmaps, |
209 const std::vector<SkBitmap>& bitmaps, | 207 const std::vector<gfx::Size>& original_sizes, |
210 const std::vector<gfx::Size>& original_sizes, | 208 const std::vector<float>& scales, |
211 const std::vector<ui::ScaleFactor>& scale_factors, | 209 int desired_size, |
212 int desired_size, | 210 float* match_score) { |
213 float* match_score) { | |
214 std::vector<SelectionResult> results; | 211 std::vector<SelectionResult> results; |
215 GetCandidateIndicesWithBestScores( | 212 GetCandidateIndicesWithBestScores( |
216 original_sizes, scale_factors, desired_size, match_score, &results); | 213 original_sizes, scales, desired_size, match_score, &results); |
217 | 214 |
218 gfx::ImageSkia multi_image; | 215 gfx::ImageSkia multi_image; |
219 for (size_t i = 0; i < results.size(); ++i) { | 216 for (size_t i = 0; i < results.size(); ++i) { |
220 const SelectionResult& result = results[i]; | 217 const SelectionResult& result = results[i]; |
221 SkBitmap resized_bitmap = GetResizedBitmap(bitmaps[result.index], | 218 SkBitmap resized_bitmap = GetResizedBitmap(bitmaps[result.index], |
222 desired_size, | 219 desired_size, |
223 result.scale_factor, | 220 result.scale, |
224 result.resize_method); | 221 result.resize_method); |
225 multi_image.AddRepresentation(gfx::ImageSkiaRep( | 222 multi_image.AddRepresentation( |
226 resized_bitmap, ui::GetScaleForScaleFactor(result.scale_factor))); | 223 gfx::ImageSkiaRep(resized_bitmap, result.scale)); |
227 } | 224 } |
228 return multi_image; | 225 return multi_image; |
229 } | 226 } |
230 | 227 |
231 void SelectFaviconFrameIndices( | 228 void SelectFaviconFrameIndices(const std::vector<gfx::Size>& frame_pixel_sizes, |
232 const std::vector<gfx::Size>& frame_pixel_sizes, | 229 const std::vector<float>& scales, |
233 const std::vector<ui::ScaleFactor>& scale_factors, | 230 int desired_size, |
234 int desired_size, | 231 std::vector<size_t>* best_indices, |
235 std::vector<size_t>* best_indices, | 232 float* match_score) { |
236 float* match_score) { | |
237 std::vector<SelectionResult> results; | 233 std::vector<SelectionResult> results; |
238 GetCandidateIndicesWithBestScores( | 234 GetCandidateIndicesWithBestScores( |
239 frame_pixel_sizes, scale_factors, desired_size, match_score, &results); | 235 frame_pixel_sizes, scales, desired_size, match_score, &results); |
240 | 236 |
241 std::set<size_t> already_added; | 237 std::set<size_t> already_added; |
242 for (size_t i = 0; i < results.size(); ++i) { | 238 for (size_t i = 0; i < results.size(); ++i) { |
243 size_t index = results[i].index; | 239 size_t index = results[i].index; |
244 // GetCandidateIndicesWithBestScores() will return duplicate indices if the | 240 // GetCandidateIndicesWithBestScores() will return duplicate indices if the |
245 // bitmap data with |frame_pixel_sizes[index]| should be used for multiple | 241 // bitmap data with |frame_pixel_sizes[index]| should be used for multiple |
246 // scale factors. Remove duplicates here such that |best_indices| contains | 242 // scale factors. Remove duplicates here such that |best_indices| contains |
247 // no duplicates. | 243 // no duplicates. |
248 if (already_added.find(index) == already_added.end()) { | 244 if (already_added.find(index) == already_added.end()) { |
249 already_added.insert(index); | 245 already_added.insert(index); |
250 best_indices->push_back(index); | 246 best_indices->push_back(index); |
251 } | 247 } |
252 } | 248 } |
253 } | 249 } |
OLD | NEW |