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

Side by Side Diff: gfx/color_utils.cc

Issue 6246027: Move src/gfx/ to src/ui/gfx... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « gfx/color_utils.h ('k') | gfx/color_utils_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gfx/color_utils.h"
6
7 #include <math.h>
8 #if defined(OS_WIN)
9 #include <windows.h>
10 #endif
11
12 #include <algorithm>
13
14 #include "base/basictypes.h"
15 #include "base/logging.h"
16 #include "build/build_config.h"
17 #if defined(OS_WIN)
18 #include "skia/ext/skia_utils_win.h"
19 #endif
20 #include "third_party/skia/include/core/SkBitmap.h"
21
22 namespace color_utils {
23
24 // Helper functions -----------------------------------------------------------
25
26 namespace {
27
28 double calcHue(double temp1, double temp2, double hue) {
29 if (hue < 0.0)
30 ++hue;
31 else if (hue > 1.0)
32 --hue;
33
34 if (hue * 6.0 < 1.0)
35 return temp1 + (temp2 - temp1) * hue * 6.0;
36 if (hue * 2.0 < 1.0)
37 return temp2;
38 if (hue * 3.0 < 2.0)
39 return temp1 + (temp2 - temp1) * (2.0 / 3.0 - hue) * 6.0;
40
41 return temp1;
42 }
43
44 int GetLumaForColor(SkColor* color) {
45 int luma = static_cast<int>((0.3 * SkColorGetR(*color)) +
46 (0.59 * SkColorGetG(*color)) +
47 (0.11 * SkColorGetB(*color)));
48 return std::max(std::min(luma, 255), 0);
49 }
50
51 // Next two functions' formulas from:
52 // http://www.w3.org/TR/WCAG20/#relativeluminancedef
53 // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
54
55 double ConvertSRGB(double eight_bit_component) {
56 const double component = eight_bit_component / 255.0;
57 return (component <= 0.03928) ?
58 (component / 12.92) : pow((component + 0.055) / 1.055, 2.4);
59 }
60
61 SkColor LumaInvertColor(const SkColor& color) {
62 HSL hsl;
63 SkColorToHSL(color, &hsl);
64 hsl.l = 1.0 - hsl.l;
65 return HSLToSkColor(hsl, 255);
66 }
67
68 double ContrastRatio(double foreground_luminance, double background_luminance) {
69 // NOTE: Only pass in numbers obtained from RelativeLuminance(), since those
70 // are guaranteed to be > 0 and thus not cause a divide-by-zero error here.
71 return (foreground_luminance > background_luminance) ?
72 (foreground_luminance / background_luminance) :
73 (background_luminance / foreground_luminance);
74 }
75
76 } // namespace
77
78 // ----------------------------------------------------------------------------
79
80 double RelativeLuminance(SkColor color) {
81 return (0.2126 * ConvertSRGB(SkColorGetR(color))) +
82 (0.7152 * ConvertSRGB(SkColorGetG(color))) +
83 (0.0722 * ConvertSRGB(SkColorGetB(color))) + 0.05;
84 }
85
86 void SkColorToHSL(SkColor c, HSL* hsl) {
87 double r = static_cast<double>(SkColorGetR(c)) / 255.0;
88 double g = static_cast<double>(SkColorGetG(c)) / 255.0;
89 double b = static_cast<double>(SkColorGetB(c)) / 255.0;
90 double vmax = std::max(std::max(r, g), b);
91 double vmin = std::min(std::min(r, g), b);
92 double delta = vmax - vmin;
93 hsl->l = (vmax + vmin) / 2;
94 if (delta) {
95 double dr = (((vmax - r) / 6.0) + (delta / 2.0)) / delta;
96 double dg = (((vmax - g) / 6.0) + (delta / 2.0)) / delta;
97 double db = (((vmax - b) / 6.0) + (delta / 2.0)) / delta;
98 // We need to compare for the max value because comparing vmax to r,
99 // g or b can sometimes result in values overflowing registers.
100 if (r >= g && r >= b)
101 hsl->h = db - dg;
102 else if (g >= r && g >= b)
103 hsl->h = (1.0 / 3.0) + dr - db;
104 else // (b >= r && b >= g)
105 hsl->h = (2.0 / 3.0) + dg - dr;
106
107 if (hsl->h < 0.0)
108 ++hsl->h;
109 else if (hsl->h > 1.0)
110 --hsl->h;
111
112 hsl->s = delta / ((hsl->l < 0.5) ? (vmax + vmin) : (2 - vmax - vmin));
113 } else {
114 hsl->h = hsl->s = 0;
115 }
116 }
117
118 SkColor HSLToSkColor(const HSL& hsl, SkAlpha alpha) {
119 double hue = hsl.h;
120 double saturation = hsl.s;
121 double lightness = hsl.l;
122
123 // If there's no color, we don't care about hue and can do everything based
124 // on brightness.
125 if (!saturation) {
126 uint8 light;
127
128 if (lightness < 0)
129 light = 0;
130 else if (lightness >= 1.0)
131 light = 255;
132 else
133 light = SkDoubleToFixed(lightness) >> 8;
134
135 return SkColorSetARGB(alpha, light, light, light);
136 }
137
138 double temp2 = (lightness < 0.5) ?
139 (lightness * (1.0 + saturation)) :
140 (lightness + saturation - (lightness * saturation));
141 double temp1 = 2.0 * lightness - temp2;
142 return SkColorSetARGB(alpha,
143 static_cast<int>(calcHue(temp1, temp2, hue + 1.0 / 3.0) * 255),
144 static_cast<int>(calcHue(temp1, temp2, hue) * 255),
145 static_cast<int>(calcHue(temp1, temp2, hue - 1.0 / 3.0) * 255));
146 }
147
148 SkColor HSLShift(SkColor color, const HSL& shift) {
149 HSL hsl;
150 int alpha = SkColorGetA(color);
151 SkColorToHSL(color, &hsl);
152
153 // Replace the hue with the tint's hue.
154 if (shift.h >= 0)
155 hsl.h = shift.h;
156
157 // Change the saturation.
158 if (shift.s >= 0) {
159 if (shift.s <= 0.5)
160 hsl.s *= shift.s * 2.0;
161 else
162 hsl.s += (1.0 - hsl.s) * ((shift.s - 0.5) * 2.0);
163 }
164
165 SkColor result = HSLToSkColor(hsl, alpha);
166
167 if (shift.l < 0)
168 return result;
169
170 // Lightness shifts in the style of popular image editors aren't
171 // actually represented in HSL - the L value does have some effect
172 // on saturation.
173 double r = static_cast<double>(SkColorGetR(result));
174 double g = static_cast<double>(SkColorGetG(result));
175 double b = static_cast<double>(SkColorGetB(result));
176 if (shift.l <= 0.5) {
177 r *= (shift.l * 2.0);
178 g *= (shift.l * 2.0);
179 b *= (shift.l * 2.0);
180 } else {
181 r += (255.0 - r) * ((shift.l - 0.5) * 2.0);
182 g += (255.0 - g) * ((shift.l - 0.5) * 2.0);
183 b += (255.0 - b) * ((shift.l - 0.5) * 2.0);
184 }
185 return SkColorSetARGB(alpha,
186 static_cast<int>(r),
187 static_cast<int>(g),
188 static_cast<int>(b));
189 }
190
191 bool IsColorCloseToTransparent(SkAlpha alpha) {
192 const int kCloseToBoundary = 64;
193 return alpha < kCloseToBoundary;
194 }
195
196 bool IsColorCloseToGrey(int r, int g, int b) {
197 const int kAverageBoundary = 15;
198 int average = (r + g + b) / 3;
199 return (abs(r - average) < kAverageBoundary) &&
200 (abs(g - average) < kAverageBoundary) &&
201 (abs(b - average) < kAverageBoundary);
202 }
203
204 SkColor GetAverageColorOfFavicon(SkBitmap* favicon, SkAlpha alpha) {
205 int r = 0, g = 0, b = 0;
206
207 SkAutoLockPixels favicon_lock(*favicon);
208 SkColor* pixels = static_cast<SkColor*>(favicon->getPixels());
209 // Assume ARGB_8888 format.
210 DCHECK(favicon->getConfig() == SkBitmap::kARGB_8888_Config);
211 SkColor* current_color = pixels;
212
213 DCHECK(favicon->width() <= 16 && favicon->height() <= 16);
214
215 int pixel_count = favicon->width() * favicon->height();
216 int color_count = 0;
217 for (int i = 0; i < pixel_count; ++i, ++current_color) {
218 // Disregard this color if it is close to black, close to white, or close
219 // to transparent since any of those pixels do not contribute much to the
220 // color makeup of this icon.
221 int cr = SkColorGetR(*current_color);
222 int cg = SkColorGetG(*current_color);
223 int cb = SkColorGetB(*current_color);
224
225 if (IsColorCloseToTransparent(SkColorGetA(*current_color)) ||
226 IsColorCloseToGrey(cr, cg, cb))
227 continue;
228
229 r += cr;
230 g += cg;
231 b += cb;
232 ++color_count;
233 }
234
235 return color_count ?
236 SkColorSetARGB(alpha, r / color_count, g / color_count, b / color_count) :
237 SkColorSetARGB(alpha, 0, 0, 0);
238 }
239
240 void BuildLumaHistogram(SkBitmap* bitmap, int histogram[256]) {
241 SkAutoLockPixels bitmap_lock(*bitmap);
242 // Assume ARGB_8888 format.
243 DCHECK(bitmap->getConfig() == SkBitmap::kARGB_8888_Config);
244
245 int pixel_width = bitmap->width();
246 int pixel_height = bitmap->height();
247 for (int y = 0; y < pixel_height; ++y) {
248 SkColor* current_color = static_cast<uint32_t*>(bitmap->getAddr32(0, y));
249 for (int x = 0; x < pixel_width; ++x, ++current_color)
250 histogram[GetLumaForColor(current_color)]++;
251 }
252 }
253
254 SkColor AlphaBlend(SkColor foreground, SkColor background, SkAlpha alpha) {
255 if (alpha == 0)
256 return background;
257 if (alpha == 255)
258 return foreground;
259
260 int f_alpha = SkColorGetA(foreground);
261 int b_alpha = SkColorGetA(background);
262
263 double normalizer = (f_alpha * alpha + b_alpha * (255 - alpha)) / 255.0;
264 if (normalizer == 0.0)
265 return SkColorSetARGB(0, 0, 0, 0);
266
267 double f_weight = f_alpha * alpha / normalizer;
268 double b_weight = b_alpha * (255 - alpha) / normalizer;
269
270 double r = (SkColorGetR(foreground) * f_weight +
271 SkColorGetR(background) * b_weight) / 255.0;
272 double g = (SkColorGetG(foreground) * f_weight +
273 SkColorGetG(background) * b_weight) / 255.0;
274 double b = (SkColorGetB(foreground) * f_weight +
275 SkColorGetB(background) * b_weight) / 255.0;
276
277 return SkColorSetARGB(static_cast<int>(normalizer),
278 static_cast<int>(r),
279 static_cast<int>(g),
280 static_cast<int>(b));
281 }
282
283 SkColor GetReadableColor(SkColor foreground, SkColor background) {
284 const SkColor foreground2 = LumaInvertColor(foreground);
285 const double background_luminance = RelativeLuminance(background);
286 return (ContrastRatio(RelativeLuminance(foreground), background_luminance) >=
287 ContrastRatio(RelativeLuminance(foreground2), background_luminance)) ?
288 foreground : foreground2;
289 }
290
291 SkColor GetSysSkColor(int which) {
292 #if defined(OS_WIN)
293 return skia::COLORREFToSkColor(GetSysColor(which));
294 #else
295 NOTIMPLEMENTED();
296 return SK_ColorLTGRAY;
297 #endif
298 }
299
300 } // namespace color_utils
OLDNEW
« no previous file with comments | « gfx/color_utils.h ('k') | gfx/color_utils_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698