有没有办法以编程方式使给定 RGB 值的颜色变暗?
Is there a way to programmatically darken the color given RGB values?
假设我有这样的 RGB 值(例如,在 R 中):
cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")
有没有办法以编程方式导出另一组颜色,即前者的深色版本?
不一定是R。
是的。
你将必须指定你想要的颜色变深或变浅。
这是在 JavaScript 中完成的函数:https://css-tricks.com/snippets/javascript/lighten-darken-color/
function LightenDarkenColor(col, amt) {
var usePound = false;
if (col[0] == "#") {
col = col.slice(1);
usePound = true;
}
var num = parseInt(col,16);
var r = (num >> 16) + amt;
if (r > 255) {
r = 255;
}else if (r < 0){
r = 0;
}
var b = ((num >> 8) & 0x00FF) + amt;
if (b > 255) {
b = 255;
}else if (b < 0) {
b = 0;
}
var g = (num & 0x0000FF) + amt;
if (g > 255) {
g = 255;
}else if (g < 0) {
g = 0;
}
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}
希望对您有所帮助,
干杯。
HSV值调整
这似乎比我第一次尝试 Munsell 颜色(下图)要好得多。它仍然有点 运行 左右(可能是因为我正在混合指定行和列中的颜色以及是否采用矩阵的包),但它有效:
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
包,所以我可能会把它变得比它需要的更复杂,但它有一个功能 darker
"Decreases the value of the Munsell colour by 1."
困难的部分是转化。据我所知,我们需要通过 RGB 将您的十六进制颜色转换为 Munsell 颜色。
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)
总的来说,我对这个解决方案并不满意。它使颜色 更 更暗,我没有在 darker
函数中看到调整它的方法。
这不是很好的代码。 munsell
包可能更友好
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
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)
问题询问是否有任何方法 以编程方式使颜色变暗。问题是有很多不同的方法,它们都会产生不同的结果。您获得的具体结果取决于所采用的具体算法和使用的颜色 space。
R 包 colorspace
现在通过 darken()
函数提供了一个内置函数来使颜色变暗。此函数使用我们提出的新 "combined" colorspace,它是 HLS 和 HCL 的混合体。 (简而言之,调整 HCL 中的 L space,但绕过 HLS 调整 C,同时保持 H 不变。)
使用该功能需要安装当前开发版colorspace:
install.packages("colorspace", repos = "http://R-Forge.R-project.org")
然后,尝试以下操作:
# 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")
您可以尝试几种不同的颜色 space 和其他调整选项,但大多数情况下默认值应该有效。
要查看不同颜色变暗的效果 spaces,请考虑当我们在 HCL 或 HLS 中将相同颜色变暗时会发生什么:
HCL 加暗的颜色看起来很灰,HLS 加暗的颜色显得过于明亮和鲜艳。但是,根据您的具体应用,您可能需要这些结果之一。
您实际上可以使用 colorRampPalette()
在基本图形中非常轻松地做到这一点。
只需使用您的初始颜色和黑色制作渐变,渐变 100 和 select "how much darker" 您想要的(1=初始和 100=黑色)。
我用一个简洁的小函数做了这个:
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))
这是适合我的简单方法,returns颜色与原始格式相同:
library(colorspace)
cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")
rgb(hex2RGB(cols)@coords * 0.8)
假设我有这样的 RGB 值(例如,在 R 中):
cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")
有没有办法以编程方式导出另一组颜色,即前者的深色版本?
不一定是R。
是的。
你将必须指定你想要的颜色变深或变浅。
这是在 JavaScript 中完成的函数:https://css-tricks.com/snippets/javascript/lighten-darken-color/
function LightenDarkenColor(col, amt) {
var usePound = false;
if (col[0] == "#") {
col = col.slice(1);
usePound = true;
}
var num = parseInt(col,16);
var r = (num >> 16) + amt;
if (r > 255) {
r = 255;
}else if (r < 0){
r = 0;
}
var b = ((num >> 8) & 0x00FF) + amt;
if (b > 255) {
b = 255;
}else if (b < 0) {
b = 0;
}
var g = (num & 0x0000FF) + amt;
if (g > 255) {
g = 255;
}else if (g < 0) {
g = 0;
}
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}
希望对您有所帮助, 干杯。
HSV值调整
这似乎比我第一次尝试 Munsell 颜色(下图)要好得多。它仍然有点 运行 左右(可能是因为我正在混合指定行和列中的颜色以及是否采用矩阵的包),但它有效:
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
包,所以我可能会把它变得比它需要的更复杂,但它有一个功能 darker
"Decreases the value of the Munsell colour by 1."
困难的部分是转化。据我所知,我们需要通过 RGB 将您的十六进制颜色转换为 Munsell 颜色。
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)
总的来说,我对这个解决方案并不满意。它使颜色 更 更暗,我没有在 darker
函数中看到调整它的方法。
这不是很好的代码。 munsell
包可能更友好
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
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)
问题询问是否有任何方法 以编程方式使颜色变暗。问题是有很多不同的方法,它们都会产生不同的结果。您获得的具体结果取决于所采用的具体算法和使用的颜色 space。
R 包 colorspace
现在通过 darken()
函数提供了一个内置函数来使颜色变暗。此函数使用我们提出的新 "combined" colorspace,它是 HLS 和 HCL 的混合体。 (简而言之,调整 HCL 中的 L space,但绕过 HLS 调整 C,同时保持 H 不变。)
使用该功能需要安装当前开发版colorspace:
install.packages("colorspace", repos = "http://R-Forge.R-project.org")
然后,尝试以下操作:
# 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")
您可以尝试几种不同的颜色 space 和其他调整选项,但大多数情况下默认值应该有效。
要查看不同颜色变暗的效果 spaces,请考虑当我们在 HCL 或 HLS 中将相同颜色变暗时会发生什么:
HCL 加暗的颜色看起来很灰,HLS 加暗的颜色显得过于明亮和鲜艳。但是,根据您的具体应用,您可能需要这些结果之一。
您实际上可以使用 colorRampPalette()
在基本图形中非常轻松地做到这一点。
只需使用您的初始颜色和黑色制作渐变,渐变 100 和 select "how much darker" 您想要的(1=初始和 100=黑色)。
我用一个简洁的小函数做了这个:
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))
这是适合我的简单方法,returns颜色与原始格式相同:
library(colorspace)
cols <- c("#CDE4F3","#E7F3D3","#F7F0C7","#EFCFE5","#D0D1E7")
rgb(hex2RGB(cols)@coords * 0.8)