README.md

chroma

chroma is a R package for parsing and formating colors in various specifications, manipulating colors, and creating nice color scales and palettes. Much of the functionality is based on the excellent chroma.js javascript library by Gregor Aish.

Installation

chroma is not on CRAN yet. To get it from this page, install the package devtools and

devtools::install_github("jiho/chroma")
library("chroma")

NB: some functions in the chroma package mask functions in basic R packages (e.g. grDevices) or often used ones (e.g. ggplot2). Most of the time, they are argument-compatible with the function they mask and, if their result is different, I would argue that the one in chroma is more correct. If you want to use chroma but would rather not mask the other functions, just install the package but do not load it with library(); instead, just call the functions with the chroma:: prefix (e.g. chroma::rgb() instead of rgb(), to avoid masking rgb() in package grDevices).

Color parsing

Parse colors in various specifications

rgb(r=0.5, g=0.5, b=0.5)
# [1] "#808080"
ryb(r=0.5, y=0.5, b=0.5)
# [1] "#957149"
hsv(h=120, s=0.5, v=0.5)
# [1] "#408040"
hsl(h=120, s=0.5, l=0.5)
# [1] "#40BF40"
hsi(h=120, s=0.5, i=0.5)
# [1] "#40FF40"
hcl(h=120, c=0.5, l=0.5)
# [1] "#638127"
lab(l=0.5, a=-0.5, b=0.2)
# [1] "#008A53"
hex("#393939")
# [1] "#393939"
hex("F39")
# [1] "#FF3399"
css("rgb(100,100,100)")
# [1] "#646464"
temperature(5600)
# [1] "#FFEDE2"
wavelength(500)
# [1] "#178672"

Parse directly from a matrix

x <- matrix(c(0.2, 0.5, 0.5, 0.5, 0.6, 0.4), ncol=3)
print(x)
#      [,1] [,2] [,3]
# [1,]  0.2  0.5  0.6
# [2,]  0.5  0.5  0.4
rgb(x)
# [1] "#338099" "#808066"

Color formating

Convert back in various formats

as.rgb("coral1")
#      r         g         b
# [1,] 1 0.4470588 0.3372549
as.ryb("coral1")
#             r        y          b
# [1,] 0.424082 0.296286 0.08746012
as.hsv("coral1")
#             h         s v
# [1,] 9.940828 0.6627451 1
as.hsl("coral1")
#             h s         l
# [1,] 9.940828 1 0.6686275
as.hsi("coral1")
#            h        s         i
# [1,] 8.89147 0.432967 0.5947712
as.hcl("coral1")
#             h         c         l
# [1,] 38.74251 0.6651031 0.6494095
as.lab("coral1")
#              l        a         b
# [1,] 0.6494095 0.518758 0.4162358
as.hex("coral1")
# [1] "#FF7256"
as.css("coral1")
# [1] "RGB(255,114,86)"
as.temperature("coral1")
# [1] 2686
as.wavelength("coral1")
# [1] 616

Color manipulation

Slightly modify a base color

col <- "#7BBBFE"
show_col(c(col, brighten(col), darken(col)))

show_col(c(col, desaturate(col), saturate(col)))

Make a color semi-transparent

col <- "#7BBBFE"
show_col(c(col, alpha(col), alpha(col, 0.2)))

Mix or blend two colors

show_col(c("#7BBBFE", "#FDFF68", mix("#7BBBFE", "#FDFF68")))

show_col(c("#7BBBFE", "#FDFF68", blend("#7BBBFE", "#FDFF68")))

show_col(c("#7BBBFE", "#FDFF68", blend("#7BBBFE", "#FDFF68", mode="screen")))

Compute the contrast between two colors

contrast("darkblue", "darkgreen")
# [1] 2.056261
contrast("yellow", "darkgreen")
# [1] 6.927705

Compute the euclidean or perceptual distance between two colors (following the CIE Delta E 2000 formula)

# pick three colors; lightgreen is closer to darkgreen that darkblue is
show_col(c("darkblue", "darkgreen", "lightgreen"))

color_distance("darkblue", "darkgreen")
# [1] 146.5474
color_distance("lightgreen", "darkgreen")
# [1] 50.67107
CMClc("darkblue", "darkgreen")
# [1] 81.42556
CMClc("lightgreen", "darkgreen")
# [1] 35.98541
deltaE("darkblue", "darkgreen")
# [1] 57.91349
deltaE("lightgreen", "darkgreen")
# [1] 43.52127

which allows to find the closest perceived color in a array of possibilities

target <- "limegreen"
choices <- rainbow(10)
closest_color <- choices[which.min(deltaE(target, choices))]
show_col(target, choices, closest_color)

Extract or set a color channel

