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

Side by Side Diff: ui/gfx/color_utils.cc

Issue 1761183002: color_utils cleanup: (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 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 (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 "ui/gfx/color_utils.h" 5 #include "ui/gfx/color_utils.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
(...skipping 24 matching lines...) Expand all
35 --hue; 35 --hue;
36 36
37 double result = temp1; 37 double result = temp1;
38 if (hue * 6.0 < 1.0) 38 if (hue * 6.0 < 1.0)
39 result = temp1 + (temp2 - temp1) * hue * 6.0; 39 result = temp1 + (temp2 - temp1) * hue * 6.0;
40 else if (hue * 2.0 < 1.0) 40 else if (hue * 2.0 < 1.0)
41 result = temp2; 41 result = temp2;
42 else if (hue * 3.0 < 2.0) 42 else if (hue * 3.0 < 2.0)
43 result = temp1 + (temp2 - temp1) * (2.0 / 3.0 - hue) * 6.0; 43 result = temp1 + (temp2 - temp1) * (2.0 / 3.0 - hue) * 6.0;
44 44
45 // Scale the result from 0 - 255 and round off the value. 45 return static_cast<int>(std::round(result * 255));
46 return static_cast<int>(result * 255 + .5);
47 } 46 }
48 47
49 // Next two functions' formulas from: 48 // Assumes sRGB.
50 // http://www.w3.org/TR/WCAG20/#relativeluminancedef 49 double Linearize(double eight_bit_component) {
51 // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
52
53 double ConvertSRGB(double eight_bit_component) {
54 const double component = eight_bit_component / 255.0; 50 const double component = eight_bit_component / 255.0;
55 return (component <= 0.03928) ? 51 return (component <= 0.03928) ?
56 (component / 12.92) : pow((component + 0.055) / 1.055, 2.4); 52 (component / 12.92) : pow((component + 0.055) / 1.055, 2.4);
57 } 53 }
58 54
59 SkColor LumaInvertColor(SkColor color) { 55 SkColor LightnessInvertColor(SkColor color) {
60 HSL hsl; 56 HSL hsl;
61 SkColorToHSL(color, &hsl); 57 SkColorToHSL(color, &hsl);
62 hsl.l = 1.0 - hsl.l; 58 hsl.l = 1.0 - hsl.l;
63 return HSLToSkColor(hsl, 255); 59 return HSLToSkColor(hsl, SkColorGetA(color));
danakj 2016/03/04 01:54:49 This is a behaviour change, can this be a separate
Peter Kasting 2016/03/04 02:10:52 It's a behavior change, but only for GetReadableCo
danakj 2016/03/04 19:05:55 Ah, ok then.
64 }
65
66 double ContrastRatio(double foreground_luminance, double background_luminance) {
67 DCHECK_GE(foreground_luminance, 0.0);
68 DCHECK_GE(background_luminance, 0.0);
69 foreground_luminance += 0.05;
70 background_luminance += 0.05;
71 return (foreground_luminance > background_luminance) ?
72 (foreground_luminance / background_luminance) :
73 (background_luminance / foreground_luminance);
74 } 60 }
75 61
76 } // namespace 62 } // namespace
77 63
78 64
79 // ---------------------------------------------------------------------------- 65 // ----------------------------------------------------------------------------
80 66
81 double GetContrastRatio(SkColor color_a, SkColor color_b) { 67 double ContrastRatio(SkColor color_a, SkColor color_b) {
82 return ContrastRatio(RelativeLuminance(color_a), RelativeLuminance(color_b)); 68 return ContrastRatio(RelativeLuminance(color_a), RelativeLuminance(color_b));
83 } 69 }
84 70
85 unsigned char GetLuminanceForColor(SkColor color) { 71 double ContrastRatio(double luminance_a, double luminance_b) {
86 return base::saturated_cast<unsigned char>( 72 DCHECK_GE(luminance_a, 0.0);
87 (0.3 * SkColorGetR(color)) + 73 DCHECK_GE(luminance_b, 0.0);
88 (0.59 * SkColorGetG(color)) + 74 luminance_a += 0.05;
89 (0.11 * SkColorGetB(color))); 75 luminance_b += 0.05;
76 return (luminance_a > luminance_b) ? (luminance_a / luminance_b)
77 : (luminance_b / luminance_a);
90 } 78 }
91 79
92 double RelativeLuminance(SkColor color) { 80 double RelativeLuminance(SkColor color) {
93 return (0.2126 * ConvertSRGB(SkColorGetR(color))) + 81 return (0.2126 * Linearize(SkColorGetR(color))) +
94 (0.7152 * ConvertSRGB(SkColorGetG(color))) + 82 (0.7152 * Linearize(SkColorGetG(color))) +
95 (0.0722 * ConvertSRGB(SkColorGetB(color))); 83 (0.0722 * Linearize(SkColorGetB(color)));
84 }
85
86 uint8_t Luma(SkColor color) {
87 return static_cast<uint8_t>(std::round((0.299 * SkColorGetR(color)) +
danakj 2016/03/04 01:54:49 These constants are diff too, similar request for
Peter Kasting 2016/03/04 02:10:52 It's true, this is a behavior change. That said,
danakj 2016/03/04 19:05:55 Yeh, it's just good practice IMO. Like maybe they
Peter Kasting 2016/03/04 20:28:57 I agree in general principle. In this specific ca
88 (0.587 * SkColorGetG(color)) +
89 (0.114 * SkColorGetB(color))));
96 } 90 }
97 91
98 void SkColorToHSL(SkColor c, HSL* hsl) { 92 void SkColorToHSL(SkColor c, HSL* hsl) {
99 double r = static_cast<double>(SkColorGetR(c)) / 255.0; 93 double r = static_cast<double>(SkColorGetR(c)) / 255.0;
100 double g = static_cast<double>(SkColorGetG(c)) / 255.0; 94 double g = static_cast<double>(SkColorGetG(c)) / 255.0;
101 double b = static_cast<double>(SkColorGetB(c)) / 255.0; 95 double b = static_cast<double>(SkColorGetB(c)) / 255.0;
102 double vmax = std::max(std::max(r, g), b); 96 double vmax = std::max(std::max(r, g), b);
103 double vmin = std::min(std::min(r, g), b); 97 double vmin = std::min(std::min(r, g), b);
104 double delta = vmax - vmin; 98 double delta = vmax - vmin;
105 hsl->l = (vmax + vmin) / 2; 99 hsl->l = (vmax + vmin) / 2;
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 229
236 void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]) { 230 void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]) {
237 DCHECK_EQ(kN32_SkColorType, bitmap.colorType()); 231 DCHECK_EQ(kN32_SkColorType, bitmap.colorType());
238 232
239 SkAutoLockPixels bitmap_lock(bitmap); 233 SkAutoLockPixels bitmap_lock(bitmap);
240 234
241 int pixel_width = bitmap.width(); 235 int pixel_width = bitmap.width();
242 int pixel_height = bitmap.height(); 236 int pixel_height = bitmap.height();
243 for (int y = 0; y < pixel_height; ++y) { 237 for (int y = 0; y < pixel_height; ++y) {
244 for (int x = 0; x < pixel_width; ++x) 238 for (int x = 0; x < pixel_width; ++x)
245 ++histogram[GetLuminanceForColor(bitmap.getColor(x, y))]; 239 ++histogram[Luma(bitmap.getColor(x, y))];
246 } 240 }
247 } 241 }
248 242
249 double CalculateBoringScore(const SkBitmap& bitmap) { 243 double CalculateBoringScore(const SkBitmap& bitmap) {
250 if (bitmap.isNull() || bitmap.empty()) 244 if (bitmap.isNull() || bitmap.empty())
251 return 1.0; 245 return 1.0;
252 int histogram[256] = {0}; 246 int histogram[256] = {0};
253 BuildLumaHistogram(bitmap, histogram); 247 BuildLumaHistogram(bitmap, histogram);
254 248
255 int color_count = *std::max_element(histogram, histogram + 256); 249 int color_count = *std::max_element(histogram, histogram + 256);
(...skipping 24 matching lines...) Expand all
280 double b = (SkColorGetB(foreground) * f_weight + 274 double b = (SkColorGetB(foreground) * f_weight +
281 SkColorGetB(background) * b_weight) / 255.0; 275 SkColorGetB(background) * b_weight) / 255.0;
282 276
283 return SkColorSetARGB(static_cast<int>(std::round(normalizer)), 277 return SkColorSetARGB(static_cast<int>(std::round(normalizer)),
284 static_cast<int>(std::round(r)), 278 static_cast<int>(std::round(r)),
285 static_cast<int>(std::round(g)), 279 static_cast<int>(std::round(g)),
286 static_cast<int>(std::round(b))); 280 static_cast<int>(std::round(b)));
287 } 281 }
288 282
289 bool IsDark(SkColor color) { 283 bool IsDark(SkColor color) {
290 return GetLuminanceForColor(color) < 128; 284 return Luma(color) < 128;
291 } 285 }
292 286
293 SkColor BlendTowardOppositeLuminance(SkColor color, SkAlpha alpha) { 287 SkColor BlendTowardOppositeLuma(SkColor color, SkAlpha alpha) {
294 return AlphaBlend(IsDark(color) ? SK_ColorWHITE : SK_ColorBLACK, color, 288 return AlphaBlend(IsDark(color) ? SK_ColorWHITE : SK_ColorBLACK, color,
295 alpha); 289 alpha);
296 } 290 }
297 291
298 SkColor GetReadableColor(SkColor foreground, SkColor background) { 292 SkColor GetReadableColor(SkColor foreground, SkColor background) {
299 const SkColor foreground2 = LumaInvertColor(foreground); 293 return PickContrastingColor(foreground, LightnessInvertColor(foreground),
294 background);
295 }
296
297 SkColor PickContrastingColor(SkColor foreground1,
298 SkColor foreground2,
299 SkColor background) {
300 const double background_luminance = RelativeLuminance(background); 300 const double background_luminance = RelativeLuminance(background);
301 return (ContrastRatio(RelativeLuminance(foreground), background_luminance) >= 301 return (ContrastRatio(RelativeLuminance(foreground1), background_luminance) >=
302 ContrastRatio(RelativeLuminance(foreground2), background_luminance)) ? 302 ContrastRatio(RelativeLuminance(foreground2), background_luminance)) ?
303 foreground : foreground2; 303 foreground1 : foreground2;
304 } 304 }
305 305
306 SkColor InvertColor(SkColor color) { 306 SkColor InvertColor(SkColor color) {
307 return SkColorSetARGB(SkColorGetA(color), 255 - SkColorGetR(color), 307 return SkColorSetARGB(SkColorGetA(color), 255 - SkColorGetR(color),
308 255 - SkColorGetG(color), 255 - SkColorGetB(color)); 308 255 - SkColorGetG(color), 255 - SkColorGetB(color));
309 } 309 }
310 310
311 SkColor GetSysSkColor(int which) { 311 SkColor GetSysSkColor(int which) {
312 #if defined(OS_WIN) 312 #if defined(OS_WIN)
313 return skia::COLORREFToSkColor(GetSysColor(which)); 313 return skia::COLORREFToSkColor(GetSysColor(which));
(...skipping 16 matching lines...) Expand all
330 if (IsDark(text_color)) { 330 if (IsDark(text_color)) {
331 // For black text, this comes out to kChromeIconGrey. 331 // For black text, this comes out to kChromeIconGrey.
332 return color_utils::AlphaBlend(SK_ColorWHITE, text_color, 332 return color_utils::AlphaBlend(SK_ColorWHITE, text_color,
333 SkColorGetR(gfx::kChromeIconGrey)); 333 SkColorGetR(gfx::kChromeIconGrey));
334 } 334 }
335 // The dimming is less dramatic when darkening a light color. 335 // The dimming is less dramatic when darkening a light color.
336 return color_utils::AlphaBlend(SK_ColorBLACK, text_color, 0x33); 336 return color_utils::AlphaBlend(SK_ColorBLACK, text_color, 0x33);
337 } 337 }
338 338
339 } // namespace color_utils 339 } // namespace color_utils
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698