Is there a way to programmatically darken the colo

2019-01-23 06:31发布

Let's say I have the RGB values like this (in R, for example):

cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")

Is there any way to programmatically derive another set of colors which is a darkened version of the former?

It doesn't have to be R.

标签: r colors rgb
7条回答
乱世女痞
2楼-- · 2019-01-23 06:41

Here's something simple that works for me and returns the colors in the same format as the original:

library(colorspace)

cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")    
rgb(hex2RGB(cols)@coords * 0.8)
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-23 06:47

It's not really nice code. The munsell package might be more friendly

library(colorspace)

cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")

lab = as(hex2RGB(cols),"LAB")
lab@coords[,1] = lab@coords[,1] *0.3 # 
cols1 =  hex(as(lab,"RGB"))
cols1
查看更多
老娘就宠你
4楼-- · 2019-01-23 06:50

You can actually do this really easily in base graphics using colorRampPalette().

Just make a gradient with your initial color and black, ramp 100 and select "how much darker" you want it (1=initial and 100=black).

I made this in a neat little function :

darker.col = function(color, how.much = 30){
  colorRampPalette(c(color, "black"))(100)[how.much]
}

plot(1:100, rep(1, 100), pch=16, cex=5, col=darker.col("royalblue", 1:100))

查看更多
我只想做你的唯一
5楼-- · 2019-01-23 06:55
library(colorspace)

cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")

cols1 <- readhex(file = textConnection(paste(cols, collapse = "\n")),
                 class = "RGB")
#transform to hue/lightness/saturation colorspace
cols1 <- as(cols1, "HLS")
cols2 <- cols1
#additive decrease of lightness
cols1@coords[, "L"] <- pmax(0, cols1@coords[, "L"] - 0.3)
#multiplicative decrease of lightness
cols2@coords[, "L"] <- cols2@coords[, "L"] * 0.75
#going via rgb seems to work better  
cols1 <- as(cols1, "RGB")
cols1 <- hex(cols1)
cols2 <- as(cols2, "RGB")
cols2 <- hex(cols2)


plot(x = seq_along(cols), y = rep(1, length(cols)), 
     col = cols, pch = 15, ylim = c(0, 4.5), cex = 5,
     xlab = "", ylab = "")
points(x = seq_along(cols), y = rep(2, length(cols)), 
       col = cols1, pch = 16, cex = 5)
points(x = seq_along(cols), y = rep(3, length(cols)), 
       col = cols2, pch = 17, cex = 5)

legend("top",legend = c("original", "additive", "multipl."), 
       pch = 15:17, ncol = 3)

resulting plot

查看更多
啃猪蹄的小仙女
6楼-- · 2019-01-23 07:02

The question asks whether there is any way to programmatically darken colors. The problem is that there are many different ways, and they all yield different results. The specific outcome you obtain depends on the specific algorithm employed and the color space used.

The R package colorspace now provides a built-in function to darken colors, through the darken() function. This function uses a new "combined" colorspace we came up with which is a mix between HLS and HCL. (In brief, adjusts L in HCL space but adjusts C by taking a detour through HLS, while keeping H constant.)

To use this function, you need to install the current development version of colorspace:

install.packages("colorspace", repos = "http://R-Forge.R-project.org")

Then, try the following:

# original colors
cols <- c("#CDE4F3", "#E7F3D3", "#F7F0C7", "#EFCFE5", "#D0D1E7")

# darken 20%
cols_d2 <- darken(cols, 0.2)

# darken 40%
cols_d4 <- darken(cols, 0.4)

# plot
pal <- function(col, border = "light gray") {
  n <- length(col)
  plot(0, 0, type="n", xlim = c(0, 1), ylim = c(0, 1), axes = FALSE,
       xlab = "", ylab = "")
  rect(0:(n-1)/n, 0, 1:n/n, 1, col = col, border = border)
}

par(mfrow = c(3, 1), mar = c(1, 0, 2, 0))
pal(cols); mtext("original")
pal(cols_d2); mtext("20% darker")
pal(cols_d4); mtext("40% darker")

enter image description here

There are a couple of different color spaces and other adjustment options you can try, but the default should work in most cases.

To see the effect of darkening in different color spaces, consider what happens when we darken the same colors in HCL or HLS:

enter image description here

The HCL-darkened colors seem quite gray, and the HLS-darkened colors appear overly bright and colorful. However, depending on your specific application, you might want one of these outcomes.

查看更多
Luminary・发光体
7楼-- · 2019-01-23 07:02

HSV Value Adjustment

This seems much better than my first stab with Munsell colors (below). It's still a bit of a run-around (probably because I'm mixing packages that specify colors in rows and columns and take matrices or not), but it works:

cols.hsv = rgb2hsv(cols.rgb)
# adjust the "value" down to 80% of it's previous level
cols.hsv["v", ] = cols.hsv["v", ] * 0.8

cols.darker = cols
for (i in seq_along(cols)) {
    cols.darker[i] = hsv(cols.hsv[1, i], cols.hsv[2, i], cols.hsv[3, i])
}

par(mfrow = c(1, 2))
scales::show_col(cols)
scales::show_col(cols.darker)

Munsell

I've not used the munsell package before, so I might be making this more complicated than it needs to be, but it has a function darker that "Decreases the value of the Munsell colour by 1."

The hard part is conversions. As near as I can tell, we need to get your hex colors to Munsell colors we have to go via RGB.

cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")
cols.rgb = col2rgb(cols)

library(munsell)
# munsell expects rgb colors in rows, not columns, and expects the
# values to be between 0 and 1, not 0 and 255
cols.m = rgb2mnsl(t(cols.rgb) / rowSums(t(cols.rgb)))

# make darker
darker.m = darker(cols.m)
# at least converting back to hex is one step!
darker.hex = mnsl2hex(darker.m)


# view the results
par(mfrow = c(2, 1))
scales::show_col(cols)
scales::show_col(darker.hex)

Overall I'm not thrilled with this solution. It made the colors much darker and I don't see a way to adjust that in the darker function.

查看更多
登录 后发表回答