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

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

Issue 214054: Eliminate a bunch of color conversions. I was going to try and clean up the ... (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) 2009 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 ----------------------------------------------------------- 22 // Helper functions -----------------------------------------------------------
23 23
24 namespace { 24 namespace {
25 25
26 // These transformations are based on the equations in:
27 // http://en.wikipedia.org/wiki/Lab_color
28 // http://en.wikipedia.org/wiki/SRGB_color_space#Specification_of_the_transforma tion
29 // See also:
30 // http://www.brucelindbloom.com/index.html?ColorCalculator.html
31
32 const double kCIEConversionAlpha = 0.055;
33 const double kCIEConversionGamma = 2.2;
34 const double kE = 0.008856;
35 const double kK = 903.3;
36
37 double CIEConvertNonLinear(uint8 color_component) {
38 double color_component_d = static_cast<double>(color_component) / 255.0;
39 if (color_component_d > 0.04045) {
40 double base = (color_component_d + kCIEConversionAlpha) /
41 (1 + kCIEConversionAlpha);
42 return pow(base, kCIEConversionGamma);
43 } else {
44 return color_component_d / 12.92;
45 }
46 }
47
48 uint8 sRGBColorComponentFromLinearComponent(double component) {
49 double result;
50 if (component <= 0.0031308) {
51 result = 12.92 * component;
52 } else {
53 result = (1 + kCIEConversionAlpha) *
54 pow(component, (static_cast<double>(1) / 2.4)) -
55 kCIEConversionAlpha;
56 }
57 return std::min(static_cast<uint8>(255), static_cast<uint8>(result * 255));
58 }
59
60 double LabConvertNonLinear(double value) {
61 if (value > 0.008856) {
62 double goat = pow(value, static_cast<double>(1) / 3);
63 return goat;
64 }
65 return (kK * value + 16) / 116;
66 }
67
68 double gen_yr(const LabColor& lab) {
69 if (lab.L > (kE * kK))
70 return pow((lab.L + 16.0) / 116, 3.0);
71 return static_cast<double>(lab.L) / kK;
72 }
73
74 double fy(const LabColor& lab) {
75 double yr = gen_yr(lab);
76 if (yr > kE)
77 return (lab.L + 16.0) / 116;
78 return (kK * yr + 16.0) / 116;
79 }
80
81 double fx(const LabColor& lab) {
82 return (static_cast<double>(lab.a) / 500) + fy(lab);
83 }
84
85 double gen_xr(const LabColor& lab) {
86 double x = fx(lab);
87 double x_cubed = pow(x, 3.0);
88 if (x_cubed > kE)
89 return x_cubed;
90 return (116.0 * x - 16.0) / kK;
91 }
92
93 double fz(const LabColor& lab) {
94 return fy(lab) - (static_cast<double>(lab.b) / 200);
95 }
96
97 double gen_zr(const LabColor& lab) {
98 double z = fz(lab);
99 double z_cubed = pow(z, 3.0);
100 if (z_cubed > kE)
101 return z_cubed;
102 return (116.0 * z - 16.0) / kK;
103 }
104
105 int GetLumaForColor(SkColor* color) { 26 int GetLumaForColor(SkColor* color) {
106 int r = SkColorGetR(*color); 27 int luma = static_cast<int>((0.3 * SkColorGetR(*color)) +
107 int g = SkColorGetG(*color); 28 (0.59 * SkColorGetG(*color)) +
108 int b = SkColorGetB(*color); 29 (0.11 * SkColorGetB(*color)));
109 30 return std::max(std::min(luma, 255), 0);
110 int luma = static_cast<int>(0.3*r + 0.59*g + 0.11*b);
111 if (luma < 0)
112 luma = 0;
113 else if (luma > 255)
114 luma = 255;
115
116 return luma;
117 } 31 }
118 32
119 // Next three functions' formulas from: 33 // Next three functions' formulas from:
120 // http://www.w3.org/TR/WCAG20/#relativeluminancedef 34 // http://www.w3.org/TR/WCAG20/#relativeluminancedef
121 // http://www.w3.org/TR/WCAG20/#contrast-ratiodef 35 // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
122 36
123 double ConvertSRGB(double eight_bit_component) { 37 double ConvertSRGB(double eight_bit_component) {
124 const double component = eight_bit_component / 255.0; 38 const double component = eight_bit_component / 255.0;
125 return (component <= 0.03928) ? 39 return (component <= 0.03928) ?
126 (component / 12.92) : pow((component + 0.055) / 1.055, 2.4); 40 (component / 12.92) : pow((component + 0.055) / 1.055, 2.4);
127 } 41 }
128 42
129 double RelativeLuminance(SkColor color) { 43 double RelativeLuminance(SkColor color) {
130 return (0.2126 * ConvertSRGB(SkColorGetR(color))) + 44 return (0.2126 * ConvertSRGB(SkColorGetR(color))) +
131 (0.7152 * ConvertSRGB(SkColorGetG(color))) + 45 (0.7152 * ConvertSRGB(SkColorGetG(color))) +
132 (0.0722 * ConvertSRGB(SkColorGetB(color))); 46 (0.0722 * ConvertSRGB(SkColorGetB(color)));
133 } 47 }
134 48
135 double ContrastRatio(SkColor color1, SkColor color2) { 49 double ContrastRatio(SkColor color1, SkColor color2) {
136 const double l1 = RelativeLuminance(color1) + 0.05; 50 const double l1 = RelativeLuminance(color1) + 0.05;
137 const double l2 = RelativeLuminance(color2) + 0.05; 51 const double l2 = RelativeLuminance(color2) + 0.05;
138 return (l1 > l2) ? (l1 / l2) : (l2 / l1); 52 return (l1 > l2) ? (l1 / l2) : (l2 / l1);
139 } 53 }
140 54
141 } // namespace 55 } // namespace
142 56
143 // ---------------------------------------------------------------------------- 57 // ----------------------------------------------------------------------------
144 58
145 // Note: this works only for sRGB.
146 void SkColorToCIEXYZ(SkColor c, CIE_XYZ* xyz) {
147 uint8 r = SkColorGetR(c);
148 uint8 g = SkColorGetG(c);
149 uint8 b = SkColorGetB(c);
150
151 xyz->X = 0.4124 * CIEConvertNonLinear(r) +
152 0.3576 * CIEConvertNonLinear(g) +
153 0.1805 * CIEConvertNonLinear(b);
154 xyz->Y = 0.2126 * CIEConvertNonLinear(r) +
155 0.7152 * CIEConvertNonLinear(g) +
156 0.0722 * CIEConvertNonLinear(g);
157 xyz->Z = 0.0193 * CIEConvertNonLinear(r) +
158 0.1192 * CIEConvertNonLinear(g) +
159 0.9505 * CIEConvertNonLinear(b);
160 }
161
162 SkColor CIEXYZToSkColor(SkAlpha alpha, const CIE_XYZ& xyz) {
163 double r_linear = 3.2410 * xyz.X - 1.5374 * xyz.Y - 0.4986 * xyz.Z;
164 double g_linear = -0.9692 * xyz.X + 1.8760 * xyz.Y + 0.0416 * xyz.Z;
165 double b_linear = 0.0556 * xyz.X - 0.2040 * xyz.Y + 1.0570 * xyz.Z;
166 uint8 r = sRGBColorComponentFromLinearComponent(r_linear);
167 uint8 g = sRGBColorComponentFromLinearComponent(g_linear);
168 uint8 b = sRGBColorComponentFromLinearComponent(b_linear);
169 return SkColorSetARGB(alpha, r, g, b);
170 }
171
172 void SkColorToLabColor(SkColor c, LabColor* lab) {
173 CIE_XYZ xyz;
174 SkColorToCIEXYZ(c, &xyz);
175 CIEXYZToLabColor(xyz, lab);
176 }
177
178 SkColor LabColorToSkColor(const LabColor& lab, SkAlpha alpha) {
179 CIE_XYZ xyz;
180 LabColorToCIEXYZ(lab, &xyz);
181 return CIEXYZToSkColor(alpha, xyz);
182 }
183
184 void CIEXYZToLabColor(const CIE_XYZ& xyz, LabColor* lab) {
185 CIE_XYZ white_xyz;
186 SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz);
187 double fx = LabConvertNonLinear(xyz.X / white_xyz.X);
188 double fy = LabConvertNonLinear(xyz.Y / white_xyz.Y);
189 double fz = LabConvertNonLinear(xyz.Z / white_xyz.Z);
190 lab->L = static_cast<int>(116 * fy) - 16;
191 lab->a = static_cast<int>(500 * (fx - fy));
192 lab->b = static_cast<int>(200 * (fy - fz));
193 }
194
195 void LabColorToCIEXYZ(const LabColor& lab, CIE_XYZ* xyz) {
196 CIE_XYZ result;
197
198 CIE_XYZ white_xyz;
199 SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz);
200
201 result.X = gen_xr(lab) * white_xyz.X;
202 result.Y = gen_yr(lab) * white_xyz.Y;
203 result.Z = gen_zr(lab) * white_xyz.Z;
204
205 *xyz = result;
206 }
207
208 bool IsColorCloseToTransparent(SkAlpha alpha) { 59 bool IsColorCloseToTransparent(SkAlpha alpha) {
209 const int kCloseToBoundary = 64; 60 const int kCloseToBoundary = 64;
210 return alpha < kCloseToBoundary; 61 return alpha < kCloseToBoundary;
211 } 62 }
212 63
213 bool IsColorCloseToGrey(int r, int g, int b) { 64 bool IsColorCloseToGrey(int r, int g, int b) {
214 const int kAverageBoundary = 15; 65 const int kAverageBoundary = 15;
215 int average = (r + g + b) / 3; 66 int average = (r + g + b) / 3;
216 return (abs(r - average) < kAverageBoundary) && 67 return (abs(r - average) < kAverageBoundary) &&
217 (abs(g - average) < kAverageBoundary) && 68 (abs(g - average) < kAverageBoundary) &&
(...skipping 24 matching lines...) Expand all
242 if (IsColorCloseToTransparent(SkColorGetA(*current_color)) || 93 if (IsColorCloseToTransparent(SkColorGetA(*current_color)) ||
243 IsColorCloseToGrey(cr, cg, cb)) 94 IsColorCloseToGrey(cr, cg, cb))
244 continue; 95 continue;
245 96
246 r += cr; 97 r += cr;
247 g += cg; 98 g += cg;
248 b += cb; 99 b += cb;
249 ++color_count; 100 ++color_count;
250 } 101 }
251 102
252 SkColor result; 103 return color_count ?
253 if (color_count > 0) { 104 SkColorSetARGB(alpha, r / color_count, g / color_count, b / color_count) :
254 result = SkColorSetARGB(alpha, 105 SkColorSetARGB(alpha, 0, 0, 0);
255 r / color_count,
256 g / color_count,
257 b / color_count);
258 } else {
259 result = SkColorSetARGB(alpha, 0, 0, 0);
260 }
261 return result;
262 } 106 }
263 107
264 void BuildLumaHistogram(SkBitmap* bitmap, int histogram[256]) { 108 void BuildLumaHistogram(SkBitmap* bitmap, int histogram[256]) {
265 SkAutoLockPixels bitmap_lock(*bitmap); 109 SkAutoLockPixels bitmap_lock(*bitmap);
266 // Assume ARGB_8888 format. 110 // Assume ARGB_8888 format.
267 DCHECK(bitmap->getConfig() == SkBitmap::kARGB_8888_Config); 111 DCHECK(bitmap->getConfig() == SkBitmap::kARGB_8888_Config);
268 112
269 int pixel_width = bitmap->width(); 113 int pixel_width = bitmap->width();
270 int pixel_height = bitmap->height(); 114 int pixel_height = bitmap->height();
271 for (int y = 0; y < pixel_height; ++y) { 115 for (int y = 0; y < pixel_height; ++y) {
272 SkColor* current_color = static_cast<uint32_t*>(bitmap->getAddr32(0, y)); 116 SkColor* current_color = static_cast<uint32_t*>(bitmap->getAddr32(0, y));
273 for (int x = 0; x < pixel_width; ++x, ++current_color) { 117 for (int x = 0; x < pixel_width; ++x, ++current_color)
274 histogram[GetLumaForColor(current_color)]++; 118 histogram[GetLumaForColor(current_color)]++;
275 }
276 } 119 }
277 } 120 }
278 121
279 SkColor AlphaBlend(SkColor foreground, SkColor background, SkAlpha alpha) { 122 SkColor AlphaBlend(SkColor foreground, SkColor background, SkAlpha alpha) {
280 if (alpha == 0) 123 if (alpha == 0)
281 return background; 124 return background;
282 else if (alpha == 0xFF) 125 if (alpha == 255)
283 return foreground; 126 return foreground;
284
285 return SkColorSetRGB( 127 return SkColorSetRGB(
286 ((SkColorGetR(foreground) * alpha) + 128 ((SkColorGetR(foreground) * alpha) +
287 (SkColorGetR(background) * (0xFF - alpha))) / 0xFF, 129 (SkColorGetR(background) * (255 - alpha))) / 255,
288 ((SkColorGetG(foreground) * alpha) + 130 ((SkColorGetG(foreground) * alpha) +
289 (SkColorGetG(background) * (0xFF - alpha))) / 0xFF, 131 (SkColorGetG(background) * (255 - alpha))) / 255,
290 ((SkColorGetB(foreground) * alpha) + 132 ((SkColorGetB(foreground) * alpha) +
291 (SkColorGetB(background) * (0xFF - alpha))) / 0xFF); 133 (SkColorGetB(background) * (255 - alpha))) / 255);
292 } 134 }
293 135
294 SkColor PickMoreReadableColor(SkColor foreground1, 136 SkColor PickMoreReadableColor(SkColor foreground1,
295 SkColor foreground2, 137 SkColor foreground2,
296 SkColor background) { 138 SkColor background) {
297 return (ContrastRatio(foreground1, background) >= 139 return (ContrastRatio(foreground1, background) >=
298 ContrastRatio(foreground2, background)) ? foreground1 : foreground2; 140 ContrastRatio(foreground2, background)) ? foreground1 : foreground2;
299 } 141 }
300 142
301 SkColor GetSysSkColor(int which) { 143 SkColor GetSysSkColor(int which) {
302 #if defined(OS_WIN) 144 #if defined(OS_WIN)
303 return skia::COLORREFToSkColor(::GetSysColor(which)); 145 return skia::COLORREFToSkColor(GetSysColor(which));
304 #else 146 #else
305 NOTIMPLEMENTED(); 147 NOTIMPLEMENTED();
306 return SK_ColorLTGRAY; 148 return SK_ColorLTGRAY;
307 #endif 149 #endif
308 } 150 }
309 151
310 } // namespace color_utils 152 } // 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