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

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

Issue 215049: Reorder the color_utils functions in preparation for adding more:... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 3 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 | « app/gfx/color_utils.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 "app/gfx/color_utils.h" 5 #include "app/gfx/color_utils.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #if defined(OS_WIN) 8 #if defined(OS_WIN)
9 #include <windows.h> 9 #include <windows.h>
10 #endif 10 #endif
11 11
12 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "build/build_config.h" 14 #include "build/build_config.h"
15 #if defined(OS_WIN) 15 #if defined(OS_WIN)
16 #include "skia/ext/skia_utils_win.h" 16 #include "skia/ext/skia_utils_win.h"
17 #endif 17 #endif
18 #include "third_party/skia/include/core/SkBitmap.h" 18 #include "third_party/skia/include/core/SkBitmap.h"
19 19
20 namespace color_utils { 20 namespace color_utils {
21 21
22 // Helper functions -----------------------------------------------------------
23
24 namespace {
25
22 // These transformations are based on the equations in: 26 // These transformations are based on the equations in:
23 // http://en.wikipedia.org/wiki/Lab_color 27 // http://en.wikipedia.org/wiki/Lab_color
24 // http://en.wikipedia.org/wiki/SRGB_color_space#Specification_of_the_transforma tion 28 // http://en.wikipedia.org/wiki/SRGB_color_space#
brettw 2009/09/22 16:40:51 I would have kept this link as-is, since now nobod
29 // Specification_of_the_transformation
25 // See also: 30 // See also:
26 // http://www.brucelindbloom.com/index.html?ColorCalculator.html 31 // http://www.brucelindbloom.com/index.html?ColorCalculator.html
27 32
28 static const double kCIEConversionAlpha = 0.055; 33 const double kCIEConversionAlpha = 0.055;
29 static const double kCIEConversionGamma = 2.2; 34 const double kCIEConversionGamma = 2.2;
30 static const double kE = 0.008856; 35 const double kE = 0.008856;
31 static const double kK = 903.3; 36 const double kK = 903.3;
32 37
33 static double CIEConvertNonLinear(uint8 color_component) { 38 double CIEConvertNonLinear(uint8 color_component) {
34 double color_component_d = static_cast<double>(color_component) / 255.0; 39 double color_component_d = static_cast<double>(color_component) / 255.0;
35 if (color_component_d > 0.04045) { 40 if (color_component_d > 0.04045) {
36 double base = (color_component_d + kCIEConversionAlpha) / 41 double base = (color_component_d + kCIEConversionAlpha) /
37 (1 + kCIEConversionAlpha); 42 (1 + kCIEConversionAlpha);
38 return pow(base, kCIEConversionGamma); 43 return pow(base, kCIEConversionGamma);
39 } else { 44 } else {
40 return color_component_d / 12.92; 45 return color_component_d / 12.92;
41 } 46 }
42 } 47 }
43 48
44 // Note: this works only for sRGB. 49 uint8 sRGBColorComponentFromLinearComponent(double component) {
45 void SkColorToCIEXYZ(SkColor c, CIE_XYZ* xyz) {
46 uint8 r = SkColorGetR(c);
47 uint8 g = SkColorGetG(c);
48 uint8 b = SkColorGetB(c);
49
50 xyz->X =
51 0.4124 * CIEConvertNonLinear(r) +
52 0.3576 * CIEConvertNonLinear(g) +
53 0.1805 * CIEConvertNonLinear(b);
54 xyz->Y =
55 0.2126 * CIEConvertNonLinear(r) +
56 0.7152 * CIEConvertNonLinear(g) +
57 0.0722 * CIEConvertNonLinear(g);
58 xyz->Z =
59 0.0193 * CIEConvertNonLinear(r) +
60 0.1192 * CIEConvertNonLinear(g) +
61 0.9505 * CIEConvertNonLinear(b);
62 }
63
64 static double LabConvertNonLinear(double value) {
65 if (value > 0.008856) {
66 double goat = pow(value, static_cast<double>(1) / 3);
67 return goat;
68 }
69 return (kK * value + 16) / 116;
70 }
71
72 void CIEXYZToLabColor(const CIE_XYZ& xyz, LabColor* lab) {
73 CIE_XYZ white_xyz;
74 SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz);
75 double fx = LabConvertNonLinear(xyz.X / white_xyz.X);
76 double fy = LabConvertNonLinear(xyz.Y / white_xyz.Y);
77 double fz = LabConvertNonLinear(xyz.Z / white_xyz.Z);
78 lab->L = static_cast<int>(116 * fy) - 16;
79 lab->a = static_cast<int>(500 * (fx - fy));
80 lab->b = static_cast<int>(200 * (fy - fz));
81 }
82
83 static uint8 sRGBColorComponentFromLinearComponent(double component) {
84 double result; 50 double result;
85 if (component <= 0.0031308) { 51 if (component <= 0.0031308) {
86 result = 12.92 * component; 52 result = 12.92 * component;
87 } else { 53 } else {
88 result = (1 + kCIEConversionAlpha) * 54 result = (1 + kCIEConversionAlpha) *
89 pow(component, (static_cast<double>(1) / 2.4)) - 55 pow(component, (static_cast<double>(1) / 2.4)) -
90 kCIEConversionAlpha; 56 kCIEConversionAlpha;
91 } 57 }
92 return std::min(static_cast<uint8>(255), static_cast<uint8>(result * 255)); 58 return std::min(static_cast<uint8>(255), static_cast<uint8>(result * 255));
93 } 59 }
94 60
95 SkColor CIEXYZToSkColor(SkAlpha alpha, const CIE_XYZ& xyz) { 61 double LabConvertNonLinear(double value) {
96 double r_linear = 3.2410 * xyz.X - 1.5374 * xyz.Y - 0.4986 * xyz.Z; 62 if (value > 0.008856) {
97 double g_linear = -0.9692 * xyz.X + 1.8760 * xyz.Y + 0.0416 * xyz.Z; 63 double goat = pow(value, static_cast<double>(1) / 3);
98 double b_linear = 0.0556 * xyz.X - 0.2040 * xyz.Y + 1.0570 * xyz.Z; 64 return goat;
99 uint8 r = sRGBColorComponentFromLinearComponent(r_linear); 65 }
100 uint8 g = sRGBColorComponentFromLinearComponent(g_linear); 66 return (kK * value + 16) / 116;
101 uint8 b = sRGBColorComponentFromLinearComponent(b_linear);
102 return SkColorSetARGB(alpha, r, g, b);
103 } 67 }
104 68
105 static double gen_yr(const LabColor& lab) { 69 double gen_yr(const LabColor& lab) {
106 if (lab.L > (kE * kK)) 70 if (lab.L > (kE * kK))
107 return pow((lab.L + 16.0) / 116, 3.0); 71 return pow((lab.L + 16.0) / 116, 3.0);
108 return static_cast<double>(lab.L) / kK; 72 return static_cast<double>(lab.L) / kK;
109 } 73 }
110 74
111 static double fy(const LabColor& lab) { 75 double fy(const LabColor& lab) {
112 double yr = gen_yr(lab); 76 double yr = gen_yr(lab);
113 if (yr > kE) 77 if (yr > kE)
114 return (lab.L + 16.0) / 116; 78 return (lab.L + 16.0) / 116;
115 return (kK * yr + 16.0) / 116; 79 return (kK * yr + 16.0) / 116;
116 } 80 }
117 81
118 static double fx(const LabColor& lab) { 82 double fx(const LabColor& lab) {
119 return (static_cast<double>(lab.a) / 500) + fy(lab); 83 return (static_cast<double>(lab.a) / 500) + fy(lab);
120 } 84 }
121 85
122 static double gen_xr(const LabColor& lab) { 86 double gen_xr(const LabColor& lab) {
123 double x = fx(lab); 87 double x = fx(lab);
124 double x_cubed = pow(x, 3.0); 88 double x_cubed = pow(x, 3.0);
125 if (x_cubed > kE) 89 if (x_cubed > kE)
126 return x_cubed; 90 return x_cubed;
127 return (116.0 * x - 16.0) / kK; 91 return (116.0 * x - 16.0) / kK;
128 } 92 }
129 93
130 static double fz(const LabColor& lab) { 94 double fz(const LabColor& lab) {
131 return fy(lab) - (static_cast<double>(lab.b) / 200); 95 return fy(lab) - (static_cast<double>(lab.b) / 200);
132 } 96 }
133 97
134 static double gen_zr(const LabColor& lab) { 98 double gen_zr(const LabColor& lab) {
135 double z = fz(lab); 99 double z = fz(lab);
136 double z_cubed = pow(z, 3.0); 100 double z_cubed = pow(z, 3.0);
137 if (z_cubed > kE) 101 if (z_cubed > kE)
138 return z_cubed; 102 return z_cubed;
139 return (116.0 * z - 16.0) / kK; 103 return (116.0 * z - 16.0) / kK;
140 } 104 }
141 105
142 void LabColorToCIEXYZ(const LabColor& lab, CIE_XYZ* xyz) { 106 int GetLumaForColor(SkColor* color) {
143 CIE_XYZ result; 107 int r = SkColorGetR(*color);
108 int g = SkColorGetG(*color);
109 int b = SkColorGetB(*color);
144 110
145 CIE_XYZ white_xyz; 111 int luma = static_cast<int>(0.3*r + 0.59*g + 0.11*b);
146 SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz); 112 if (luma < 0)
113 luma = 0;
114 else if (luma > 255)
115 luma = 255;
147 116
148 result.X = gen_xr(lab) * white_xyz.X; 117 return luma;
149 result.Y = gen_yr(lab) * white_xyz.Y; 118 }
150 result.Z = gen_zr(lab) * white_xyz.Z;
151 119
152 *xyz = result; 120 // Next three functions' formulas from:
121 // http://www.w3.org/TR/WCAG20/#relativeluminancedef
122 // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
123
124 double ConvertSRGB(double eight_bit_component) {
125 const double component = eight_bit_component / 255.0;
126 return (component <= 0.03928) ?
127 (component / 12.92) : pow((component + 0.055) / 1.055, 2.4);
128 }
129
130 double RelativeLuminance(SkColor color) {
131 return (0.2126 * ConvertSRGB(SkColorGetR(color))) +
132 (0.7152 * ConvertSRGB(SkColorGetG(color))) +
133 (0.0722 * ConvertSRGB(SkColorGetB(color)));
134 }
135
136 double ContrastRatio(SkColor color1, SkColor color2) {
137 const double l1 = RelativeLuminance(color1) + 0.05;
138 const double l2 = RelativeLuminance(color2) + 0.05;
139 return (l1 > l2) ? (l1 / l2) : (l2 / l1);
140 }
141
142 } // namespace
143
144 // ----------------------------------------------------------------------------
145
146 // Note: this works only for sRGB.
147 void SkColorToCIEXYZ(SkColor c, CIE_XYZ* xyz) {
148 uint8 r = SkColorGetR(c);
149 uint8 g = SkColorGetG(c);
150 uint8 b = SkColorGetB(c);
151
152 xyz->X =
brettw 2009/09/22 16:40:51 Can you indent the wrapped lines 2 more spaces whi
153 0.4124 * CIEConvertNonLinear(r) +
154 0.3576 * CIEConvertNonLinear(g) +
155 0.1805 * CIEConvertNonLinear(b);
156 xyz->Y =
157 0.2126 * CIEConvertNonLinear(r) +
158 0.7152 * CIEConvertNonLinear(g) +
159 0.0722 * CIEConvertNonLinear(g);
160 xyz->Z =
161 0.0193 * CIEConvertNonLinear(r) +
162 0.1192 * CIEConvertNonLinear(g) +
163 0.9505 * CIEConvertNonLinear(b);
164 }
165
166 SkColor CIEXYZToSkColor(SkAlpha alpha, const CIE_XYZ& xyz) {
167 double r_linear = 3.2410 * xyz.X - 1.5374 * xyz.Y - 0.4986 * xyz.Z;
168 double g_linear = -0.9692 * xyz.X + 1.8760 * xyz.Y + 0.0416 * xyz.Z;
169 double b_linear = 0.0556 * xyz.X - 0.2040 * xyz.Y + 1.0570 * xyz.Z;
170 uint8 r = sRGBColorComponentFromLinearComponent(r_linear);
171 uint8 g = sRGBColorComponentFromLinearComponent(g_linear);
172 uint8 b = sRGBColorComponentFromLinearComponent(b_linear);
173 return SkColorSetARGB(alpha, r, g, b);
153 } 174 }
154 175
155 void SkColorToLabColor(SkColor c, LabColor* lab) { 176 void SkColorToLabColor(SkColor c, LabColor* lab) {
156 CIE_XYZ xyz; 177 CIE_XYZ xyz;
157 SkColorToCIEXYZ(c, &xyz); 178 SkColorToCIEXYZ(c, &xyz);
158 CIEXYZToLabColor(xyz, lab); 179 CIEXYZToLabColor(xyz, lab);
159 } 180 }
160 181
161 SkColor LabColorToSkColor(const LabColor& lab, SkAlpha alpha) { 182 SkColor LabColorToSkColor(const LabColor& lab, SkAlpha alpha) {
162 CIE_XYZ xyz; 183 CIE_XYZ xyz;
163 LabColorToCIEXYZ(lab, &xyz); 184 LabColorToCIEXYZ(lab, &xyz);
164 return CIEXYZToSkColor(alpha, xyz); 185 return CIEXYZToSkColor(alpha, xyz);
165 } 186 }
166 187
167 static const int kCloseToBoundary = 64; 188 void CIEXYZToLabColor(const CIE_XYZ& xyz, LabColor* lab) {
168 static const int kAverageBoundary = 15; 189 CIE_XYZ white_xyz;
190 SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz);
191 double fx = LabConvertNonLinear(xyz.X / white_xyz.X);
192 double fy = LabConvertNonLinear(xyz.Y / white_xyz.Y);
193 double fz = LabConvertNonLinear(xyz.Z / white_xyz.Z);
194 lab->L = static_cast<int>(116 * fy) - 16;
195 lab->a = static_cast<int>(500 * (fx - fy));
196 lab->b = static_cast<int>(200 * (fy - fz));
197 }
198
199 void LabColorToCIEXYZ(const LabColor& lab, CIE_XYZ* xyz) {
200 CIE_XYZ result;
201
202 CIE_XYZ white_xyz;
203 SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz);
204
205 result.X = gen_xr(lab) * white_xyz.X;
206 result.Y = gen_yr(lab) * white_xyz.Y;
207 result.Z = gen_zr(lab) * white_xyz.Z;
208
209 *xyz = result;
210 }
169 211
170 bool IsColorCloseToTransparent(SkAlpha alpha) { 212 bool IsColorCloseToTransparent(SkAlpha alpha) {
213 const int kCloseToBoundary = 64;
171 return alpha < kCloseToBoundary; 214 return alpha < kCloseToBoundary;
172 } 215 }
173 216
174 bool IsColorCloseToGrey(int r, int g, int b) { 217 bool IsColorCloseToGrey(int r, int g, int b) {
218 const int kAverageBoundary = 15;
175 int average = (r + g + b) / 3; 219 int average = (r + g + b) / 3;
176 return (abs(r - average) < kAverageBoundary) && 220 return (abs(r - average) < kAverageBoundary) &&
177 (abs(g - average) < kAverageBoundary) && 221 (abs(g - average) < kAverageBoundary) &&
178 (abs(b - average) < kAverageBoundary); 222 (abs(b - average) < kAverageBoundary);
179 } 223 }
180 224
181 SkColor GetAverageColorOfFavicon(SkBitmap* favicon, SkAlpha alpha) { 225 SkColor GetAverageColorOfFavicon(SkBitmap* favicon, SkAlpha alpha) {
182 int r = 0, g = 0, b = 0; 226 int r = 0, g = 0, b = 0;
183 227
184 SkAutoLockPixels favicon_lock(*favicon); 228 SkAutoLockPixels favicon_lock(*favicon);
(...skipping 29 matching lines...) Expand all
214 result = SkColorSetARGB(alpha, 258 result = SkColorSetARGB(alpha,
215 r / color_count, 259 r / color_count,
216 g / color_count, 260 g / color_count,
217 b / color_count); 261 b / color_count);
218 } else { 262 } else {
219 result = SkColorSetARGB(alpha, 0, 0, 0); 263 result = SkColorSetARGB(alpha, 0, 0, 0);
220 } 264 }
221 return result; 265 return result;
222 } 266 }
223 267
224 inline int GetLumaForColor(SkColor* color) {
225 int r = SkColorGetR(*color);
226 int g = SkColorGetG(*color);
227 int b = SkColorGetB(*color);
228
229 int luma = static_cast<int>(0.3*r + 0.59*g + 0.11*b);
230 if (luma < 0)
231 luma = 0;
232 else if (luma > 255)
233 luma = 255;
234
235 return luma;
236 }
237
238 void BuildLumaHistogram(SkBitmap* bitmap, int histogram[256]) { 268 void BuildLumaHistogram(SkBitmap* bitmap, int histogram[256]) {
239 SkAutoLockPixels bitmap_lock(*bitmap); 269 SkAutoLockPixels bitmap_lock(*bitmap);
240 // Assume ARGB_8888 format. 270 // Assume ARGB_8888 format.
241 DCHECK(bitmap->getConfig() == SkBitmap::kARGB_8888_Config); 271 DCHECK(bitmap->getConfig() == SkBitmap::kARGB_8888_Config);
242 272
243 int pixel_width = bitmap->width(); 273 int pixel_width = bitmap->width();
244 int pixel_height = bitmap->height(); 274 int pixel_height = bitmap->height();
245 for (int y = 0; y < pixel_height; ++y) { 275 for (int y = 0; y < pixel_height; ++y) {
246 SkColor* current_color = static_cast<uint32_t*>(bitmap->getAddr32(0, y)); 276 SkColor* current_color = static_cast<uint32_t*>(bitmap->getAddr32(0, y));
247 for (int x = 0; x < pixel_width; ++x, ++current_color) { 277 for (int x = 0; x < pixel_width; ++x, ++current_color) {
(...skipping 10 matching lines...) Expand all
258 288
259 return SkColorSetRGB( 289 return SkColorSetRGB(
260 ((SkColorGetR(foreground) * alpha) + 290 ((SkColorGetR(foreground) * alpha) +
261 (SkColorGetR(background) * (0xFF - alpha))) / 0xFF, 291 (SkColorGetR(background) * (0xFF - alpha))) / 0xFF,
262 ((SkColorGetG(foreground) * alpha) + 292 ((SkColorGetG(foreground) * alpha) +
263 (SkColorGetG(background) * (0xFF - alpha))) / 0xFF, 293 (SkColorGetG(background) * (0xFF - alpha))) / 0xFF,
264 ((SkColorGetB(foreground) * alpha) + 294 ((SkColorGetB(foreground) * alpha) +
265 (SkColorGetB(background) * (0xFF - alpha))) / 0xFF); 295 (SkColorGetB(background) * (0xFF - alpha))) / 0xFF);
266 } 296 }
267 297
268 // Next three functions' formulas from:
269 // http://www.w3.org/TR/WCAG20/#relativeluminancedef
270 // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
271 static double ConvertSRGB(double eight_bit_component) {
272 const double component = eight_bit_component / 255.0;
273 return (component <= 0.03928) ?
274 (component / 12.92) : pow((component + 0.055) / 1.055, 2.4);
275 }
276
277 static double RelativeLuminance(SkColor color) {
278 return (0.2126 * ConvertSRGB(SkColorGetR(color))) +
279 (0.7152 * ConvertSRGB(SkColorGetG(color))) +
280 (0.0722 * ConvertSRGB(SkColorGetB(color)));
281 }
282
283 static double ContrastRatio(SkColor color1, SkColor color2) {
284 const double l1 = RelativeLuminance(color1) + 0.05;
285 const double l2 = RelativeLuminance(color2) + 0.05;
286 return (l1 > l2) ? (l1 / l2) : (l2 / l1);
287 }
288
289 SkColor PickMoreReadableColor(SkColor foreground1, 298 SkColor PickMoreReadableColor(SkColor foreground1,
290 SkColor foreground2, 299 SkColor foreground2,
291 SkColor background) { 300 SkColor background) {
292 return (ContrastRatio(foreground1, background) >= 301 return (ContrastRatio(foreground1, background) >=
293 ContrastRatio(foreground2, background)) ? foreground1 : foreground2; 302 ContrastRatio(foreground2, background)) ? foreground1 : foreground2;
294 } 303 }
295 304
296 SkColor GetSysSkColor(int which) { 305 SkColor GetSysSkColor(int which) {
297 #if defined(OS_WIN) 306 #if defined(OS_WIN)
298 return skia::COLORREFToSkColor(::GetSysColor(which)); 307 return skia::COLORREFToSkColor(::GetSysColor(which));
299 #else 308 #else
300 NOTIMPLEMENTED(); 309 NOTIMPLEMENTED();
301 return SK_ColorLTGRAY; 310 return SK_ColorLTGRAY;
302 #endif 311 #endif
303 } 312 }
304 313
305 } // namespace color_utils 314 } // namespace color_utils
OLDNEW
« no previous file with comments | « app/gfx/color_utils.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698