Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(329)

Side by Side Diff: components/favicon_base/favicon_util.cc

Issue 2739173002: Always select best favicon bitmap (Closed)
Patch Set: WIP. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/favicon_util.h" 5 #include "components/favicon_base/favicon_util.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
(...skipping 12 matching lines...) Expand all
23 #include "ui/gfx/image/image_png_rep.h" 23 #include "ui/gfx/image/image_png_rep.h"
24 #include "ui/gfx/image/image_skia.h" 24 #include "ui/gfx/image/image_skia.h"
25 25
26 #if defined(OS_MACOSX) && !defined(OS_IOS) 26 #if defined(OS_MACOSX) && !defined(OS_IOS)
27 #include "base/mac/mac_util.h" 27 #include "base/mac/mac_util.h"
28 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 28 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
29 29
30 namespace favicon_base { 30 namespace favicon_base {
31 namespace { 31 namespace {
32 32
33 gfx::Image SelectLargestFrame(
34 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data) {
35 if (png_data.empty())
36 return gfx::Image();
37
38 int maximum_area = 0;
39 scoped_refptr<base::RefCountedMemory> best_candidate;
40 for (size_t i = 0; i < png_data.size(); ++i) {
41 int area = png_data[i].pixel_size.GetArea();
42 if (area > maximum_area) {
43 maximum_area = area;
44 best_candidate = png_data[i].bitmap_data;
45 }
46 }
47 return gfx::Image({gfx::ImagePNGRep(best_candidate, 1.0f)});
48 }
49
33 // Creates image reps of DIP size |favicon_size| for the subset of 50 // Creates image reps of DIP size |favicon_size| for the subset of
34 // |favicon_scales| for which the image reps can be created without resizing 51 // |favicon_scales| for which the image reps can be created without resizing
35 // or decoding the bitmap data. 52 // or decoding the bitmap data.
36 std::vector<gfx::ImagePNGRep> SelectFaviconFramesFromPNGsWithoutResizing( 53 std::vector<gfx::ImagePNGRep> SelectFaviconFramesFromPNGsWithoutResizing(
37 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, 54 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data,
38 const std::vector<float>& favicon_scales, 55 std::map<int, float> desired_pixel_sizes) {
39 int favicon_size) {
40 TRACE_EVENT0("browser", 56 TRACE_EVENT0("browser",
41 "FaviconUtil::SelectFaviconFramesFromPNGsWithoutResizing"); 57 "FaviconUtil::SelectFaviconFramesFromPNGsWithoutResizing");
42 std::vector<gfx::ImagePNGRep> png_reps; 58 std::vector<gfx::ImagePNGRep> png_reps;
43 if (png_data.empty()) 59 if (png_data.empty())
44 return png_reps; 60 return png_reps;
45 61
46 // A |favicon_size| of 0 indicates that the largest frame is desired.
47 if (favicon_size == 0) {
48 int maximum_area = 0;
49 scoped_refptr<base::RefCountedMemory> best_candidate;
50 for (size_t i = 0; i < png_data.size(); ++i) {
51 int area = png_data[i].pixel_size.GetArea();
52 if (area > maximum_area) {
53 maximum_area = area;
54 best_candidate = png_data[i].bitmap_data;
55 }
56 }
57 png_reps.push_back(gfx::ImagePNGRep(best_candidate, 1.0f));
58 return png_reps;
59 }
60
61 // Build a map which will be used to determine the scale used to
62 // create a bitmap with given pixel size.
63 std::map<int, float> desired_pixel_sizes;
64 for (size_t i = 0; i < favicon_scales.size(); ++i) {
65 int pixel_size =
66 static_cast<int>(std::ceil(favicon_size * favicon_scales[i]));
67 desired_pixel_sizes[pixel_size] = favicon_scales[i];
68 }
69
70 for (size_t i = 0; i < png_data.size(); ++i) { 62 for (size_t i = 0; i < png_data.size(); ++i) {
71 if (!png_data[i].is_valid()) 63 if (!png_data[i].is_valid())
72 continue; 64 continue;
73 65
74 const gfx::Size& pixel_size = png_data[i].pixel_size; 66 const gfx::Size& pixel_size = png_data[i].pixel_size;
75 if (pixel_size.width() != pixel_size.height()) 67 if (pixel_size.width() != pixel_size.height())
76 continue; 68 continue;
77 69
78 std::map<int, float>::iterator it = 70 std::map<int, float>::iterator it =
79 desired_pixel_sizes.find(pixel_size.width()); 71 desired_pixel_sizes.find(pixel_size.width());
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 image->SetSourceColorSpace(base::mac::GetSystemColorSpace()); 156 image->SetSourceColorSpace(base::mac::GetSystemColorSpace());
165 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 157 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
166 } 158 }
167 159
168 gfx::Image SelectFaviconFramesFromPNGs( 160 gfx::Image SelectFaviconFramesFromPNGs(
169 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, 161 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data,
170 const std::vector<float>& favicon_scales, 162 const std::vector<float>& favicon_scales,
171 int favicon_size) { 163 int favicon_size) {
172 TRACE_EVENT0("browser", "FaviconUtil::SelectFaviconFramesFromPNGs"); 164 TRACE_EVENT0("browser", "FaviconUtil::SelectFaviconFramesFromPNGs");
173 165
166 // A |favicon_size| of 0 indicates that the largest frame is desired.
167 if (favicon_size == 0) {
168 return SelectLargestFrame(png_data);
169 }
170
171 // Build a map which will be used to determine the scale used to
172 // create a bitmap with given pixel size.
173 std::map<int, float> desired_pixel_sizes;
174 for (size_t i = 0; i < favicon_scales.size(); ++i) {
175 int pixel_size =
176 static_cast<int>(std::ceil(favicon_size * favicon_scales[i]));
177 desired_pixel_sizes[pixel_size] = favicon_scales[i];
178 }
179
180 return SelectFaviconFramesForPixelSizesFromPNGs(png_data,
181 desired_pixel_sizes);
182 }
183
184 gfx::Image SelectFaviconFramesForPixelSizesFromPNGs(
185 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data,
186 const std::map<int, float>& desired_pixel_sizes) {
174 // Create image reps for as many scales as possible without resizing 187 // Create image reps for as many scales as possible without resizing
175 // the bitmap data or decoding it. FaviconHandler stores already resized 188 // the bitmap data or decoding it. FaviconHandler stores already resized
176 // favicons into history so no additional resizing should be needed in the 189 // favicons into history so no additional resizing should be needed in the
177 // common case. 190 // common case.
178 // Creating the gfx::Image from |png_data| without resizing or decoding if 191 // Creating the gfx::Image from |png_data| without resizing or decoding if
179 // possible is important because: 192 // possible is important because:
180 // - Sync does a byte-to-byte comparison of gfx::Image::As1xPNGBytes() to 193 // - Sync does a byte-to-byte comparison of gfx::Image::As1xPNGBytes() to
181 // the data it put into the database in order to determine whether any 194 // the data it put into the database in order to determine whether any
182 // updates should be pushed to sync. 195 // updates should be pushed to sync.
183 // - The decoding occurs on the UI thread and the decoding can be a 196 // - The decoding occurs on the UI thread and the decoding can be a
184 // significant performance hit if a user has many bookmarks. 197 // significant performance hit if a user has many bookmarks.
185 // TODO(pkotwicz): Move the decoding off the UI thread. 198 // TODO(pkotwicz): Move the decoding off the UI thread.
186 std::vector<gfx::ImagePNGRep> png_reps = 199 std::vector<gfx::ImagePNGRep> png_reps =
187 SelectFaviconFramesFromPNGsWithoutResizing( 200 SelectFaviconFramesFromPNGsWithoutResizing(png_data, desired_pixel_sizes);
188 png_data, favicon_scales, favicon_size);
189 201
190 // SelectFaviconFramesFromPNGsWithoutResizing() should have selected the 202 std::map<int, float> favicon_scales_to_generate = desired_pixel_sizes;
191 // largest favicon if |favicon_size| == 0.
192 if (favicon_size == 0)
193 return gfx::Image(png_reps);
194
195 std::vector<float> favicon_scales_to_generate = favicon_scales;
196 for (size_t i = 0; i < png_reps.size(); ++i) { 203 for (size_t i = 0; i < png_reps.size(); ++i) {
197 std::vector<float>::iterator iter = std::find( 204 favicon_scales_to_generate.erase(
198 favicon_scales_to_generate.begin(), 205 favicon_scales_to_generate.find(png_reps[i].Size().width()));
199 favicon_scales_to_generate.end(),
200 png_reps[i].scale);
201 if (iter != favicon_scales_to_generate.end())
202 favicon_scales_to_generate.erase(iter);
203 } 206 }
204 207
205 if (favicon_scales_to_generate.empty()) 208 if (favicon_scales_to_generate.empty())
206 return gfx::Image(png_reps); 209 return gfx::Image(png_reps);
207 210
208 std::vector<SkBitmap> bitmaps; 211 std::vector<SkBitmap> bitmaps;
209 for (size_t i = 0; i < png_data.size(); ++i) { 212 for (size_t i = 0; i < png_data.size(); ++i) {
210 if (!png_data[i].is_valid()) 213 if (!png_data[i].is_valid())
211 continue; 214 continue;
212 215
213 SkBitmap bitmap; 216 SkBitmap bitmap;
214 if (gfx::PNGCodec::Decode(png_data[i].bitmap_data->front(), 217 if (gfx::PNGCodec::Decode(png_data[i].bitmap_data->front(),
215 png_data[i].bitmap_data->size(), 218 png_data[i].bitmap_data->size(),
216 &bitmap)) { 219 &bitmap)) {
217 bitmaps.push_back(bitmap); 220 bitmaps.push_back(bitmap);
218 } 221 }
219 } 222 }
220 223
221 if (bitmaps.empty()) 224 if (bitmaps.empty())
222 return gfx::Image(); 225 return gfx::Image();
223 226
224 gfx::ImageSkia resized_image_skia; 227 gfx::ImageSkia resized_image_skia;
225 for (size_t i = 0; i < favicon_scales_to_generate.size(); ++i) { 228 for (const auto& scale_to_generate : favicon_scales_to_generate) {
226 float scale = favicon_scales_to_generate[i]; 229 float scale = scale_to_generate.second;
227 int desired_size_in_pixel = 230 int desired_size_in_pixel = scale_to_generate.first;
228 static_cast<int>(std::ceil(favicon_size * scale));
229 SkBitmap bitmap = 231 SkBitmap bitmap =
230 ResizeBitmapByDownsamplingIfPossible(bitmaps, desired_size_in_pixel); 232 ResizeBitmapByDownsamplingIfPossible(bitmaps, desired_size_in_pixel);
231 resized_image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); 233 resized_image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
232 } 234 }
233 235
234 if (png_reps.empty()) 236 if (png_reps.empty())
235 return gfx::Image(resized_image_skia); 237 return gfx::Image(resized_image_skia);
236 238
237 std::vector<gfx::ImageSkiaRep> resized_image_skia_reps = 239 std::vector<gfx::ImageSkiaRep> resized_image_skia_reps =
238 resized_image_skia.image_reps(); 240 resized_image_skia.image_reps();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 291
290 bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector( 292 bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector(
291 &resized_bitmap_data); 293 &resized_bitmap_data);
292 bitmap_result.pixel_size = 294 bitmap_result.pixel_size =
293 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); 295 gfx::Size(desired_size_in_pixel, desired_size_in_pixel);
294 296
295 return bitmap_result; 297 return bitmap_result;
296 } 298 }
297 299
298 } // namespace favicon_base 300 } // namespace favicon_base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698