Module: ColorExtract::ColorUtil

Included in:
Analytics, Palette
Defined in:
lib/color_extract/color_util.rb

Constant Summary collapse

K =

Corresponds roughly to RGB brighter/darker

18
X =

D65 standard referent

0.950470
Y =
1
Z =
1.088830

Instance Method Summary collapse

Instance Method Details

#darken(hsl_color, percent) ⇒ Object



111
112
113
# File 'lib/color_extract/color_util.rb', line 111

def darken( hsl_color, percent )
  hsl_color.tap { |c| darken!( c, percent ) }
end

#darken!(hsl_color, percent) ⇒ Object



115
116
117
118
# File 'lib/color_extract/color_util.rb', line 115

def darken!( hsl_color, percent )
  l = hsl_color.l
  hsl_color.l -= (1-l) * percent
end

#dither(color) ⇒ Object



91
92
93
94
95
96
97
98
99
100
# File 'lib/color_extract/color_util.rb', line 91

def dither( color )
  color.to_hsl.tap do |c|
    if c.s > 0.8
      c.s -= (c.s) * 0.3
      c.l -= 0.1
    else
      c.s += (1-c.s) * 0.5
    end
  end
end

#hue_similarity(color1, color2) ⇒ Object

Public: 判断两种颜色的色系相似程度

Returns 色相距离,0-180之间的角度值



27
28
29
30
31
32
33
34
35
# File 'lib/color_extract/color_util.rb', line 27

def hue_similarity( color1, color2 )
  deg1   = color1.to_hsl.h
  deg2   = color2.to_hsl.h
  deg1  += 1 if deg1 < 0
  deg2  += 1 if deg2 < 0
  delta  = (deg1 - deg2).abs
  delta  = 1 - delta if delta > 0.5
  delta * 360
end

#lighten(hsl_color, percent) ⇒ Object



120
121
122
# File 'lib/color_extract/color_util.rb', line 120

def lighten( hsl_color, percent )
  hsl_color.tap { |c| lighten!( c, percent ) }
end

#lighten!(hsl_color, percent) ⇒ Object



124
125
126
127
# File 'lib/color_extract/color_util.rb', line 124

def lighten!( hsl_color, percent )
  l = hsl_color.l
  hsl_color.l += l * percent
end

#pure(color, s: 1, l: 1) ⇒ Object



80
81
82
83
84
85
86
87
88
89
# File 'lib/color_extract/color_util.rb', line 80

def pure( color, s: 1, l: 1 )
  color.to_hsl.tap do |c|
    if s
      c.s = s
    else
      c.s += (1 - c.s) * 0.382
    end
    c.l = l if l
  end.to_rgb
end

#readable_textcolor(bg: nil, accent: nil, lock_accent: false) ⇒ Object

Public: 根据背景色,计算适用于显示其上的文字的颜色



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/color_extract/color_util.rb', line 64

def readable_textcolor( bg: nil, accent: nil, lock_accent: false)
  l1, a1, b1 = *rgb2lab(bg)
  if accent
    l2, a2, b2 = *rgb2lab(accent)
    return accent if (l1 - l2).abs > 255 * 0.8
  end
  
  # TODO: ajust accent unless lock_accent
  # 白色会显得品质高档,因此尽量使用白色
  if l1 < 75
    Color::RGB.from_html( '#FFFFFF' )
  else
    bg.to_hsl.tap { |c| c.l = 0.1 }.to_rgb
  end
end

#reverse_color(color) ⇒ Object



102
103
104
105
106
107
108
109
# File 'lib/color_extract/color_util.rb', line 102

def reverse_color( color )
  color.to_hsl.tap do |c|
    # 色盘旋转60度
    h = c.h + 1.0/6
    h -= 1 if h > 1
    c.h = h
  end.to_rgb
end

#rgb2lab(color) ⇒ Object

来自 github 上的开源项目 chroma github.com/gka/chroma.js/blob/master/src/conversions/rgb2lab.coffee

color - RGB颜色

Returns [l*, a*, b*] 值。



44
45
46
47
48
49
50
51
52
53
# File 'lib/color_extract/color_util.rb', line 44

def rgb2lab(color)
  r, g, b = color.r * 255, color.g * 255, color.b * 255
  r = rgb_xyz r
  g = rgb_xyz g
  b = rgb_xyz b
  x = xyz_lab (0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / X
  y = xyz_lab (0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / Y
  z = xyz_lab (0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / Z
  [116 * y - 16, 500 * (x - y), 200 * (y - z)]
end

#rgb_xyz(r) ⇒ Object



55
56
57
# File 'lib/color_extract/color_util.rb', line 55

def rgb_xyz (r)
  if (r /= 255) <= 0.04045 then r / 12.92 else ((r + 0.055) / 1.055) ** 2.4 end
end

#similarity(color1, color2, ignore_lightness: false) ⇒ Object

使用 CIE76 公式计算颜色的相似程度参考:



17
18
19
20
21
# File 'lib/color_extract/color_util.rb', line 17

def similarity( color1, color2, ignore_lightness: false )
  l1, a1, b1 = *rgb2lab(color1.to_rgb)
  l2, a2, b2 = *rgb2lab(color2.to_rgb)
  Math.sqrt( (ignore_lightness ? 0 : (l1-l2)**2) + (a1-a2)**2 + (b1-b2)**2 )
end

#xyz_lab(x) ⇒ Object



59
60
61
# File 'lib/color_extract/color_util.rb', line 59

def xyz_lab (x)
  if x > 0.008856 then x ** (1.0/3) else 7.787037 * x + 4 / 29 end
end