|
127 | 127 | [fastmath.easings :as e]
|
128 | 128 | [clojure2d.protocols :as pr]
|
129 | 129 | [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]) |
131 | 133 | (:import [fastmath.vector Vec2 Vec3 Vec4]
|
132 | 134 | [java.awt Color]
|
133 | 135 | [clojure.lang APersistentVector ISeq Seqable]
|
|
145 | 147 | ;; read
|
146 | 148 | ;;;;;;;;;
|
147 | 149 |
|
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)) |
154 | 151 |
|
155 | 152 | ;; color names
|
156 | 153 |
|
|
1297 | 1294 |
|
1298 | 1295 | ;; ### XYZ
|
1299 | 1296 |
|
| 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 | + |
1300 | 1325 | (def ^{:private true :const true :tag 'double} D65X 95.047)
|
1301 | 1326 | (def ^{:private true :const true :tag 'double} D65Y 100.0)
|
1302 | 1327 | (def ^{:private true :const true :tag 'double} D65Z 108.883)
|
1303 | 1328 | (def ^{:private true :const true :tag 'double} D65x 0.31270)
|
1304 | 1329 | (def ^{:private true :const true :tag 'double} D65y 0.32900)
|
1305 | 1330 |
|
1306 |
| - |
1307 | 1331 | (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)))) |
1313 | 1337 |
|
1314 | 1338 | (defn to-XYZ1
|
1315 | 1339 | "sRGB -> XYZ, scaled to range 0-1"
|
|
1331 | 1355 | * Z: 0.0 - 108.883"
|
1332 | 1356 | {:metadoc/categories meta-conv}
|
1333 | 1357 | ^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))) |
1339 | 1359 |
|
1340 | 1360 | (defn to-XYZ*
|
1341 | 1361 | "sRGB -> XYZ, normalized"
|
|
1370 | 1390 | For ranges, see [[to-XYZ]]"
|
1371 | 1391 | {:metadoc/categories meta-conv}
|
1372 | 1392 | ^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))) |
1378 | 1394 |
|
1379 | 1395 | (defn from-XYZ*
|
1380 | 1396 | "XYZ -> sRGB, normalized"
|
|
3980 | 3996 |
|
3981 | 3997 | (defn delta-E*
|
3982 | 3998 | "Δ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)))))) |
3989 | 4008 |
|
3990 | 4009 | (defn- delta-ab
|
3991 | 4010 | ^double [^Vec4 c1 ^Vec4 c2]
|
|
3995 | 4014 | (defn delta-C*
|
3996 | 4015 | "ΔC*_ab difference, chroma difference in LAB color space, CIE 1976"
|
3997 | 4016 | {: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))))) |
4000 | 4022 |
|
4001 | 4023 | (def ^{:deprecated "Use delta-C*"} delta-c delta-C*)
|
4002 | 4024 |
|
4003 | 4025 | (defn delta-H*
|
4004 | 4026 | "ΔH* difference, hue difference in LAB, CIE 1976"
|
4005 | 4027 | {: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))))))) |
4012 | 4037 |
|
4013 | 4038 | (def ^{:deprecated "Use delta-H*"} delta-h delta-H*)
|
4014 | 4039 |
|
4015 | 4040 | (defn delta-E-HyAB
|
4016 | 4041 | "Δ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))))))) |
4023 | 4051 |
|
4024 | 4052 | (defn delta-E*-94
|
4025 | 4053 | "ΔE* difference, CIE 1994"
|
4026 | 4054 | {: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}}] |
4029 | 4058 | (let [k1 (if textiles? 0.048 0.045)
|
4030 | 4059 | 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) |
4033 | 4063 | C* (m/sqrt (* (m/hypot-sqrt (.y c1) (.z c1))
|
4034 | 4064 | (m/hypot-sqrt (.y c2) (.z c2))))
|
4035 | 4065 | Sc (inc (* k1 C*))
|
|
4049 | 4079 | (defn delta-E*-euclidean
|
4050 | 4080 | ^{:metadoc/categories #{:dist}
|
4051 | 4081 | :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}}] |
4054 | 4085 | (let [to (first (colorspaces colorspace))
|
4055 | 4086 | ^Vec4 c1 (to c1)
|
4056 | 4087 | ^Vec4 c2 (to c2)]
|
|
4081 | 4112 | ;; http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.125.3833&rep=rep1&type=pdf
|
4082 | 4113 | (defn delta-D-HCL
|
4083 | 4114 | "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)))))))))) |
4094 | 4128 |
|
4095 | 4129 | (defn delta-E*-CMC
|
4096 | 4130 | "ΔE* CMC difference
|
4097 | 4131 |
|
4098 | 4132 | Parameters `l` and `c` defaults to 1.0. Other common settings is `l=2.0` and `c=1.0`."
|
4099 | 4133 | {: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) |
4104 | 4140 | L1 (.x c1)
|
4105 | 4141 | L2 (.x c2)
|
4106 | 4142 | a1 (.y c1)
|
|
4136 | 4172 | (defn delta-E-z
|
4137 | 4173 | "ΔE* calculated in JAB color space."
|
4138 | 4174 | {: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)))))))) |
4155 | 4194 |
|
4156 | 4195 | (def ^{:deprecated "Use delta-e-jab"} delta-e-jab delta-E-z)
|
4157 | 4196 |
|
|
4171 | 4210 | "ΔE* color difference, CIE 2000
|
4172 | 4211 |
|
4173 | 4212 | 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) |
4178 | 4219 | C1* (m/hypot-sqrt (.y c1) (.z c1))
|
4179 | 4220 | C2* (m/hypot-sqrt (.y c2) (.z c2))
|
4180 | 4221 | Cm* (* 0.5 (+ C1* C2*))
|
|
4220 | 4261 | Sc (inc (* 0.045 Cm'))
|
4221 | 4262 | Sh (inc (* 0.015 Cm' T))
|
4222 | 4263 | 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))] |
4226 | 4267 | (m/sqrt (+ (m/sq l') (m/sq c') (m/sq h')
|
4227 | 4268 | (* Rt c' h'))))))
|
4228 | 4269 |
|
|
4252 | 4293 |
|
4253 | 4294 | Implementation from: https://github.com/connorgr/d3-jnd/blob/master/src/jnd.js"
|
4254 | 4295 | {: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) |
4259 | 4302 | ^Vec4 diff (v/abs (v/sub c1 c2))
|
4260 | 4303 | ^Vec3 nd (nd-lab-interval s p)]
|
4261 | 4304 | (or (>= (.x diff) (.x nd))
|
|
4295 | 4338 | {:metadoc/categories #{:interp}}
|
4296 | 4339 | ([cs weights colorspace]
|
4297 | 4340 | (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))))) |
4299 | 4342 | ([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)))) |
4301 | 4344 |
|
4302 | 4345 | (defn lerp
|
4303 | 4346 | "Linear interpolation of two colors.
|
|
0 commit comments