col <- "#7BBBFE"
channel(col, model="hcl", "h")
#        h 
# 266.7734
channel(col, model="hsv", "s")
#        s 
# 0.515748
channel(col, model="hsi", "i")
#         i 
# 0.7372549
channel(col, model="rgb", "r")
#         r 
# 0.4823529
col1 <- col2 <- col
channel(col1, model="hcl", "h") <- 120
channel(col2, model="hcl", "l") <- 1
show_col(c(col, col1, col2))

Compute or set the perceived luminance of a color

luminance(c("red", "yellow", "darkblue"))
# [1] 0.2126000 0.9278000 0.0186408
col1 <- col2 <- col <- "#7BBBFE"
luminance(col)
# [1] 0.4690736
luminance(col1) <- 0.6
luminance(col2) <- 0.2
show_col(c(col, col1, col2))

Color scales and palettes

All scales and palettes are organised the same way:

x <- 0:10/10
s <- interp_scale()
s(x)
#  [1] "#FFFFFF" "#E2E2E2" "#C6C6C6" "#ABABAB" "#919191" "#777777" "#5E5E5E"
#  [8] "#474747" "#303030" "#1B1B1B" "#000000"
# or
interp_map(x)
#  [1] "#FFFFFF" "#E2E2E2" "#C6C6C6" "#ABABAB" "#919191" "#777777" "#5E5E5E"
#  [8] "#474747" "#303030" "#1B1B1B" "#000000"
n <- 11
p <- interp_palette()
p(n)
#  [1] "#FFFFFF" "#E2E2E2" "#C6C6C6" "#ABABAB" "#919191" "#777777" "#5E5E5E"
#  [8] "#474747" "#303030" "#1B1B1B" "#000000"
# or
interp_colors(n)
#  [1] "#FFFFFF" "#E2E2E2" "#C6C6C6" "#ABABAB" "#919191" "#777777" "#5E5E5E"
#  [8] "#474747" "#303030" "#1B1B1B" "#000000"

Palettes can be built by interpolating between colors

show_col(interp_colors(10))

show_col(interp_colors(10, colors=c("#2D2B63", "#F7FF84")))

show_col(interp_colors(10, colors=c("#2D2B63", "#FB3C44", "#F7FF84")))

For the perception of “change” along the scale to be more linear, colors can be interpolated using bezier curves and their lightness can be corrected.

show_col(interp_colors(10, colors=c("#2D2B63", "#FB3C44", "#F7FF84")))

show_col(interp_colors(10, colors=c("#2D2B63", "#FB3C44", "#F7FF84"), interp="bezier"))

show_col(interp_colors(10, colors=c("#2D2B63", "#FB3C44", "#F7FF84"), interp="bezier", correct.lightness=TRUE))

Preset palettes are available, from colorbrewer

show_col(lapply(brewer_info$name, function(x) {brewer_colors(n=7, name=x)}))

Or viridis

show_col(
  viridis_colors(10),
  magma_colors(10),
  plasma_colors(10),
  inferno_colors(10)
)

Or cubehelix

show_col(
  cubehelix_colors(10),
  cubehelix_colors(10, h=300, rot=-0.75),
  cubehelix_colors(10, h=120, rot=0.5),
  cubehelix_colors(10, h=300, rot=0.5)
)

Or ETOPO1 and Wikipedia for topographical maps

show_col(
  etopo_colors(100),
  wikitopo_colors(100)
)

Custom, perceptually appropriate, palettes can be built in HCL space, for either discrete

show_col(hue_colors(10))

or continuous variables

show_col(chroma_colors(10, h=140))

show_col(light_colors(10, h=140))

Helper functions

Additional functions are included to facilitate the use of the color scales in base and ggplot2 plots.

sidemargin() and sidelegend() allow to place legends on the side of base plots

attach(iris)
# make larger right margin
pars <- sidemargin()
# plot the data with a nice color scale
plot(Petal.Length, Petal.Width, col=hue_map(Species), pch=19)
# add a legend for the scale on the side
sidelegend(legend=levels(Species), col=hue_colors(nlevels(Species)), pch=19)

# set graphical parameters back to default
par(pars)
detach(iris)

persp_facets() allows to compute the colors for each facet of a persp() plot

persp(maunga, theta=50, phi=25, scale=FALSE, expand=2,
      border=alpha("black", 0.4),
      col=magma_map(persp_facets(maunga$z)))

Various scale_color_*() and scale_fill_*() functions allow to use the color scales defined in chroma directly with ggplots and scale_xy_map() draws nice x and y scales for maps.

ggplot(iris) +
  geom_point(aes(Petal.Length, Sepal.Length, color=Species)) +
  scale_color_cubehelix_d(h=0, rot=0.75, c=1, l=c(0.6, 0.6))

ggplot(thaixyz) + coord_quickmap() +
 geom_raster(aes(x, y, fill=z)) +
 scale_fill_wikitopo() + scale_xy_map()

Happy coloring!



jiho/chroma documentation built on Nov. 26, 2022, 2:39 a.m.