thi-ng / Color
Programming Languages
#+SETUPFILE: src/setup.org #+TITLE: thi.ng/color
[[http://media.thi.ng/color/presets/rainbow1.svg]]
- Contents :toc_3_gh:
- [[#about-the-project][About the project]]
- [[#overview][Overview]]
- [[#leiningen-coordinates][Leiningen coordinates]]
- [[#stable][Stable]]
- [[#status][Status]]
- [[#example-usage][Example usage]]
- [[#namespaces][Namespaces]]
- [[#tests][Tests]]
- [[#project-definition][Project definition]]
- [[#injected-properties][Injected properties]]
- [[#dependencies][Dependencies]]
- [[#runtime][Runtime]]
- [[#development][Development]]
- [[#leiningen-coordinates][Leiningen coordinates]]
- [[#building-this-project][Building this project]]
- [[#testing][Testing]]
- [[#working-with-the-repl][Working with the REPL]]
- [[#leiningen-project-file][Leiningen project file]]
- [[#clojurescript-html-harness][ClojureScript HTML harness]]
- [[#accessing-library-version-during-runtime][Accessing library version during runtime]]
- [[#version-namespace][Version namespace]]
- [[#release-history][Release history]]
- [[#contributors][Contributors]]
- [[#license][License]]
- About the project ** Overview
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.
** Leiningen coordinates *** Stable #+BEGIN_SRC clojure [thi.ng/color "1.4.0"] #+END_SRC
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
** Status
STABLE & under regular development, 170+ tests
** Example usage
#+BEGIN_SRC clojure (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") #+END_SRC
- Namespaces
- [[./src/core.org][thi.ng.color.core]]
- [[./src/gradients.org][thi.ng.color.gradients]]
- [[./src/presets.org][thi.ng.color.presets]]
- Tests
- [[./test/core.org][thi.ng.color.test.core]]
- Project definition ** Injected properties :noexport:
#+BEGIN_SRC clojure :noweb-ref version 1.4.0 #+END_SRC
#+BEGIN_SRC clojure :exports none :noweb-ref project-url http://thi.ng/color #+END_SRC
#+BEGIN_SRC clojure :exports none :noweb yes :noweb-ref cljs-artefact-path target/color-<>.js #+END_SRC
** Dependencies *** Runtime **** [[https://github.com/clojure/clojure][Clojure]] #+BEGIN_SRC clojure :noweb-ref dep-clj [org.clojure/clojure "1.9.0"] #+END_SRC **** [[https://github.com/clojure/clojurescript][ClojureScript]] #+BEGIN_SRC clojure :noweb-ref dep-cljs [org.clojure/clojurescript "1.10.339"] #+END_SRC **** [[https://github.com/thi-ng/math][thi.ng/math]] #+BEGIN_SRC clojure :noweb-ref dep-math [thi.ng/math "0.3.0"] #+END_SRC **** [[https://github.com/thi-ng/dstruct][thi.ng/dstruct]] #+BEGIN_SRC clojure :noweb-ref dep-dstruct [thi.ng/dstruct "0.2.0"] #+END_SRC **** [[https://github.com/thi-ng/typedarrays/][thi.ng/typedarrays]] #+NAME: dep-arrays #+BEGIN_SRC clojure [thi.ng/typedarrays "0.1.3"] #+END_SRC **** [[https://github.com/thi-ng/strf][thi.ng/strf]] #+BEGIN_SRC clojure :noweb-ref dep-strf [thi.ng/strf "0.2.2"] #+END_SRC **** [[https://github.com/thi-ng/xerror][thi.ng/xerror]] #+BEGIN_SRC clojure :noweb-ref dep-xerror [thi.ng/xerror "0.1.0"] #+END_SRC
*** Development **** [[https://github.com/hugoduncan/criterium][Criterium]] #+BEGIN_SRC clojure :noweb-ref dep-criterium [criterium "0.4.4"] #+END_SRC
**** [[https://github.com/cemerick/clojurescript.test][clojurescript.test]] #+BEGIN_SRC clojure :noweb-ref dep-cljs-test [com.cemerick/clojurescript.test "0.3.3"] #+END_SRC
**** [[https://github.com/emezeske/lein-cljsbuild][Cljsbuild]] #+BEGIN_SRC clojure :noweb-ref dep-cljsbuild [lein-cljsbuild "1.1.7"] #+END_SRC
** Leiningen coordinates
#+BEGIN_SRC clojure :noweb yes :noweb-ref lein-coords [thi.ng/color <>] #+END_SRC
** Building this project
This project is written in a literate programming format and requires [[https://www.gnu.org/software/emacs/][Emacs]] & [[http://orgmode.org][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=):
#+BEGIN_SRC bash git clone https://github.com/thi.ng/color.git cd color ./tangle.sh src/.org test/.org #+END_SRC
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.
*** Testing
The =project.clj= file defines an alias to trigger a complete build & tests for both CLJ & CLJS versions.
#+BEGIN_SRC bash cd babel lein cleantest #+END_SRC
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.
*** Working with the REPL
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.
** Leiningen project file :noexport:
#+BEGIN_SRC clojure :tangle babel/project.clj :noweb yes :mkdirp yes :padline no (defproject thi.ng/color "<>" :description "Cross-platform CLJ/CLJS library for color conversion & manipulation." :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 "http://postspectacular.com"]
[:timezone "0"]]])
#+END_SRC
** ClojureScript HTML harness :noexport:
#+BEGIN_SRC html :tangle babel/index.html :noweb yes :mkdirp yes :padline no
<title><> test</title> <script type="text/javascript" src="<>"></script> #+END_SRC** Accessing library version during runtime
The autogenerated namespace =thi.ng.color.version= contains a single symbol =version= holding the version string defined above:
#+BEGIN_SRC clojure :noweb yes (use '[thi.ng.color.version])
(prn version) ; "<>" #+END_SRC
*** Version namespace :noexport:
#+BEGIN_SRC clojure :tangle babel/src/thi/ng/color/version.cljc :noweb yes :mkdirp yes :padline no :exports none (ns thi.ng.color.version)
(def version "<>") #+END_SRC
** Release history
| Version | Released | Description | Tagged GH URL | |-----------+------------+-----------------------------------------------------------+-----------------| | 1.2.1 | TBC | add opt gradient ramping | [[https://github.com/thi-ng/color/tree/1.2.1][1.2.1]] | | 1.2.0 | 2016-04-05 | update dstruct dep, refactor IBuffer impls, add tests | [[https://github.com/thi-ng/color/tree/1.2.0][1.2.0]] | | 1.1.2 | 2016-03-28 | add gradient presets | [[https://github.com/thi-ng/color/tree/1.1.2][1.1.2]] | | 1.1.1 | 2016-03-19 | fix dependencies | [[https://github.com/thi-ng/color/tree/1.1.1][1.1.1]] | | 1.1.0 | 2016-03-19 | defrecord impl, protocol updates, optimizations, bugfixes | [[https://github.com/thi-ng/color/tree/1.1.0][1.1.0]] | | 1.0.1 | 2015-12-25 | bugfix yuva & cie1931 rgba conversions | [[https://github.com/thi-ng/color/tree/1.0.1][1.0.1]] | | 1.0.0 | 2015-10-02 | complete rewrite using protocols | [[https://github.com/thi-ng/color/tree/1.0.0][1.0.0]] | | 0.3.1 | 2015-06-21 | add YCbCr & YUV conversion, update deps | [[https://github.com/thi-ng/color/tree/0.3.1][0.3.1]] | | 0.3.0 | 2015-06-15 | gradient ns, HSL/HCY/HCV color space support, bugfixes | [[https://github.com/thi-ng/color/tree/0.3.0][0.3.0]] | | 0.2.0 | 2015-05-26 | no more CLJX, CIE1931 color space support, doc updates | [[https://github.com/thi-ng/color/tree/0.2.0][0.2.0]] | | 0.1.3 | 2015-04-22 | bugfixes, conversion updates | [[https://github.com/thi-ng/color/tree/0.1.3][0.1.3]] | | 0.1.2 | 2015-03-15 | bugfixes | [[https://github.com/thi-ng/color/tree/0.1.2][0.1.2]] | | 0.1.1 | 2015-02-22 | updated presets, added conversions | [[https://github.com/thi-ng/color/tree/0.1.1][0.1.1]] | | 0.1.0 | 2015-01-20 | 1st public release | [[https://github.com/thi-ng/color/tree/0.1.0][0.1.0]] |
** Contributors
| Name | Role | Website | |-----------------+---------------------------------+-------------------------------------------| | [[mailto:[email protected]][Karsten Schmidt]] | initiator & principal developer | http://postspectacular.com, http://thi.ng |
** License
This project is open source and licensed under the [[http://www.apache.org/licenses/LICENSE-2.0][Apache Software License 2.0]].