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 23 matching lines...) Expand all Loading... |
34 { | 34 { |
35 SkCanvas canvas(bitmap); | 35 SkCanvas canvas(bitmap); |
36 int shift = (desired_size - source_size) / 2; | 36 int shift = (desired_size - source_size) / 2; |
37 SkRect dest(SkRect::MakeXYWH(shift, shift, source_size, source_size)); | 37 SkRect dest(SkRect::MakeXYWH(shift, shift, source_size, source_size)); |
38 canvas.drawBitmapRect(contents, NULL, dest); | 38 canvas.drawBitmapRect(contents, NULL, dest); |
39 } | 39 } |
40 | 40 |
41 return bitmap; | 41 return bitmap; |
42 } | 42 } |
43 | 43 |
| 44 SkBitmap SampleNearestNeighbor(SkBitmap contents, int desired_size) { |
| 45 SkBitmap bitmap; |
| 46 bitmap.setConfig( |
| 47 SkBitmap::kARGB_8888_Config, desired_size, desired_size); |
| 48 bitmap.allocPixels(); |
| 49 if (!contents.isOpaque()) |
| 50 bitmap.eraseARGB(0, 0, 0, 0); |
| 51 |
| 52 { |
| 53 SkCanvas canvas(bitmap); |
| 54 SkRect dest(SkRect::MakeWH(desired_size, desired_size)); |
| 55 canvas.drawBitmapRect(contents, NULL, dest); |
| 56 } |
| 57 |
| 58 return bitmap; |
| 59 } |
| 60 |
44 SkBitmap SelectCandidate(const std::vector<SkBitmap>& bitmaps, | 61 SkBitmap SelectCandidate(const std::vector<SkBitmap>& bitmaps, |
45 int desired_size, | 62 int desired_size, |
46 ui::ScaleFactor scale_factor) { | 63 ui::ScaleFactor scale_factor) { |
47 float scale = GetScaleFactorScale(scale_factor); | 64 float scale = GetScaleFactorScale(scale_factor); |
48 desired_size = static_cast<int>(desired_size * scale + 0.5f); | 65 desired_size = static_cast<int>(desired_size * scale + 0.5f); |
49 | 66 |
50 // Try to find an exact match. | 67 // Try to find an exact match. |
51 for (size_t i = 0; i < bitmaps.size(); ++i) { | 68 for (size_t i = 0; i < bitmaps.size(); ++i) { |
52 if (bitmaps[i].width() == desired_size && | 69 if (bitmaps[i].width() == desired_size && |
53 bitmaps[i].height() == desired_size) { | 70 bitmaps[i].height() == desired_size) { |
(...skipping 15 matching lines...) Expand all Loading... |
69 // Try again, with upsizing the base variant. | 86 // Try again, with upsizing the base variant. |
70 for (size_t i = 0; i < bitmaps.size(); ++i) { | 87 for (size_t i = 0; i < bitmaps.size(); ++i) { |
71 if (bitmaps[i].width() * scale == source_size && | 88 if (bitmaps[i].width() * scale == source_size && |
72 bitmaps[i].height() * scale == source_size) { | 89 bitmaps[i].height() * scale == source_size) { |
73 return PadWithBorder(bitmaps[i], desired_size, source_size); | 90 return PadWithBorder(bitmaps[i], desired_size, source_size); |
74 } | 91 } |
75 } | 92 } |
76 } | 93 } |
77 | 94 |
78 // 2. Integer multiples are built using nearest neighbor sampling. | 95 // 2. Integer multiples are built using nearest neighbor sampling. |
79 // TODO(thakis): Implement. | |
80 | |
81 // 3. Else, use Lancosz scaling: | 96 // 3. Else, use Lancosz scaling: |
82 // b) If available, from the next bigger variant. | 97 // b) If available, from the next bigger variant. |
83 int lancosz_candidate = -1; | 98 int candidate = -1; |
84 int min_area = INT_MAX; | 99 int min_area = INT_MAX; |
85 for (size_t i = 0; i < bitmaps.size(); ++i) { | 100 for (size_t i = 0; i < bitmaps.size(); ++i) { |
86 int area = bitmaps[i].width() * bitmaps[i].height(); | 101 int area = bitmaps[i].width() * bitmaps[i].height(); |
87 if (bitmaps[i].width() > desired_size && | 102 if (bitmaps[i].width() > desired_size && |
88 bitmaps[i].height() > desired_size && | 103 bitmaps[i].height() > desired_size && |
89 (lancosz_candidate == -1 || area < min_area)) { | 104 (candidate == -1 || area < min_area)) { |
90 lancosz_candidate = i; | 105 candidate = i; |
91 min_area = area; | 106 min_area = area; |
92 } | 107 } |
93 } | 108 } |
94 // c) Else, from the biggest smaller variant. | 109 // c) Else, from the biggest smaller variant. |
95 if (lancosz_candidate == -1) | 110 if (candidate == -1) |
96 lancosz_candidate = BiggestCandidate(bitmaps); | 111 candidate = BiggestCandidate(bitmaps); |
97 | 112 |
| 113 const SkBitmap& bitmap = bitmaps[candidate]; |
| 114 bool is_integer_multiple = desired_size % bitmap.width() == 0 && |
| 115 desired_size % bitmap.height() == 0; |
| 116 if (is_integer_multiple) |
| 117 return SampleNearestNeighbor(bitmap, desired_size); |
98 return skia::ImageOperations::Resize( | 118 return skia::ImageOperations::Resize( |
99 bitmaps[lancosz_candidate], skia::ImageOperations::RESIZE_LANCZOS3, | 119 bitmap, skia::ImageOperations::RESIZE_LANCZOS3, |
100 desired_size, desired_size); | 120 desired_size, desired_size); |
101 } | 121 } |
102 | 122 |
103 } // namespace | 123 } // namespace |
104 | 124 |
105 gfx::ImageSkia SelectFaviconFrames( | 125 gfx::ImageSkia SelectFaviconFrames( |
106 const std::vector<SkBitmap>& bitmaps, | 126 const std::vector<SkBitmap>& bitmaps, |
107 const std::vector<ui::ScaleFactor>& scale_factors, | 127 const std::vector<ui::ScaleFactor>& scale_factors, |
108 int desired_size) { | 128 int desired_size) { |
109 gfx::ImageSkia multi_image; | 129 gfx::ImageSkia multi_image; |
110 if (bitmaps.empty()) | 130 if (bitmaps.empty()) |
111 return multi_image; | 131 return multi_image; |
112 | 132 |
113 if (desired_size == 0) { | 133 if (desired_size == 0) { |
114 // Just return the biggest image available. | 134 // Just return the biggest image available. |
115 size_t max_index = BiggestCandidate(bitmaps); | 135 size_t max_index = BiggestCandidate(bitmaps); |
116 multi_image.AddRepresentation( | 136 multi_image.AddRepresentation( |
117 gfx::ImageSkiaRep(bitmaps[max_index], ui::SCALE_FACTOR_100P)); | 137 gfx::ImageSkiaRep(bitmaps[max_index], ui::SCALE_FACTOR_100P)); |
118 return multi_image; | 138 return multi_image; |
119 } | 139 } |
120 | 140 |
121 for (size_t i = 0; i < scale_factors.size(); ++i) { | 141 for (size_t i = 0; i < scale_factors.size(); ++i) { |
122 multi_image.AddRepresentation(gfx::ImageSkiaRep( | 142 multi_image.AddRepresentation(gfx::ImageSkiaRep( |
123 SelectCandidate(bitmaps, desired_size, scale_factors[i]), | 143 SelectCandidate(bitmaps, desired_size, scale_factors[i]), |
124 scale_factors[i])); | 144 scale_factors[i])); |
125 } | 145 } |
126 | 146 |
127 return multi_image; | 147 return multi_image; |
128 } | 148 } |
OLD | NEW |