Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if character string is a valid color representation

Tags:

r

Short question, if I have a string, how can I test if that string is a valid color representation in R?

Two things I tried, first uses the function col2rgb() to test if it is a color:

isColor <- function(x) {   res <- try(col2rgb(x),silent=TRUE)   return(!"try-error"%in%class(res)) }  > isColor("white") [1] TRUE > isColor("#000000") [1] TRUE > isColor("foo") [1] FALSE 

Works, but doesn't seem very pretty and isn't vectorized. Second thing is to just check if the string is in the colors() vector or a # followed by a hexadecimal number of length 4 to 6:

isColor2 <- function(x) {   return(x%in%colors() | grepl("^#(\\d|[a-f]){6,8}$",x,ignore.case=TRUE)) }  > isColor2("white") [1] TRUE > isColor2("#000000") [1] TRUE > isColor2("foo") [1] FALSE 

Which works though I am not sure how stable it is. But it seems that there should be a built in function to make this check?

like image 996
Sacha Epskamp Avatar asked Nov 08 '12 12:11

Sacha Epskamp


People also ask

How do you check if a string is a valid hex color?

The length of the hexadecimal color code should be either 6 or 3, excluding '#' symbol. For example: #abc, #ABC, #000, #FFF, #000000, #FF0000, #00FF00, #0000FF, #FFFFFF are all valid Hexadecimal color codes.

Is Hex valid?

Yes, in hexadecimal, things like A, B, C, D, E, and F are considered numbers, not letters. That means that 200 is a perfectly valid hexadecimal number just as much as 2FA is also a valid hex number.

Is string a Colour?

String has great warmth and richnessString is a great colour - always choose delicate shades from Farrow and Ball but this time I wanted something with a litte more colour depth. I wasn't disappointed. It has a changing face depending on the time of day and the natural light levels entering the room.

What is the regular expression for a valid HTML hex color value?

regex = "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"; Where: ^ represents the starting of the string. # represents the hexadecimal color code must start with a '#' symbol.


2 Answers

Your first idea (using col2rgb() to test color names' validity for you) seems good to me, and just needs to be vectorized. As for whether it seems pretty or not ... lots/most R functions aren't particularly pretty "under the hood", which is a major reason to create a function in the first place! Hides all those ugly internals from the user.

Once you've defined areColors() below, using it is easy as can be:

areColors <- function(x) {      sapply(x, function(X) {          tryCatch(is.matrix(col2rgb(X)),                    error = function(e) FALSE)          })      }  areColors(c(NA, "black", "blackk", "1", "#00", "#000000")) #   <NA>   black  blackk       1     #00 #000000  #   TRUE    TRUE   FALSE    TRUE   FALSE    TRUE  
like image 178
Josh O'Brien Avatar answered Oct 06 '22 00:10

Josh O'Brien


Update, given the edit

?par gives a thorough description of the ways in which colours can be specified in R. Any solution to a valid colour must consider:

  1. A named colour as listed in colors()
  2. A hexademical representation, as a character, of the form "#RRGGBBAA specifying the red, green, blue and alpha channels. The Alpha channel is for transparency, which not all devices support and hence whilst it is valid to specify a colour in this way with 8 hex values it may not be valid on a specific device.
  3. NA is a valid "colour". It means transparent, but as far as R is concerned it is a valid colour representation.
  4. Likewise "transparent" is also valid, but not in colors(), so that needs to be handled as well
  5. 1 is a valid colour representation as it is the index of a colour in a small palette of colours as returned by palette()

    > palette() [1] "black"   "red"     "green3"  "blue"    "cyan"    "magenta" "yellow"  [8] "gray" 

    Hence you need to cope with 1:8. Why is this important, well ?par tells us that it is also valid to represent the index for these colours as a character hence you need to capture "1" as a valid colour representation. However (as noted by @hadley in the comments) this is just for the default palette. Another palette may be used by a user, in which case you will have to consider a character index to an element of a vector of the maximum allowed length for your version of R.

Once you've handled all those you should be good to go ;-)

To the best of my knowledge there isn't a user-visible function that does this. All of this in buried away inside the C code that does the plotting; very quickly you end up in .Internal(....) land and there be dragons!


Original

[To be pedantic #000000 isn't a colour name in R.]

The only colour names R knows are those returned by colors(). Yes, #000000 is one of the colour representations that R understands but you specifically ask about a name and the definitive list or solution is x %in% colors() as you have in your second example.

This is about as stable as it gets. When you use a colour like col = "goldenrod", internally R matches this with a "proper" representation of the colour for whichever device you are plotting on. color() returns the list of colour names that R can do this looking up for. If it isn't in colors() then it isn't a colour name.

like image 23
Gavin Simpson Avatar answered Oct 05 '22 22:10

Gavin Simpson