Given a finite palette, how to sort from Hot to Co

2020-06-14 07:59发布

Update (Original question below)

Issue is partially solved.

Still trying to figure out how to extend to other color combinations

If I use this code

hLIM <- rgb2hsv(col2rgb('#8000ff'))['h', ]
sLIM <- rgb2hsv(col2rgb('#8000ff'))['s', ]
vLIM <- rgb2hsv(col2rgb('#8000ff'))['v', ]
rankorder <- order((hLIM-tHSVcol[,1] + (hLIM < tHSVcol[,1])),
                   (sLIM-tHSVcol[,2] + (sLIM < tHSVcol[,2])),
                   (vLIM-tHSVcol[,3] + (vLIM < tHSVcol[,3])))

orderType <- "HSV Ordering"

I am able to sort this

enter image description here

Unsorted Color Palette:

"#313695","#fdae61","#a50026","#ffffbf","#f46d43","#fee090","#e0f3f8","#74add1","#d73027","#4575b4","#abd9e9"

Into this

enter image description here

Sorted Color Palette:

"#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1", "#4575b4","#313695"

However, I have difficulty extending it to other color combinations.

For Instance when I try to sort this

enter image description here

Unsorted

"#22325f" "#88ce64" "#fbd234" "#b8091f" "#682f4e" "#fdea6e" "#4aec6a" "#fb7894" "#f13111" "#2584a0" "#460809" "#00699e" "#391b72" "#03471d" "#ba0841"

