Chromium Code Reviews| Index: app/gfx/color_utils.cc |
| =================================================================== |
| --- app/gfx/color_utils.cc (revision 26699) |
| +++ app/gfx/color_utils.cc (working copy) |
| @@ -1,4 +1,4 @@ |
| -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| @@ -19,18 +19,23 @@ |
| namespace color_utils { |
| +// Helper functions ----------------------------------------------------------- |
| + |
| +namespace { |
| + |
| // These transformations are based on the equations in: |
| // http://en.wikipedia.org/wiki/Lab_color |
| -// http://en.wikipedia.org/wiki/SRGB_color_space#Specification_of_the_transformation |
| +// 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
|
| +// Specification_of_the_transformation |
| // See also: |
| // http://www.brucelindbloom.com/index.html?ColorCalculator.html |
| -static const double kCIEConversionAlpha = 0.055; |
| -static const double kCIEConversionGamma = 2.2; |
| -static const double kE = 0.008856; |
| -static const double kK = 903.3; |
| +const double kCIEConversionAlpha = 0.055; |
| +const double kCIEConversionGamma = 2.2; |
| +const double kE = 0.008856; |
| +const double kK = 903.3; |
| -static double CIEConvertNonLinear(uint8 color_component) { |
| +double CIEConvertNonLinear(uint8 color_component) { |
| double color_component_d = static_cast<double>(color_component) / 255.0; |
| if (color_component_d > 0.04045) { |
| double base = (color_component_d + kCIEConversionAlpha) / |
| @@ -41,46 +46,7 @@ |
| } |
| } |
| -// Note: this works only for sRGB. |
| -void SkColorToCIEXYZ(SkColor c, CIE_XYZ* xyz) { |
| - uint8 r = SkColorGetR(c); |
| - uint8 g = SkColorGetG(c); |
| - uint8 b = SkColorGetB(c); |
| - |
| - xyz->X = |
| - 0.4124 * CIEConvertNonLinear(r) + |
| - 0.3576 * CIEConvertNonLinear(g) + |
| - 0.1805 * CIEConvertNonLinear(b); |
| - xyz->Y = |
| - 0.2126 * CIEConvertNonLinear(r) + |
| - 0.7152 * CIEConvertNonLinear(g) + |
| - 0.0722 * CIEConvertNonLinear(g); |
| - xyz->Z = |
| - 0.0193 * CIEConvertNonLinear(r) + |
| - 0.1192 * CIEConvertNonLinear(g) + |
| - 0.9505 * CIEConvertNonLinear(b); |
| -} |
| - |
| -static double LabConvertNonLinear(double value) { |
| - if (value > 0.008856) { |
| - double goat = pow(value, static_cast<double>(1) / 3); |
| - return goat; |
| - } |
| - return (kK * value + 16) / 116; |
| -} |
| - |
| -void CIEXYZToLabColor(const CIE_XYZ& xyz, LabColor* lab) { |
| - CIE_XYZ white_xyz; |
| - SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz); |
| - double fx = LabConvertNonLinear(xyz.X / white_xyz.X); |
| - double fy = LabConvertNonLinear(xyz.Y / white_xyz.Y); |
| - double fz = LabConvertNonLinear(xyz.Z / white_xyz.Z); |
| - lab->L = static_cast<int>(116 * fy) - 16; |
| - lab->a = static_cast<int>(500 * (fx - fy)); |
| - lab->b = static_cast<int>(200 * (fy - fz)); |
| -} |
| - |
| -static uint8 sRGBColorComponentFromLinearComponent(double component) { |
| +uint8 sRGBColorComponentFromLinearComponent(double component) { |
| double result; |
| if (component <= 0.0031308) { |
| result = 12.92 * component; |
| @@ -92,34 +58,32 @@ |
| return std::min(static_cast<uint8>(255), static_cast<uint8>(result * 255)); |
| } |
| -SkColor CIEXYZToSkColor(SkAlpha alpha, const CIE_XYZ& xyz) { |
| - double r_linear = 3.2410 * xyz.X - 1.5374 * xyz.Y - 0.4986 * xyz.Z; |
| - double g_linear = -0.9692 * xyz.X + 1.8760 * xyz.Y + 0.0416 * xyz.Z; |
| - double b_linear = 0.0556 * xyz.X - 0.2040 * xyz.Y + 1.0570 * xyz.Z; |
| - uint8 r = sRGBColorComponentFromLinearComponent(r_linear); |
| - uint8 g = sRGBColorComponentFromLinearComponent(g_linear); |
| - uint8 b = sRGBColorComponentFromLinearComponent(b_linear); |
| - return SkColorSetARGB(alpha, r, g, b); |
| +double LabConvertNonLinear(double value) { |
| + if (value > 0.008856) { |
| + double goat = pow(value, static_cast<double>(1) / 3); |
| + return goat; |
| + } |
| + return (kK * value + 16) / 116; |
| } |
| -static double gen_yr(const LabColor& lab) { |
| +double gen_yr(const LabColor& lab) { |
| if (lab.L > (kE * kK)) |
| return pow((lab.L + 16.0) / 116, 3.0); |
| return static_cast<double>(lab.L) / kK; |
| } |
| -static double fy(const LabColor& lab) { |
| +double fy(const LabColor& lab) { |
| double yr = gen_yr(lab); |
| if (yr > kE) |
| return (lab.L + 16.0) / 116; |
| return (kK * yr + 16.0) / 116; |
| } |
| -static double fx(const LabColor& lab) { |
| +double fx(const LabColor& lab) { |
| return (static_cast<double>(lab.a) / 500) + fy(lab); |
| } |
| -static double gen_xr(const LabColor& lab) { |
| +double gen_xr(const LabColor& lab) { |
| double x = fx(lab); |
| double x_cubed = pow(x, 3.0); |
| if (x_cubed > kE) |
| @@ -127,11 +91,11 @@ |
| return (116.0 * x - 16.0) / kK; |
| } |
| -static double fz(const LabColor& lab) { |
| +double fz(const LabColor& lab) { |
| return fy(lab) - (static_cast<double>(lab.b) / 200); |
| } |
| -static double gen_zr(const LabColor& lab) { |
| +double gen_zr(const LabColor& lab) { |
| double z = fz(lab); |
| double z_cubed = pow(z, 3.0); |
| if (z_cubed > kE) |
| @@ -139,19 +103,76 @@ |
| return (116.0 * z - 16.0) / kK; |
| } |
| -void LabColorToCIEXYZ(const LabColor& lab, CIE_XYZ* xyz) { |
| - CIE_XYZ result; |
| +int GetLumaForColor(SkColor* color) { |
| + int r = SkColorGetR(*color); |
| + int g = SkColorGetG(*color); |
| + int b = SkColorGetB(*color); |
| - CIE_XYZ white_xyz; |
| - SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz); |
| + int luma = static_cast<int>(0.3*r + 0.59*g + 0.11*b); |
| + if (luma < 0) |
| + luma = 0; |
| + else if (luma > 255) |
| + luma = 255; |
| - result.X = gen_xr(lab) * white_xyz.X; |
| - result.Y = gen_yr(lab) * white_xyz.Y; |
| - result.Z = gen_zr(lab) * white_xyz.Z; |
| + return luma; |
| +} |
| - *xyz = result; |
| +// Next three functions' formulas from: |
| +// http://www.w3.org/TR/WCAG20/#relativeluminancedef |
| +// http://www.w3.org/TR/WCAG20/#contrast-ratiodef |
| + |
| +double ConvertSRGB(double eight_bit_component) { |
| + const double component = eight_bit_component / 255.0; |
| + return (component <= 0.03928) ? |
| + (component / 12.92) : pow((component + 0.055) / 1.055, 2.4); |
| } |
| +double RelativeLuminance(SkColor color) { |
| + return (0.2126 * ConvertSRGB(SkColorGetR(color))) + |
| + (0.7152 * ConvertSRGB(SkColorGetG(color))) + |
| + (0.0722 * ConvertSRGB(SkColorGetB(color))); |
| +} |
| + |
| +double ContrastRatio(SkColor color1, SkColor color2) { |
| + const double l1 = RelativeLuminance(color1) + 0.05; |
| + const double l2 = RelativeLuminance(color2) + 0.05; |
| + return (l1 > l2) ? (l1 / l2) : (l2 / l1); |
| +} |
| + |
| +} // namespace |
| + |
| +// ---------------------------------------------------------------------------- |
| + |
| +// Note: this works only for sRGB. |
| +void SkColorToCIEXYZ(SkColor c, CIE_XYZ* xyz) { |
| + uint8 r = SkColorGetR(c); |
| + uint8 g = SkColorGetG(c); |
| + uint8 b = SkColorGetB(c); |
| + |
| + xyz->X = |
|
brettw
2009/09/22 16:40:51
Can you indent the wrapped lines 2 more spaces whi
|
| + 0.4124 * CIEConvertNonLinear(r) + |
| + 0.3576 * CIEConvertNonLinear(g) + |
| + 0.1805 * CIEConvertNonLinear(b); |
| + xyz->Y = |
| + 0.2126 * CIEConvertNonLinear(r) + |
| + 0.7152 * CIEConvertNonLinear(g) + |
| + 0.0722 * CIEConvertNonLinear(g); |
| + xyz->Z = |
| + 0.0193 * CIEConvertNonLinear(r) + |
| + 0.1192 * CIEConvertNonLinear(g) + |
| + 0.9505 * CIEConvertNonLinear(b); |
| +} |
| + |
| +SkColor CIEXYZToSkColor(SkAlpha alpha, const CIE_XYZ& xyz) { |
| + double r_linear = 3.2410 * xyz.X - 1.5374 * xyz.Y - 0.4986 * xyz.Z; |
| + double g_linear = -0.9692 * xyz.X + 1.8760 * xyz.Y + 0.0416 * xyz.Z; |
| + double b_linear = 0.0556 * xyz.X - 0.2040 * xyz.Y + 1.0570 * xyz.Z; |
| + uint8 r = sRGBColorComponentFromLinearComponent(r_linear); |
| + uint8 g = sRGBColorComponentFromLinearComponent(g_linear); |
| + uint8 b = sRGBColorComponentFromLinearComponent(b_linear); |
| + return SkColorSetARGB(alpha, r, g, b); |
| +} |
| + |
| void SkColorToLabColor(SkColor c, LabColor* lab) { |
| CIE_XYZ xyz; |
| SkColorToCIEXYZ(c, &xyz); |
| @@ -164,14 +185,37 @@ |
| return CIEXYZToSkColor(alpha, xyz); |
| } |
| -static const int kCloseToBoundary = 64; |
| -static const int kAverageBoundary = 15; |
| +void CIEXYZToLabColor(const CIE_XYZ& xyz, LabColor* lab) { |
| + CIE_XYZ white_xyz; |
| + SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz); |
| + double fx = LabConvertNonLinear(xyz.X / white_xyz.X); |
| + double fy = LabConvertNonLinear(xyz.Y / white_xyz.Y); |
| + double fz = LabConvertNonLinear(xyz.Z / white_xyz.Z); |
| + lab->L = static_cast<int>(116 * fy) - 16; |
| + lab->a = static_cast<int>(500 * (fx - fy)); |
| + lab->b = static_cast<int>(200 * (fy - fz)); |
| +} |
| +void LabColorToCIEXYZ(const LabColor& lab, CIE_XYZ* xyz) { |
| + CIE_XYZ result; |
| + |
| + CIE_XYZ white_xyz; |
| + SkColorToCIEXYZ(SkColorSetRGB(255, 255, 255), &white_xyz); |
| + |
| + result.X = gen_xr(lab) * white_xyz.X; |
| + result.Y = gen_yr(lab) * white_xyz.Y; |
| + result.Z = gen_zr(lab) * white_xyz.Z; |
| + |
| + *xyz = result; |
| +} |
| + |
| bool IsColorCloseToTransparent(SkAlpha alpha) { |
| + const int kCloseToBoundary = 64; |
| return alpha < kCloseToBoundary; |
| } |
| bool IsColorCloseToGrey(int r, int g, int b) { |
| + const int kAverageBoundary = 15; |
| int average = (r + g + b) / 3; |
| return (abs(r - average) < kAverageBoundary) && |
| (abs(g - average) < kAverageBoundary) && |
| @@ -221,20 +265,6 @@ |
| return result; |
| } |
| -inline int GetLumaForColor(SkColor* color) { |
| - int r = SkColorGetR(*color); |
| - int g = SkColorGetG(*color); |
| - int b = SkColorGetB(*color); |
| - |
| - int luma = static_cast<int>(0.3*r + 0.59*g + 0.11*b); |
| - if (luma < 0) |
| - luma = 0; |
| - else if (luma > 255) |
| - luma = 255; |
| - |
| - return luma; |
| -} |
| - |
| void BuildLumaHistogram(SkBitmap* bitmap, int histogram[256]) { |
| SkAutoLockPixels bitmap_lock(*bitmap); |
| // Assume ARGB_8888 format. |
| @@ -265,27 +295,6 @@ |
| (SkColorGetB(background) * (0xFF - alpha))) / 0xFF); |
| } |
| -// Next three functions' formulas from: |
| -// http://www.w3.org/TR/WCAG20/#relativeluminancedef |
| -// http://www.w3.org/TR/WCAG20/#contrast-ratiodef |
| -static double ConvertSRGB(double eight_bit_component) { |
| - const double component = eight_bit_component / 255.0; |
| - return (component <= 0.03928) ? |
| - (component / 12.92) : pow((component + 0.055) / 1.055, 2.4); |
| -} |
| - |
| -static double RelativeLuminance(SkColor color) { |
| - return (0.2126 * ConvertSRGB(SkColorGetR(color))) + |
| - (0.7152 * ConvertSRGB(SkColorGetG(color))) + |
| - (0.0722 * ConvertSRGB(SkColorGetB(color))); |
| -} |
| - |
| -static double ContrastRatio(SkColor color1, SkColor color2) { |
| - const double l1 = RelativeLuminance(color1) + 0.05; |
| - const double l2 = RelativeLuminance(color2) + 0.05; |
| - return (l1 > l2) ? (l1 / l2) : (l2 / l1); |
| -} |
| - |
| SkColor PickMoreReadableColor(SkColor foreground1, |
| SkColor foreground2, |
| SkColor background) { |