Skip to content

Instantly share code, notes, and snippets.

@chrisschreiner
Created July 11, 2010 12:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisschreiner/471501 to your computer and use it in GitHub Desktop.
Save chrisschreiner/471501 to your computer and use it in GitHub Desktop.
Color utilities for CSS
(import 'java.awt.Color)
(def *default-color-fraction* 0.2)
(def *default-blend-fraction* 0.5)
(defn- format-hex [c]
(str "#" (format "%02x%02x%02x"
(.getRed c)
(.getGreen c)
(.getBlue c))))
(defn- string-or-keyword? [t]
(some #(identical? % (type t)) [clojure.lang.Keyword java.lang.String]))
(defn- inside-byte [n]
(cond
(< n 0) 0
(> n 255) 255
:else (int n)))
(defn- expand-3-letter-color [color]
{:pre [(some #(= % (count (drop 1 (name color)))) [3 6])]}
(let [ic (name color)
c (if (= \# (first ic)) (apply str (drop 1 ic)) ic)]
(if (= 3 (count c))
(->> c (repeat 2) (apply interleave) (apply str "#"))
ic)))
(defn- extract-proper-color [color]
(condp identical? (type color)
clojure.lang.Keyword (extract-proper-color (name color))
java.lang.String (Color/decode (expand-3-letter-color color))
color))
(defn- lightdark [color fraction op]
{:pre [(identical? java.awt.Color (type (extract-proper-color color)))]}
(let [c (extract-proper-color color)
fr (op 1.0 fraction)
[red green blue] (map #(-> % (* fr) Math/round inside-byte)
[(.getRed c) (.getGreen c) (.getBlue c)])
alpha (.getAlpha c)
result (Color. red green blue alpha)]
(if (some string-or-keyword? [color])
(format-hex result)
result)))
(defn lighter
([color]
(lighter color *default-color-fraction*))
([color fraction]
(lightdark color fraction +)))
(defn darker
([color]
(darker color *default-color-fraction*))
([color fraction]
(lightdark color fraction -)))
(defn blend
([color1 color2]
(blend color1 color2 *default-blend-fraction*))
([color1 color2 ratio]
(let [[c1 c2] (map extract-proper-color [color1 color2])
ir (- 1.0 ratio)
[rgb1 rgb2] (map #(.getColorComponents % (float-array 3)) [c1 c2])
[r g b] (map #(int (* 255 (+ (* ratio (nth rgb1 %)) (* ir (nth rgb2 %))))) (range 3))
result (Color. r g b)]
(if (some string-or-keyword? [color1 color2])
(format-hex result)
result))))
(comment "usage:"
(darker Color/red) ; => #<Color java.awt.Color[r=204,g=0,b=0]>
(darker "#FFFF00") ; => "#cccc00
(darker (lighter :#AA00FF)) ; => "#a300cc"
(darker (lighter "#AA00FF" 0.1) 0.3) ; => "#8300b3"
(blend :#FFAA00 Color/magenta) ; => "#Fff557f"
(blend (darker Color/red) Color/blue) ; => #<Color java.awt.Color[r=102,g=0,b=127]>
(blend (darker Color/red) (lighter :#FFAA44)) ; => "#e56629"
(blend (darker :#AEF) (lighter :#333)) ; => "#627d84"
(lighter "#800") ; => "#a30000"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment