Cross-platform CLJ/CLJS library for color conversion & manipulation. The library supports any-to-any conversions and color manipulations for the following color spaces:
- RGBA (floats, packed int24/int32)
- HSVA
- HSLA
- CMYKA
- HCYA
- HCVA
- CIE1931A
- CSS(A) (hex 3/6-digit & long forms)
The library also provides a protocol wrapper for other, user supplied color spaces to proxy all operations via intermediate RGBA conversions. Users will only need to provide two functions to convert from/to RGBA.
All color types are completely protocol based with optimized implementations for each. The current set of color operations includes:
- channel accessors for all supported color spaces
- hue rotation
- brightness/saturation/alpha adjustments
- analog/complementary/inverse colors
- hue matching
- blending
- distance calculations in RGB/HSV
Furthermore the library includes namespaces to generate procedural gradients and features 100+ CSS named color & gradient presets as well as D3’s & Cynthia Brewer’s categorical color schemes originally intented for geo mapping and other data visualization applications.
[thi.ng/color "1.5.1"]
Note: This library relies on the new conditional reader syntax of recent Clojure & Clojurescript versions and therefore is **not compatible with Clojure versions < 1.7.0
STABLE & under regular development, 170+ tests
(require '[thi.ng.color.core :as col])
(col/rgba 1 0 0 0.5)
;; #thi.ng.color.core.RGBA [1.0 0.0 0.0 0.5]
(col/hsva 0.5 1 1)
;; #thi.ng.color.core.HSVA [0.5 1.0 1.0 1.0]
(col/as-cmyka (col/hsva 0.5 1 1))
;; #thi.ng.color.core.CMYKA [1.0 0.0 0.0 0.0 1.0]
;; use deref to obtain the wrapped color values
@(col/as-css (col/hsla 1/6 1 0.5 0.25))
;; "hsla(60,100%,50%,0.25)"
;; parse CSS colors into any target space
@(col/as-rgba (col/css "hsla(60,100%,50%,0.25)"))
;; [0.9999999999999998 1.0 0.0 0.25]
(= 0xffff00 @(col/as-int24 (col/css "hsla(60,100%,50%,0.25)")))
;; compact CSS colors
@(-> "hsla(60,100%,50%,0.25)" col/css col/as-int24 col/as-css)
;; "#ffff00"
;; create controlled color variations (e.g. to create hover state colors)
@(-> (col/css "#f04") (col/analog 0.0 -0.2 0.4) col/as-int24 col/as-css)
"#ff3369"
@(-> (col/rgba 1 0 0.25 0.8) (col/random-analog 0.05 0.1 0.2) col/as-css)
;; "rgba(255,8,63,0.8)"
;; All color types implement the IIinterpolate protocol defined in thi.ng.math.core (1.1.0+ only)
;; For previous versions use (col/blend ...) (same API as m/mix)
(require '[thi.ng.math.core :as m])
;; blend with any color space (result is in color space of first color)
(m/mix (col/hsva 0 1 1) (col/rgba 0 1 0 0.5) 0.5)
;; #thi.ng.color.core.HSVA [0.16666666666666666 1.0 1.0 0.75]
;; sort colors by proximity to a target color
(->> (repeatedly 10 col/random-rgb)
(sort-by #(col/dist-hsv col/RED %)) ;; use HSV distance
(map (comp deref col/as-css col/as-int24)))
;; ("#d8756c" "#ca6709" "#f67e9c" "#bf984e" "#6e400d" "#d602af" "#c52fd2" "#93759d" "#3710d1" "#06a1c3")
1.5.1
[org.clojure/clojure "1.11.1"]
[org.clojure/clojurescript "1.11.121"]
[thi.ng/math "0.3.2"]
[thi.ng/dstruct "0.2.2"]
[thi.ng/typedarrays "0.1.7"]
[thi.ng/strf "0.2.4"]
[thi.ng/xerror "0.1.0"]
[criterium "0.4.6"]
[com.cemerick/clojurescript.test "0.3.3"]
[lein-cljsbuild "1.1.8"]
[thi.ng/color <<version>>]
This project is written in a literate programming format and requires
Emacs & Org-mode to generate usable source code. Assuming both tools
are installed, the easiest way to generate a working project is via
command line (make sure emacs
is on your path or else edit its path
in tangle.sh
):
git clone https://github.com/thi.ng/color.git
cd color
./tangle.sh src/*.org test/*.org
Tangling is the process of extracting & combining source blocks from
.org
files into an actual working project/source tree. Once tangling
is complete, you can cd
into the generated project directory
(babel
) and then use lein
as usual.
The project.clj
file defines an alias to trigger a complete build &
tests for both CLJ & CLJS versions.
cd babel
lein cleantest
To build the Clojurescript version simply run lein cljsbuild test
from the same directory. A small HTML harness for the resulting JS
file is also located in that folder (babel/index.html
), allowing for
further experimentation in the browser.
Editing code blocks or files in Org-mode, then re-loading & testing
changes is quite trivial. Simply launch a REPL (via lein
or Emacs)
as usual. Everytime you’ve made changes to an .org
file, re-tangle
it from Emacs (C-c C-v t
) or tangle.sh
, then reload the namespace
in the REPL via (require 'thi.ng.color... :reload)
or similar.
(defproject thi.ng/color "<<version>>"
:description "Cross-platform CLJ/CLJS library for color conversion & manipulation."
:url "<<project-url>>"
:license {:name "Apache Software License 2.0"
:url "http://www.apache.org/licenses/LICENSE-2.0"
:distribution :repo}
:scm {:name "git"
:url "https://github.com/thi-ng/color"}
:min-lein-version "2.4.0"
:dependencies [<<dep-clj>>
<<dep-cljs>>
<<dep-math>>
<<dep-dstruct>>
<<dep-arrays>>
<<dep-strf>>
<<dep-xerror>>]
:profiles {:dev {:dependencies [<<dep-criterium>>]
:plugins [<<dep-cljsbuild>>
<<dep-cljs-test>>]
:global-vars {*warn-on-reflection* true}
:jvm-opts ^:replace []
:aliases {"cleantest" ["do" "clean," "test," "cljsbuild" "test"]}}}
:cljsbuild {:builds [{:source-paths ["src" "test"]
:id "simple"
:compiler {:output-to "<<cljs-artefact-path>>"
:optimizations :whitespace
:pretty-print true}}]
:test-commands {"unit-tests" ["phantomjs" :runner "<<cljs-artefact-path>>"]}}
:pom-addition [:developers [:developer
[:name "Karsten Schmidt"]
[:url "https://thi.ng"]
[:timezone "1"]]])
<!DOCTYPE html>
<html lang="en">
<head>
<title><<lein-coords>> test</title>
</head>
<body>
<script type="text/javascript" src="<<cljs-artefact-path>>"></script>
</body>
</html>
The autogenerated namespace thi.ng.color.version
contains a single
symbol version
holding the version string defined above:
(use '[thi.ng.color.version])
(prn version)
; "<<version>>"
Version | Released | Description | Tagged GH URL |
---|---|---|---|
1.5.1 | 2022-10-23 | update deps | 1.5.1 |
1.5.0 | 2022-04-23 | update deps | 1.5.0 |
1.2.0 | 2016-04-05 | update dstruct dep, refactor IBuffer impls, add tests | 1.2.0 |
1.1.2 | 2016-03-28 | add gradient presets | 1.1.2 |
1.1.1 | 2016-03-19 | fix dependencies | 1.1.1 |
1.1.0 | 2016-03-19 | defrecord impl, protocol updates, optimizations, bugfixes | 1.1.0 |
1.0.1 | 2015-12-25 | bugfix yuva & cie1931 rgba conversions | 1.0.1 |
1.0.0 | 2015-10-02 | complete rewrite using protocols | 1.0.0 |
0.3.1 | 2015-06-21 | add YCbCr & YUV conversion, update deps | 0.3.1 |
0.3.0 | 2015-06-15 | gradient ns, HSL/HCY/HCV color space support, bugfixes | 0.3.0 |
0.2.0 | 2015-05-26 | no more CLJX, CIE1931 color space support, doc updates | 0.2.0 |
0.1.3 | 2015-04-22 | bugfixes, conversion updates | 0.1.3 |
0.1.2 | 2015-03-15 | bugfixes | 0.1.2 |
0.1.1 | 2015-02-22 | updated presets, added conversions | 0.1.1 |
0.1.0 | 2015-01-20 | 1st public release | 0.1.0 |
Name | Role | Website |
---|---|---|
Karsten Schmidt | initiator & principal developer | https://thi.ng |
This project is open source and licensed under the Apache Software License 2.0.