Skip to content

Commit f7d5caa

Browse files
committed
white points wip
1 parent 81d4fa5 commit f7d5caa

File tree

6 files changed

+780
-401
lines changed

6 files changed

+780
-401
lines changed

resources/color/cmfs_standard_observer.edn

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

resources/color/illuminants.edn

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

resources/color/whitepoints.edn

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

src/clojure2d/color.clj

Lines changed: 135 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@
127127
[fastmath.easings :as e]
128128
[clojure2d.protocols :as pr]
129129
[clojure2d.color.whitepoints :as wp]
130-
[clojure.java.io :refer [input-stream resource]])
130+
[clojure.java.io :refer [input-stream resource]]
131+
[clojure.edn :as edn]
132+
[fastmath.matrix :as mat])
131133
(:import [fastmath.vector Vec2 Vec3 Vec4]
132134
[java.awt Color]
133135
[clojure.lang APersistentVector ISeq Seqable]
@@ -145,12 +147,7 @@
145147
;; read
146148
;;;;;;;;;
147149

148-
(defn- read-edn
149-
[n]
150-
(-> (resource n)
151-
(input-stream)
152-
(slurp)
153-
(read-string)))
150+
(defn- read-edn [n] (-> (resource n) input-stream slurp edn/read-string))
154151

155152
;; color names
156153

@@ -1297,19 +1294,46 @@
12971294

12981295
;; ### XYZ
12991296

1297+
(defn ->XYZ-to-XYZ
1298+
"Create XYZ converter between different white points and given adaptation method.
1299+
1300+
Adaptation method can be one of: `:xyz-scaling`, `:bradford` (default), `:von-kries`, `:sharp`, `:fairchild`, `:cat97`, `:cat2000`, `:cat02`, `:cat02brill2008`, `:cat16`, `bianco2010`, `:bianco2010-pc`."
1301+
([source-wp destination-wp] (->XYZ-to-XYZ :bradford source-wp destination-wp))
1302+
([adaptation-method source-wp destination-wp]
1303+
(let [M (wp/chromatic-adaptation-matrix adaptation-method source-wp destination-wp)]
1304+
(fn ^Vec4 [c]
1305+
(let [^Vec4 c (pr/to-color c)
1306+
^Vec3 c3 (mat/mulv M (Vec3. (.x c) (.y c) (.z c)))]
1307+
(Vec4. (.x c3) (.y c3) (.z c3) (.w c)))))))
1308+
1309+
(defn XYZ-to-XYZ1
1310+
^Vec4 [c]
1311+
(let [^Vec4 c (pr/to-color c)]
1312+
(Vec4. (* 0.01 (.x c))
1313+
(* 0.01 (.y c))
1314+
(* 0.01 (.z c))
1315+
(.w c))))
1316+
1317+
(defn XYZ1-to-XYZ
1318+
^Vec4 [c]
1319+
(let [^Vec4 c (pr/to-color c)]
1320+
(Vec4. (* 100.0 (.x c))
1321+
(* 100.0 (.y c))
1322+
(* 100.0 (.z c))
1323+
(.w c))))
1324+
13001325
(def ^{:private true :const true :tag 'double} D65X 95.047)
13011326
(def ^{:private true :const true :tag 'double} D65Y 100.0)
13021327
(def ^{:private true :const true :tag 'double} D65Z 108.883)
13031328
(def ^{:private true :const true :tag 'double} D65x 0.31270)
13041329
(def ^{:private true :const true :tag 'double} D65y 0.32900)
13051330

1306-
13071331
(defn- to-XYZ-
1308-
"Pure RGB->XYZ conversion without corrections."
1309-
^Vec3 [^Vec3 c]
1310-
(Vec3. (+ (* (.x c) 0.4124564390896921) (* (.y c) 0.357576077643909) (* (.z c) 0.18043748326639894))
1311-
(+ (* (.x c) 0.21267285140562248) (* (.y c) 0.715152155287818) (* (.z c) 0.07217499330655958))
1312-
(+ (* (.x c) 0.019333895582329317) (* (.y c) 0.119192025881303) (* (.z c) 0.9503040785363677))))
1332+
"Pure RGB->XYZ conversion without corrections."
1333+
^Vec3 [^Vec3 c]
1334+
(Vec3. (+ (* (.x c) 0.4124564390896921) (* (.y c) 0.357576077643909) (* (.z c) 0.18043748326639894))
1335+
(+ (* (.x c) 0.21267285140562248) (* (.y c) 0.715152155287818) (* (.z c) 0.07217499330655958))
1336+
(+ (* (.x c) 0.019333895582329317) (* (.y c) 0.119192025881303) (* (.z c) 0.9503040785363677))))
13131337

13141338
(defn to-XYZ1
13151339
"sRGB -> XYZ, scaled to range 0-1"
@@ -1331,11 +1355,7 @@
13311355
* Z: 0.0 - 108.883"
13321356
{:metadoc/categories meta-conv}
13331357
^Vec4 [c]
1334-
(let [^Vec4 c (to-XYZ1 c)]
1335-
(Vec4. (* 100.0 (.x c))
1336-
(* 100.0 (.y c))
1337-
(* 100.0 (.z c))
1338-
(.w c))))
1358+
(XYZ1-to-XYZ (to-XYZ1 c)))
13391359

13401360
(defn to-XYZ*
13411361
"sRGB -> XYZ, normalized"
@@ -1370,11 +1390,7 @@
13701390
For ranges, see [[to-XYZ]]"
13711391
{:metadoc/categories meta-conv}
13721392
^Vec4 [c]
1373-
(let [^Vec4 c (pr/to-color c)]
1374-
(from-XYZ1 (Vec4. (* 0.01 (.x c))
1375-
(* 0.01 (.y c))
1376-
(* 0.01 (.z c))
1377-
(.w c)))))
1393+
(from-XYZ1 (XYZ-to-XYZ1 c)))
13781394

13791395
(defn from-XYZ*
13801396
"XYZ -> sRGB, normalized"
@@ -3980,12 +3996,15 @@
39803996

39813997
(defn delta-E*
39823998
"ΔE*_ab difference, CIE 1976"
3983-
^double [c1 c2]
3984-
(let [^Vec4 c1 (to-LAB c1)
3985-
^Vec4 c2 (to-LAB c2)]
3986-
(m/hypot-sqrt (- (.x c2) (.x c1))
3987-
(- (.y c2) (.y c1))
3988-
(- (.z c2) (.z c1)))))
3999+
(^double [c1 c2] (delta-E* c1 c2 nil))
4000+
(^double [c1 c2 {:keys [colorspace]
4001+
:or {colorspace :LAB}}]
4002+
(let [to (first (colorspaces colorspace))
4003+
^Vec4 c1 (to c1)
4004+
^Vec4 c2 (to c2)]
4005+
(m/hypot-sqrt (- (.x c2) (.x c1))
4006+
(- (.y c2) (.y c1))
4007+
(- (.z c2) (.z c1))))))
39894008

39904009
(defn- delta-ab
39914010
^double [^Vec4 c1 ^Vec4 c2]
@@ -3995,41 +4014,52 @@
39954014
(defn delta-C*
39964015
"ΔC*_ab difference, chroma difference in LAB color space, CIE 1976"
39974016
{:metadoc/categories #{:dist}}
3998-
^double [c1 c2]
3999-
(delta-ab (to-LAB c1) (to-LAB c2)))
4017+
(^double [c1 c2] (delta-C* c1 c2 nil))
4018+
(^double [c1 c2 {:keys [colorspace]
4019+
:or {colorspace :LAB}}]
4020+
(let [to (first (colorspaces colorspace))]
4021+
(delta-ab (to c1) (to c2)))))
40004022

40014023
(def ^{:deprecated "Use delta-C*"} delta-c delta-C*)
40024024

40034025
(defn delta-H*
40044026
"ΔH* difference, hue difference in LAB, CIE 1976"
40054027
{:metadoc/categories #{:dist}}
4006-
^double [c1 c2]
4007-
(let [^Vec4 c1 (to-LAB c1)
4008-
^Vec4 c2 (to-LAB c2)]
4009-
(m/safe-sqrt (- (+ (m/sq (- (.y c2) (.y c1)))
4010-
(m/sq (- (.z c2) (.z c1))))
4011-
(m/sq (delta-ab c1 c2))))))
4028+
(^double [c1 c2] (delta-H* c1 c2 nil))
4029+
(^double [c1 c2 {:keys [colorspace]
4030+
:or {colorspace :LAB}}]
4031+
(let [to (first (colorspaces colorspace))
4032+
^Vec4 c1 (to c1)
4033+
^Vec4 c2 (to c2)]
4034+
(m/safe-sqrt (- (+ (m/sq (- (.y c2) (.y c1)))
4035+
(m/sq (- (.z c2) (.z c1))))
4036+
(m/sq (delta-ab c1 c2)))))))
40124037

40134038
(def ^{:deprecated "Use delta-H*"} delta-h delta-H*)
40144039

40154040
(defn delta-E-HyAB
40164041
"ΔE_HyAB difference"
4017-
^double [c1 c2]
4018-
(let [^Vec4 c1 (to-LAB c1)
4019-
^Vec4 c2 (to-LAB c2)]
4020-
(+ (m/hypot-sqrt (- (.y c2) (.y c1))
4021-
(- (.z c2) (.z c1)))
4022-
(m/abs (- (.x c2) (.x c1))))))
4042+
(^double [c1 c2] (delta-E-HyAB c1 c2 nil))
4043+
(^double [c1 c2 {:keys [colorspace]
4044+
:or {colorspace :LAB}}]
4045+
(let [to (first (colorspaces colorspace))
4046+
^Vec4 c1 (to c1)
4047+
^Vec4 c2 (to c2)]
4048+
(+ (m/hypot-sqrt (- (.y c2) (.y c1))
4049+
(- (.z c2) (.z c1)))
4050+
(m/abs (- (.x c2) (.x c1)))))))
40234051

40244052
(defn delta-E*-94
40254053
"ΔE* difference, CIE 1994"
40264054
{:metadoc/categories #{:dist}}
4027-
(^double [c1 c2] (delta-E*-94 c1 c2 false))
4028-
(^double [c1 c2 textiles?]
4055+
(^double [c1 c2] (delta-E*-94 c1 c2 nil))
4056+
(^double [c1 c2 {:keys [textiles? colorspace]
4057+
:or {textiles? false colorspace :LAB}}]
40294058
(let [k1 (if textiles? 0.048 0.045)
40304059
k2 (if textiles? 0.014 0.015)
4031-
^Vec4 c1 (to-LAB c1)
4032-
^Vec4 c2 (to-LAB c2)
4060+
to (first (colorspaces colorspace))
4061+
^Vec4 c1 (to c1)
4062+
^Vec4 c2 (to c2)
40334063
C* (m/sqrt (* (m/hypot-sqrt (.y c1) (.z c1))
40344064
(m/hypot-sqrt (.y c2) (.z c2))))
40354065
Sc (inc (* k1 C*))
@@ -4049,8 +4079,9 @@
40494079
(defn delta-E*-euclidean
40504080
^{:metadoc/categories #{:dist}
40514081
:doc "Euclidean distance in given colorspace (default Oklab)."}
4052-
(^double [c1 c2] (delta-E*-euclidean c1 c2 :Oklab))
4053-
(^double [c1 c2 colorspace]
4082+
(^double [c1 c2] (delta-E*-euclidean c1 c2 nil))
4083+
(^double [c1 c2 {:keys [colorspace]
4084+
:or {colorspace :Oklab}}]
40544085
(let [to (first (colorspaces colorspace))
40554086
^Vec4 c1 (to c1)
40564087
^Vec4 c2 (to c2)]
@@ -4081,26 +4112,31 @@
40814112
;; http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.125.3833&rep=rep1&type=pdf
40824113
(defn delta-D-HCL
40834114
"Color difference in HCL (Sarifuddin and Missaou) color space"
4084-
^double [c1 c2]
4085-
(let [^Vec4 c1 (to-HCL c1)
4086-
^Vec4 c2 (to-HCL c2)
4087-
dH (diff-H (.x c2) (.x c1))
4088-
dL (- (.z c2) (.z c1))]
4089-
(m/sqrt (+ (m/sq (* 1.4456 dL))
4090-
(* (+ dH 0.16)
4091-
(+ (m/sq (.y c1))
4092-
(m/sq (.y c2))
4093-
(* -2.0 (.y c1) (.y c2) (m/cos (m/radians dH)))))))))
4115+
(^double [c1 c2] (delta-D-HCL c1 c2 nil))
4116+
(^double [c1 c2 {:keys [colorspace]
4117+
:or {colorspace :HCL}}]
4118+
(let [to (first (colorspaces colorspace))
4119+
^Vec4 c1 (to c1)
4120+
^Vec4 c2 (to c2)
4121+
dH (diff-H (.x c2) (.x c1))
4122+
dL (- (.z c2) (.z c1))]
4123+
(m/sqrt (+ (m/sq (* 1.4456 dL))
4124+
(* (+ dH 0.16)
4125+
(+ (m/sq (.y c1))
4126+
(m/sq (.y c2))
4127+
(* -2.0 (.y c1) (.y c2) (m/cos (m/radians dH))))))))))
40944128

40954129
(defn delta-E*-CMC
40964130
"ΔE* CMC difference
40974131
40984132
Parameters `l` and `c` defaults to 1.0. Other common settings is `l=2.0` and `c=1.0`."
40994133
{:metadoc/categories #{:dist}}
4100-
(^double [c1 c2] (delta-E*-CMC c1 c2 1.0 1.0))
4101-
(^double [c1 c2 ^double l ^double c ]
4102-
(let [^Vec4 c1 (to-LAB c1)
4103-
^Vec4 c2 (to-LAB c2)
4134+
(^double [c1 c2] (delta-E*-CMC c1 c2 nil))
4135+
(^double [c1 c2 {:keys [^double l ^double c colorspace]
4136+
:or {l 1.0 c 1.0 colorspace :LAB}}]
4137+
(let [to (first (colorspaces colorspace))
4138+
^Vec4 c1 (to c1)
4139+
^Vec4 c2 (to c2)
41044140
L1 (.x c1)
41054141
L2 (.x c2)
41064142
a1 (.y c1)
@@ -4136,22 +4172,25 @@
41364172
(defn delta-E-z
41374173
"ΔE* calculated in JAB color space."
41384174
{:metadoc/categories #{:dist}}
4139-
^double [c1 c2]
4140-
(let [^Vec4 c1 (to-JAB c1)
4141-
^Vec4 c2 (to-JAB c2)
4142-
J1 (.x c1)
4143-
J2 (.x c2)
4144-
a1 (.y c1)
4145-
a2 (.y c2)
4146-
b1 (.z c1)
4147-
b2 (.z c2)
4148-
C1 (m/hypot-sqrt a1 b1)
4149-
C2 (m/hypot-sqrt a2 b2)
4150-
h1 (m/atan2 b1 a1)
4151-
h2 (m/atan2 b2 a2)]
4152-
(m/hypot-sqrt (- J2 J1)
4153-
(- C2 C1)
4154-
(* 2.0 (m/sqrt (* C1 C2)) (m/sin (* 0.5 (- h2 h1)))))))
4175+
(^double [c1 c2] (delta-E-z c1 c2 nil))
4176+
(^double [c1 c2 {:keys [colorspace]
4177+
:or {colorspace :JAB}}]
4178+
(let [to (first (colorspaces colorspace))
4179+
^Vec4 c1 (to c1)
4180+
^Vec4 c2 (to c2)
4181+
J1 (.x c1)
4182+
J2 (.x c2)
4183+
a1 (.y c1)
4184+
a2 (.y c2)
4185+
b1 (.z c1)
4186+
b2 (.z c2)
4187+
C1 (m/hypot-sqrt a1 b1)
4188+
C2 (m/hypot-sqrt a2 b2)
4189+
h1 (m/atan2 b1 a1)
4190+
h2 (m/atan2 b2 a2)]
4191+
(m/hypot-sqrt (- J2 J1)
4192+
(- C2 C1)
4193+
(* 2.0 (m/sqrt (* C1 C2)) (m/sin (* 0.5 (- h2 h1))))))))
41554194

41564195
(def ^{:deprecated "Use delta-e-jab"} delta-e-jab delta-E-z)
41574196

@@ -4171,10 +4210,12 @@
41714210
"ΔE* color difference, CIE 2000
41724211
41734212
http://www2.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf"
4174-
(^double [c1 c2] (delta-E*-2000 c1 c2 1.0 1.0 1.0))
4175-
([c1 c2 l c h]
4176-
(let [^Vec4 c1 (to-LAB c1)
4177-
^Vec4 c2 (to-LAB c2)
4213+
(^double [c1 c2] (delta-E*-2000 c1 c2 nil))
4214+
(^double [c1 c2 {:keys [^double l ^double c ^double h colorspace]
4215+
:or {l 1.0 c 1.0 h 1.0 colorspace :LAB}}]
4216+
(let [to (first (colorspaces colorspace))
4217+
^Vec4 c1 (to c1)
4218+
^Vec4 c2 (to c2)
41784219
C1* (m/hypot-sqrt (.y c1) (.z c1))
41794220
C2* (m/hypot-sqrt (.y c2) (.z c2))
41804221
Cm* (* 0.5 (+ C1* C2*))
@@ -4220,9 +4261,9 @@
42204261
Sc (inc (* 0.045 Cm'))
42214262
Sh (inc (* 0.015 Cm' T))
42224263
Rt (- (* (m/sin (* 2.0 dtheta)) Rc))
4223-
l' (/ dL' (* (double l) Sl))
4224-
c' (/ dC' (* (double c) Sc))
4225-
h' (/ dH' (* (double h) Sh))]
4264+
l' (/ dL' (* l Sl))
4265+
c' (/ dC' (* c Sc))
4266+
h' (/ dH' (* h Sh))]
42264267
(m/sqrt (+ (m/sq l') (m/sq c') (m/sq h')
42274268
(* Rt c' h'))))))
42284269

@@ -4252,10 +4293,12 @@
42524293
42534294
Implementation from: https://github.com/connorgr/d3-jnd/blob/master/src/jnd.js"
42544295
{:metadoc/categories #{:dist}}
4255-
([c1 c2] (noticable-different? c1 c2 0.1 0.5))
4256-
([c1 c2 ^double s ^double p ]
4257-
(let [c1 (to-LAB c1)
4258-
c2 (to-LAB c2)
4296+
([c1 c2] (noticable-different? c1 c2 nil))
4297+
([c1 c2 {:keys [^double s ^double p colorspace]
4298+
:or {s 0.1 p 0.5 colorspace :LAB}} ]
4299+
(let [to (first (colorspaces colorspace))
4300+
c1 (to c1)
4301+
c2 (to c2)
42594302
^Vec4 diff (v/abs (v/sub c1 c2))
42604303
^Vec3 nd (nd-lab-interval s p)]
42614304
(or (>= (.x diff) (.x nd))
@@ -4295,9 +4338,9 @@
42954338
{:metadoc/categories #{:interp}}
42964339
([cs weights colorspace]
42974340
(let [[to from] (colorspaces colorspace)]
4298-
(from (v/div (reduce v/add (map #(v/mult (to %1) %2) cs weights)) (reduce m/fast+ weights)))))
4341+
(from (v/div (reduce v/add (map #(v/mult (to %1) %2) cs weights)) (reduce m/+ weights)))))
42994342
([cs weights]
4300-
(v/div (reduce v/add (map #(v/mult (pr/to-color %1) %2) cs weights)) (reduce m/fast+ weights))))
4343+
(v/div (reduce v/add (map #(v/mult (pr/to-color %1) %2) cs weights)) (reduce m/+ weights))))
43014344

43024345
(defn lerp
43034346
"Linear interpolation of two colors.

0 commit comments

Comments
 (0)