Dear all, My thanks to everyone who addressed my question. I've incorporated Eik Vettorazzi's suggestion for improved conversion of hexadecimal RGB colours to decimal numbers, and Martin Maechler's hint to look at demo(colors). I've loosened the default definition of "close enough" from the latter, since the following seems to work well for my purposes.
r2c <- function(){ hex2dec <- function(hexnums) { # suggestion of Eik Vettorazzi sapply(strtoi(hexnums, 16L), function(x) x %/% 256^(2:0) %% 256) } findMatch <- function(dec.col) { sq.dist <- colSums((hsv - dec.col)^2) rbind(which.min(sq.dist), min(sq.dist)) } colors <- colors() hsv <- rgb2hsv(col2rgb(colors)) function(cols, near=0.25){ cols <- sub("^#", "", toupper(cols)) dec.cols <- rgb2hsv(hex2dec(cols)) which.col <- apply(dec.cols, 2, findMatch) matches <- colors[which.col[1, ]] unmatched <- which.col[2, ] > near^2 matches[unmatched] <- paste("#", cols[unmatched], sep="") matches } } rgb2col <- r2c() For example, > rgb2col(c("010101", "EEEEEE", "AA0000", "00AA00", "0000AA", "AAAA00", "AA00AA", "00AAAA")) [1] "black" "gray93" "darkred" "green4" [5] "blue4" "darkgoldenrod" "darkmagenta" "cyan4" > rgb2col(c("010101", "090909", "090000", "000900", "000009", "090900", "090009", "000909")) [1] "black" "gray3" "#090000" "#000900" "#000009" "#090900" [7] "#090009" "#000909" Thanks again, John > -----Original Message----- > From: r-help-boun...@r-project.org [mailto:r-help-bounces@r- > project.org] On Behalf Of John Fox > Sent: Thursday, May 30, 2013 8:13 AM > To: r-help@r-project.org > Subject: [R] measuring distances between colours? > > Dear r-helpers, > > I'm interested in locating the named colour that's "closest" to an > arbitrary RGB colour. The best that I've been able to come up is the > following, which uses HSV colours for the comparison: > > r2c <- function(){ > hexnumerals <- 0:15 > names(hexnumerals) <- c(0:9, LETTERS[1:6]) > hex2decimal <- function(hexnums){ > hexnums <- strsplit(hexnums, "") > decimals <- matrix(0, 3, length(hexnums)) > decimals[1, ] <- sapply(hexnums, function(x) > sum(hexnumerals[x[1:2]] * c(16, 1))) > decimals[2, ] <- sapply(hexnums, function(x) > sum(hexnumerals[x[3:4]] * c(16, 1))) > decimals[3, ] <- sapply(hexnums, function(x) > sum(hexnumerals[x[5:6]] * c(16, 1))) > decimals > } > colors <- colors() > hsv <- rgb2hsv(col2rgb(colors)) > function(cols){ > cols <- sub("^#", "", toupper(cols)) > dec.cols <- rgb2hsv(hex2decimal(cols)) > colors[apply(dec.cols, 2, function(dec.col) > which.min(colSums((hsv - dec.col)^2)))] > } > } > > rgb2col <- r2c() > > I've programmed this with a closure so that hsv gets computed only > once. > > Examples: > > > rgb2col(c("AA0000", "002200", "000099", "333300", "BB00BB", > "#005555")) > [1] "darkred" "darkgreen" "blue4" "darkgreen" "magenta3" > "darkgreen" > > rgb2col(c("AAAA00", "#00AAAA")) > [1] "darkgoldenrod" "cyan4" > > Some of these colour matches, e.g., "#005555" -> "darkgreen" seem poor > to me. Even if the approach is sound, I'd like to be able to detect > that there is no sufficiently close match in the vector of named > colours. That is, can I establish a maximum acceptable distance in the > HSV (or some other) colour space? > > I vaguely recall a paper or discussion concerning colour representation > in R but can't locate it. > > Any suggestions would be appreciated. > > John > > ------------------------------------------------ > John Fox > Sen. William McMaster Prof. of Social Statistics > Department of Sociology > McMaster University > Hamilton, Ontario, Canada > http://socserv.mcmaster.ca/jfox/ > > ______________________________________________ > R-help@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting- > guide.html > and provide commented, minimal, self-contained, reproducible code. ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.