Skip to content

Instantly share code, notes, and snippets.

@anna328p
Created June 2, 2020 06:56
Show Gist options
  • Save anna328p/d842e31dc4d6c8073b6e3fc4c6c1db61 to your computer and use it in GitHub Desktop.
Save anna328p/d842e31dc4d6c8073b6e3fc4c6c1db61 to your computer and use it in GitHub Desktop.
Closest color
# Closest Color Algorithm
require 'matrix'
RGB_XYZ_MATRIX = Matrix[
[ 0.4124564, 0.3575761, 0.1804375 ],
[ 0.2126729, 0.7151522, 0.0721750 ],
[ 0.0193339, 0.1191920, 0.9503041 ]
]
XYZ_RGB_MATRIX = Matrix[
[ 3.2404542, -1.5371385, -0.4985314 ],
[ -0.9692660, 1.8760108, 0.0415560 ],
[ 0.0556434, -0.2040259, 1.0572252 ]
]
D65 = [ 95.047, 100, 108.883 ]
def hex_to_rgb(hex)
return hex[-6..-1].chars.each_slice(2).map { |a, b| "#{a}#{b}".to_i(16) }
end
def rgb_to_hex(rgb)
return "#" + rgb.map { |c| c.round.to_s(16).rjust(2, ?0) }.join
end
def rgb_to_xyz(rgb)
r, g, b = rgb.map { |c| c / 256.0 }
return (RGB_XYZ_MATRIX * Matrix[[r], [g], [b]]).to_a.flatten
end
def xyz_to_rgb(xyz)
x, y, z = xyz
ary = (XYZ_RGB_MATRIX * Matrix[[x], [y], [z]]).to_a.flatten
return ary.map { |c| c * 256.0 }
end
def f(t)
delta = 6.0 / 29
if t > delta ** 3
return t ** (1.0/3)
else
return t / (3 * delta**2) + 4.0/29
end
end
def xyz_to_lab(xyz)
x, y, z = xyz.map { |c| c * 100 }
xn, yn, zn = D65
l = 116 * f(y/yn) - 16
a = 500 * (f(x/xn) - f(y/yn))
b = 200 * (f(y/yn) - f(z/zn))
return [l, a, b]
end
def lab_to_xyz(lab)
l, a, b = lab
xn, yn, zn = D65
p = (l + 16) / 116.0
x = xn * (p + a/500.0) ** 3
y = yn * p**3
z = zn * (p - b/200.0) ** 3
return [x, y, z].map { |c| c / 100.0 }
end
def cie76(lab1, lab2)
l1, a1, b1 = lab1
l2, a2, b2 = lab2
return ((l2 - l1)**2 + (a2 - a1)**2 + (b2 - b1)**2)**0.5
end
def ciede2000(lab1, lab2)
# TODO: write this
end
def hex_to_lab(c)
return xyz_to_lab(rgb_to_xyz(hex_to_rgb(c)))
end
def lab_to_hex(c)
return rgb_to_hex(xyz_to_rgb(lab_to_xyz(c)))
end
colors = File.readlines("colors.txt").map.with_index { |c, idx| [c.chomp, idx] }
labs = colors.map { |c, idx| [hex_to_lab(c), idx] }
compare = hex_to_lab(ARGV[0])
de = labs.map { |val, idx| [cie76(compare, val), idx] }
min = de.min_by { |val, idx| val }
puts colors[min[1]][0]
000000
000001
000092
0000ff
000a55
001337
0061a8
006400
007175
008000
0080fe
008b45
0090ff
0099ff
0099ff
00d000
00ff00
00ffff
010010
010101
0399fc
051866
0f52ba
1338be
15c3eb
15ebd5
1793d1
198844
25575e
282c34
2832c2
2979ff
2a6ad1
31d4b3
34c9eb
353542
3568be
3570ff
36393e
36393f
367f8a
3b3b3b
3e85db
420dab
443872
444dac
48d1cc
4978ff
4c82c2
4d79ff
4d8fac
4dd4e8
5170ff
5180ff
52518b
5277c3
5294e2
52e6f2
555555
56d2c7
586868
5988ff
5998ff
5eff3b
629bb7
640064
666000
666688
6699cc
66cdaa
678767
696969
696979
7093db
7289da
745039
77f7fa
789789
78adc2
7e3fa0
7eb7e1
7ecbf8
7ed849
7fffd4
81c7a6
8470ff
857fbb
8a6545
8b5742
8bc669
8cb86e
8fbc8f
920000
9290b8
92ffaa
930230
96dfe8
98f5ff
9b4d4e
9f3e1a
a55a55
a9a9a9
a9dfbf
abcdef
ada9db
adbeef
ae3333
afd7fc
b00b69
b0c4de
b16a55
b19cd9
b39ddb
b4d2f0
b5d101
b5ead7
b5ebd8
b9f2ff
bada55
bb1111
bbaacc
bc72df
be9764
becafe
bf002d
bfa388
c07067
c0c0c0
c17089
c1cdcd
c22f50
c63552
c65b59
c8e6a0
cc241d
cc8800
cdaa7d
cdc673
ce5f5f
d00000
d00b00
d00d00
d2691e
d2b48c
d46088
d58138
d5f5e3
d88a8a
d9b3ff
daa498
dabdab
dc143c
dc322f
dcb6ad
dd00ff
dd4814
dda0dd
e0115f
e072d2
e23dff
e2455a
e43941
e67e95
e874d9
e8f6f3
e9f7ef
eaafcf
eafaf1
edc7a9
ee2222
eedd82
eeee00
f0f0f0
f26d7e
f5a2b4
f5deb3
f7a8b8
f7e3c0
f7f767
fa7a55
fc86e4
fdfb84
fdfeba
fed5db
ff0000
ff0076
ff00ff
ff2052
ff3030
ff35b4
ff4444
ff6347
ff6961
ff69b4
ff7777
ff7f00
ff83fa
ff8c00
ff8dc1
ff9900
ff99dd
ffa500
ffb6c1
ffb90f
ffcc00
ffcef0
ffd700
ffd900
ffe9b9
ffea00
ffee5e
ffff00
fffffe
ffffff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment