diff --git a/examples/colors.ipynb b/examples/colors.ipynb index 4f404dee..8166b6b8 100644 --- a/examples/colors.ipynb +++ b/examples/colors.ipynb @@ -76,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 5, "metadata": { "collapsed": false }, @@ -90,11 +90,11 @@ "\n", " \n", + " fill=\"#8B0000\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{U8}(0.0,0.0,1.0)" + "RGB{U8}(0.545,0.0,0.0)" ] }, "metadata": {}, @@ -109,11 +109,11 @@ "\n", " \n", + " fill=\"#A43F2C\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.29284122574765004,0.20616016088988381,0.8154590567565114)" + "RGB{Float64}(0.6449732480680251,0.24687858778696326,0.1718286334561658)" ] }, "metadata": {}, @@ -128,11 +128,11 @@ "\n", " \n", + " fill=\"#BB6956\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.34473316201852744,0.30261169288286327,0.6359164489679165)" + "RGB{Float64}(0.7317427172713643,0.41225340901460217,0.3386364074684657)" ] }, "metadata": {}, @@ -147,11 +147,11 @@ "\n", " \n", + " fill=\"#CD9284\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.3320652279465807,0.37816870085640947,0.4597207917942931)" + "RGB{Float64}(0.8039567309138798,0.5726364314657387,0.5160946953459501)" ] }, "metadata": {}, @@ -166,11 +166,11 @@ "\n", " \n", + " fill=\"#DBBBB3\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.2606854798779104,0.4433586313880962,0.27940782734210995)" + "RGB{Float64}(0.860528904523117,0.7346642346573816,0.7035894622428008)" ] }, "metadata": {}, @@ -185,11 +185,11 @@ "\n", " \n", + " fill=\"#E5E6E5\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(2.135658170401844e-7,0.5019607992717322,0.0)" + "RGB{Float64}(0.8999999623961378,0.9000000605076355,0.8999999906534984)" ] }, "metadata": {}, @@ -204,11 +204,11 @@ "\n", " \n", + " fill=\"#C2B6D4\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.37220781950534426,0.4811025938574362,0.0)" + "RGB{Float64}(0.760988507467883,0.7130985069476236,0.832485912065674)" ] }, "metadata": {}, @@ -223,11 +223,11 @@ "\n", " \n", + " fill=\"#9E88C3\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.5528978474402565,0.445996276949532,0.0)" + "RGB{Float64}(0.6188605152922215,0.5330855129690464,0.7631766169206075)" ] }, "metadata": {}, @@ -242,11 +242,11 @@ "\n", " \n", + " fill=\"#785CB0\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.709264766923926,0.3896484083057615,0.0)" + "RGB{Float64}(0.4699473714709525,0.3600450904359411,0.6920921699128304)" ] }, "metadata": {}, @@ -261,11 +261,11 @@ "\n", " \n", + " fill=\"#4D319E\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.8565683200929008,0.294237959040753,0.0)" + "RGB{Float64}(0.303237574455172,0.19182702742121874,0.6193214998443142)" ] }, "metadata": {}, @@ -280,49 +280,29 @@ "\n", " \n", + " fill=\"#00008B\" stroke=\"none\"/>\n", "\n" ], "text/plain": [ - "RGB{Float64}(0.9999999006125039,2.0222806256020575e-6,0.0)" + "RGB{Float64}(3.598763199685884e-7,0.0,0.545098034746462)" ] }, "metadata": {}, "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "11-element Array{Void,1}:\n", - " nothing\n", - " nothing\n", - " nothing\n", - " nothing\n", - " nothing\n", - " nothing\n", - " nothing\n", - " nothing\n", - " nothing\n", - " nothing\n", - " nothing" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ "using Plots\n", - "grad = Plots.ColorGradient([colorant\"blue\", colorant\"green\", colorant\"red\"], [0,0.5,1])\n", - "map(display, [Plots.getColor(grad, x) for x in 0:0.1:1])" + "#grad = Plots.ColorGradient([colorant\"blue\", colorant\"lightgrey\", colorant\"red\"], [0,0.5,1])\n", + "grad = Plots.ColorGradient(:redsblues)\n", + "map(display, [Plots.getColor(grad, x) for x in 0:0.1:1]);" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [] diff --git a/src/colors.jl b/src/colors.jl index 3ae0bb6c..32a1529f 100644 --- a/src/colors.jl +++ b/src/colors.jl @@ -80,6 +80,17 @@ convertColor(cvec::AbstractVector) = map(convertColor, cvec) abstract ColorScheme +getColor(scheme::ColorScheme, idx::Integer) = getColor(scheme, 0.0, idx) +getColor(scheme::ColorScheme, z::AbstractFloat) = getColor(scheme, z, 0) + +const _gradients = Dict( + :blues => [colorant"lightblue", colorant"darkblue"], + :reds => [colorant"lightpink", colorant"darkred"], + :greens => [colorant"lightgreen", colorant"darkgreen"], + :redsblues => [colorant"darkred", RGB(0.9,0.9,0.9), colorant"darkblue"] + :bluesreds => [colorant"darkblue", RGB(0.9,0.9,0.9), colorant"darkred"] + ) + # -------------------------------------------------------------- "Continuous gradient between values. Wraps a list of bounding colors and the values they represent." @@ -88,6 +99,20 @@ type ColorGradient <: ColorScheme values::Vector{Float64} end +# create a gradient from a symbol (blues, reds, etc) and vector of boundary values +function ColorGradient{T<:Real}(s::Symbol, vals::AVec{T} = 0:1) + haskey(_gradients, s) || error("Invalid gradient symbol. Choose from: ", sort(collect(keys(_gradients)))) + + # if we passed in the right number of values, create the gradient directly + cs = _gradients[s] + length(cs) == length(vals) && return ColorGradient(cs, collect(vals)) + + # otherwise interpolate evenly between the minval and maxval + minval, maxval = minimum(vals), maximum(vals) + vs = Float64[interpolate(minval, maxval, w) for w in linspace(0, 1, length(cs))] + ColorGradient(cs, vs) +end + function getColor(gradient::ColorGradient, z::Real, idx::Int) cs = gradient.colors vs = gradient.values @@ -102,7 +127,7 @@ function getColor(gradient::ColorGradient, z::Real, idx::Int) # find the bounding colors and interpolate for i in 2:n if z <= vs[i] - return interpolateColor(cs[i-1], cs[i], (z - vs[i-1]) / (vs[i] - vs[i-1])) + return interpolate(cs[i-1], cs[i], (z - vs[i-1]) / (vs[i] - vs[i-1])) end end @@ -110,15 +135,19 @@ function getColor(gradient::ColorGradient, z::Real, idx::Int) cs[end] end -function interpolateColor(c1::Colorant, c2::Colorant, w::Real) +function interpolate(c1::Colorant, c2::Colorant, w::Real) lab1 = Lab(c1) lab2 = Lab(c2) - l = (1-w) * lab1.l + w * lab2.l - a = (1-w) * lab1.a + w * lab2.a - b = (1-w) * lab1.b + w * lab2.b + l = interpolate(lab1.l, lab2.l, w) + a = interpolate(lab1.a, lab2.a, w) + b = interpolate(lab1.b, lab2.b, w) RGB(Lab(l, a, b)) end +function interpolate(v1::Real, v2::Real, w::Real) + (1-w) * v1 + w * v2 +end + # -------------------------------------------------------------- "Wraps a function, taking a z-value and index and returning a Colorant"