I get this (Interesting part is, I'm unsure how the perfectly sorted palette would look like ---- certainly no dark bands interspersed!)

enter image description here

Imperfectly Sorted

"#391b72" "#22325f" "#00699e" "#2584a0" "#03471d" "#4aec6a" "#88ce64" "#fdea6e" "#fbd234" "#f13111" "#460809" "#b8091f" "#fb7894" "#ba0841" "#682f4e"



Original Question

I have a finite palette, how to sort from Hot(reds) to Cold(blues).

How do I turn this

enter image description here

Unsorted Color Palette:

"#313695","#fdae61","#a50026","#ffffbf","#f46d43","#fee090","#e0f3f8","#74add1","#d73027","#4575b4","#abd9e9"

Into this

enter image description here

Sorted Color Palette:

"#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1", "#4575b4","#313695"

R Code is at the end of the message. I tried sorting by combinations of RGB and HSV, (based on what is commented, or uncommented) but to no avail.

I am unable to find a pattern in the following values (where colors are sorted divergently)

Any guidance is greatly appreciated.

RGB Sorted Color

> tRGBcol
      red green blue
 [1,] 165     0   38
 [2,] 215    48   39
 [3,] 244   109   67
 [4,] 253   174   97
 [5,] 254   224  144
 [6,] 255   255  191
 [7,] 224   243  248
 [8,] 171   217  233
 [9,] 116   173  209
[10,]  69   117  180
[11,]  49    54  149

HSV Sorted Color

> tHSVcol
                h          s         v
 [1,] 0.961616162 1.00000000 0.6470588
 [2,] 0.008522727 0.81860465 0.8431373
 [3,] 0.039548023 0.72540984 0.9568627
 [4,] 0.082264957 0.61660079 0.9921569
 [5,] 0.121212121 0.43307087 0.9960784
 [6,] 0.166666667 0.25098039 1.0000000
 [7,] 0.534722222 0.09677419 0.9725490
 [8,] 0.543010753 0.26609442 0.9137255
 [9,] 0.564516129 0.44497608 0.8196078
[10,] 0.594594595 0.61666667 0.7058824
[11,] 0.658333333 0.67114094 0.5843137

Manually split hex colors

a5  00  26
d7  30  27
f4  6d  43
fd  ae  61
fe  e0  90
ff  ff  bf
e0  f3  f8
ab  d9  e9
74  ad  d1
45  75  b4
31  36  95

Code

RenderPal <- function(x,name){

  if ((missing(x)) || (missing(name))){
    stop("Internal error, please troubleshoot")
  }
  n <- length(x)
  old <- graphics::par(mar = c(0.5, 0.5, 0.5, 0.5))
  on.exit(graphics::par(old))

  graphics::image(1:n, 1, as.matrix(1:n), col = x,
                  ylab = "", xaxt = "n", yaxt = "n", bty = "n")
  graphics::rect(0, 0.9, n + 1, 1.1, col = grDevices::rgb(1, 1, 1, 0.8), border = NA)
  graphics::text((n + 1) / 2, 1, labels = name, cex = 2, family = "serif")
}

i <- NULL
oldPal <- NULL
rankorder <- c(1,2,3,4,5,6,7,8,9,10,11)
orderedPal<- NULL
RGBcol <- NULL
HSVcol <- NULL
tHSVcol <- NULL
orderType <- "Unsorted"



oldPal <- c("#313695","#fdae61","#a50026","#ffffbf","#f46d43","#fee090","#e0f3f8","#74add1","#d73027","#4575b4","#abd9e9")

# Print hex values
oldPal

# Convert Hex to RGB
RGBcol <- col2rgb(oldPal)

# Print RGB values
RGBcol

# Transpose matrix
tRGBcol <- t(RGBcol)

# Print matrix
tRGBcol

# Uncomment following to order by Red, Green, then Blue
# rankorder <- order(tRGBcol[,1],tRGBcol[,2],tRGBcol[,3])
# orderType <- "Red Ordering"

# Uncomment following to order by Blue, Green, then Red
# rankorder <- order(tRGBcol[,3],tRGBcol[,2],tRGBcol[,1])
# orderType <- "Blue Ordering"

# Uncomment following to order by Green, Blue then Red
# rankorder <- order(tRGBcol[,2],tRGBcol[,3],tRGBcol[,1])
# orderType <- "Green Ordering"

# Uncomment following to order by Red + Blue
# rANDb <- apply(tRGBcol[,c(1,3)],1,sum)
# rankorder <- order(rANDb)
# orderType <- "Red + Blue Ordering"

# Uncomment following to order by Red + Green + Blue
# rANDgANDb <- apply(tRGBcol[,c(1,2,3)],1,sum)
# rankorder <- order(rANDgANDb)
# orderType <- "Red + Green + Blue Ordering"

# Convert RGB to HSV
HSVcol <- rgb2hsv(RGBcol)

# Print matrix
HSVcol

# Transpose matrix
tHSVcol <- t(HSVcol)

# Print matrix
tHSVcol


# Uncomment following to order by Hue, then Saturation, then Value
# rankorder <- order(tHSVcol[,1],tHSVcol[,2],tHSVcol[,3])
# orderType <- "Hue Ordering"

# Uncomment following to order by hANDv = Hue + Value
# hANDv <- apply(tHSVcol[,c(1,3)],1,sum)
# rankorder <- order(hANDv)
# orderType <- "Hue + Value Ordering"

# Uncomment following to order by hPRODv = Hue * Value
# hPRODv <- apply(tHSVcol[,c(1,3)],1,prod)
# rankorder <- order(hPRODv)
# orderType <- "Hue * Value Ordering"

# Combine matrices tRGBcol and tHSVcol
tCombo <- cbind(tRGBcol,tHSVcol)

rankorder

for (i in 1:length(rankorder)){
  orderedPal[i] <- oldPal[rankorder[i]]
}

# Print old, unordered palette
oldPal

# Print new, ordered palette
orderedPal

RenderPal(oldPal, "Unordered Palette")
RenderPal(orderedPal, orderType)

Edit: Result when I sort by Hue

enter image description here

1条回答
ゆ 、 Hurt°
2楼-- · 2020-06-14 08:33

I get almost your requested order with this:

Coolness = function(P) { 
    RGB = col2rgb(P)
    (RGB[3,] - RGB[1,]) / (RGB[3,] + RGB[1,])
}

CoolPal = oldPal[order(Coolness(oldPal))]
RenderPal(CoolPal, "Coolness")

Palette Ordered by coolness

But notice that I have swapped the first two colors. Your suggested answer says that "#a50026" is hotter than "#d73027". My Coolness function has the opposite ordering for those two.

查看更多
登录 后发表回答