15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/color_utils.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/skia_utils_win.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace color_utils { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper functions ----------------------------------------------------------- 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int calcHue(double temp1, double temp2, double hue) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hue < 0.0) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++hue; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (hue > 1.0) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --hue; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double result = temp1; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hue * 6.0 < 1.0) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = temp1 + (temp2 - temp1) * hue * 6.0; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (hue * 2.0 < 1.0) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = temp2; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (hue * 3.0 < 2.0) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = temp1 + (temp2 - temp1) * (2.0 / 3.0 - hue) * 6.0; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scale the result from 0 - 255 and round off the value. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(result * 255 + .5); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Next two functions' formulas from: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://www.w3.org/TR/WCAG20/#relativeluminancedef 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://www.w3.org/TR/WCAG20/#contrast-ratiodef 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double ConvertSRGB(double eight_bit_component) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const double component = eight_bit_component / 255.0; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (component <= 0.03928) ? 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (component / 12.92) : pow((component + 0.055) / 1.055, 2.4); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor LumaInvertColor(SkColor color) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HSL hsl; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColorToHSL(color, &hsl); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl.l = 1.0 - hsl.l; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HSLToSkColor(hsl, 255); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double ContrastRatio(double foreground_luminance, double background_luminance) { 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(foreground_luminance, 0.0); 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(background_luminance, 0.0); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) foreground_luminance += 0.05; 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) background_luminance += 0.05; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (foreground_luminance > background_luminance) ? 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (foreground_luminance / background_luminance) : 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (background_luminance / foreground_luminance); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------------- 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned char GetLuminanceForColor(SkColor color) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int luma = static_cast<int>((0.3 * SkColorGetR(color)) + 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (0.59 * SkColorGetG(color)) + 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (0.11 * SkColorGetB(color))); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max(std::min(luma, 255), 0); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double RelativeLuminance(SkColor color) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0.2126 * ConvertSRGB(SkColorGetR(color))) + 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (0.7152 * ConvertSRGB(SkColorGetG(color))) + 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (0.0722 * ConvertSRGB(SkColorGetB(color))); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkColorToHSL(SkColor c, HSL* hsl) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double r = static_cast<double>(SkColorGetR(c)) / 255.0; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double g = static_cast<double>(SkColorGetG(c)) / 255.0; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double b = static_cast<double>(SkColorGetB(c)) / 255.0; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double vmax = std::max(std::max(r, g), b); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double vmin = std::min(std::min(r, g), b); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double delta = vmax - vmin; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl->l = (vmax + vmin) / 2; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SkColorGetR(c) == SkColorGetG(c) && SkColorGetR(c) == SkColorGetB(c)) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl->h = hsl->s = 0; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double dr = (((vmax - r) / 6.0) + (delta / 2.0)) / delta; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double dg = (((vmax - g) / 6.0) + (delta / 2.0)) / delta; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double db = (((vmax - b) / 6.0) + (delta / 2.0)) / delta; 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // We need to compare for the max value because comparing vmax to r, g, or b 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // can sometimes result in values overflowing registers. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r >= g && r >= b) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl->h = db - dg; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (g >= r && g >= b) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl->h = (1.0 / 3.0) + dr - db; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else // (b >= r && b >= g) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl->h = (2.0 / 3.0) + dg - dr; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hsl->h < 0.0) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++hsl->h; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (hsl->h > 1.0) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --hsl->h; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl->s = delta / ((hsl->l < 0.5) ? (vmax + vmin) : (2 - vmax - vmin)); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor HSLToSkColor(const HSL& hsl, SkAlpha alpha) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double hue = hsl.h; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double saturation = hsl.s; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double lightness = hsl.l; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // If there's no color, we don't care about hue and can do everything based on 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // brightness. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!saturation) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 light; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lightness < 0) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) light = 0; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (lightness >= 1.0) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) light = 255; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) light = SkDoubleToFixed(lightness) >> 8; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkColorSetARGB(alpha, light, light, light); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double temp2 = (lightness < 0.5) ? 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (lightness * (1.0 + saturation)) : 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (lightness + saturation - (lightness * saturation)); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double temp1 = 2.0 * lightness - temp2; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkColorSetARGB(alpha, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) calcHue(temp1, temp2, hue + 1.0 / 3.0), 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) calcHue(temp1, temp2, hue), 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) calcHue(temp1, temp2, hue - 1.0 / 3.0)); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool IsWithinHSLRange(const HSL& hsl, 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const HSL& lower_bound, 15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const HSL& upper_bound) { 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(hsl.h >= 0 && hsl.h <= 1) << hsl.h; 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(hsl.s >= 0 && hsl.s <= 1) << hsl.s; 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(hsl.l >= 0 && hsl.l <= 1) << hsl.l; 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(lower_bound.h < 0 || upper_bound.h < 0 || 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) (lower_bound.h <= 1 && upper_bound.h <= lower_bound.h + 1)) 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << "lower_bound.h: " << lower_bound.h 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << ", upper_bound.h: " << upper_bound.h; 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(lower_bound.s < 0 || upper_bound.s < 0 || 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) (lower_bound.s <= upper_bound.s && upper_bound.s <= 1)) 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << "lower_bound.s: " << lower_bound.s 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << ", upper_bound.s: " << upper_bound.s; 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(lower_bound.l < 0 || upper_bound.l < 0 || 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) (lower_bound.l <= upper_bound.l && upper_bound.l <= 1)) 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << "lower_bound.l: " << lower_bound.l 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << ", upper_bound.l: " << upper_bound.l; 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // If the upper hue is >1, the given hue bounds wrap around at 1. 17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool matches_hue = upper_bound.h > 1 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ? hsl.h >= lower_bound.h || hsl.h <= upper_bound.h - 1 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : hsl.h >= lower_bound.h && hsl.h <= upper_bound.h; 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return (upper_bound.h < 0 || lower_bound.h < 0 || matches_hue) && 17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) (upper_bound.s < 0 || lower_bound.s < 0 || 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) (hsl.s >= lower_bound.s && hsl.s <= upper_bound.s)) && 18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) (upper_bound.l < 0 || lower_bound.l < 0 || 18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) (hsl.l >= lower_bound.l && hsl.l <= upper_bound.l)); 18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor HSLShift(SkColor color, const HSL& shift) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HSL hsl; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int alpha = SkColorGetA(color); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColorToHSL(color, &hsl); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the hue with the tint's hue. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift.h >= 0) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl.h = shift.h; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Change the saturation. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift.s >= 0) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift.s <= 0.5) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl.s *= shift.s * 2.0; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hsl.s += (1.0 - hsl.s) * ((shift.s - 0.5) * 2.0); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColor result = HSLToSkColor(hsl, alpha); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift.l < 0) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Lightness shifts in the style of popular image editors aren't actually 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // represented in HSL - the L value does have some effect on saturation. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double r = static_cast<double>(SkColorGetR(result)); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double g = static_cast<double>(SkColorGetG(result)); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double b = static_cast<double>(SkColorGetB(result)); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift.l <= 0.5) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r *= (shift.l * 2.0); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g *= (shift.l * 2.0); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) b *= (shift.l * 2.0); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r += (255.0 - r) * ((shift.l - 0.5) * 2.0); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g += (255.0 - g) * ((shift.l - 0.5) * 2.0); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) b += (255.0 - b) * ((shift.l - 0.5) * 2.0); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkColorSetARGB(alpha, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(r), 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(g), 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(b)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]) { 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(kN32_SkColorType, bitmap.colorType()); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkAutoLockPixels bitmap_lock(bitmap); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pixel_width = bitmap.width(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pixel_height = bitmap.height(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < pixel_height; ++y) { 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int x = 0; x < pixel_width; ++x) 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++histogram[GetLuminanceForColor(bitmap.getColor(x, y))]; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor AlphaBlend(SkColor foreground, SkColor background, SkAlpha alpha) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alpha == 0) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return background; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alpha == 255) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return foreground; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int f_alpha = SkColorGetA(foreground); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int b_alpha = SkColorGetA(background); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double normalizer = (f_alpha * alpha + b_alpha * (255 - alpha)) / 255.0; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (normalizer == 0.0) 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return SK_ColorTRANSPARENT; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double f_weight = f_alpha * alpha / normalizer; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double b_weight = b_alpha * (255 - alpha) / normalizer; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double r = (SkColorGetR(foreground) * f_weight + 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColorGetR(background) * b_weight) / 255.0; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double g = (SkColorGetG(foreground) * f_weight + 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColorGetG(background) * b_weight) / 255.0; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double b = (SkColorGetB(foreground) * f_weight + 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColorGetB(background) * b_weight) / 255.0; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkColorSetARGB(static_cast<int>(normalizer), 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(r), 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(g), 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(b)); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SkColor BlendTowardOppositeLuminance(SkColor color, SkAlpha alpha) { 2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) unsigned char background_luminance = 2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) color_utils::GetLuminanceForColor(color); 2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const SkColor blend_color = 2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (background_luminance < 128) ? SK_ColorWHITE : SK_ColorBLACK; 2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return color_utils::AlphaBlend(blend_color, color, alpha); 2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor GetReadableColor(SkColor foreground, SkColor background) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkColor foreground2 = LumaInvertColor(foreground); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const double background_luminance = RelativeLuminance(background); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (ContrastRatio(RelativeLuminance(foreground), background_luminance) >= 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContrastRatio(RelativeLuminance(foreground2), background_luminance)) ? 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) foreground : foreground2; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor InvertColor(SkColor color) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkColorSetARGB( 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColorGetA(color), 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255 - SkColorGetR(color), 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255 - SkColorGetG(color), 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255 - SkColorGetB(color)); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor GetSysSkColor(int which) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return skia::COLORREFToSkColor(GetSysColor(which)); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SK_ColorLTGRAY; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace color_utils 302