Check If Character String Is a Valid Color Representation

Check if character string is a valid color representation

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

How to check if a string is a valid hex color representation?

/^#[0-9A-F]{6}$/i.test('#AABBCC')

To elaborate:

^ -> match beginning

# -> a hash

[0-9A-F] -> any integer from 0 to 9 and any letter from A to F

{6} -> the previous group appears exactly 6 times

$ -> match end

i -> ignore case

If you need support for 3-character HEX codes, use the following:

/^#([0-9A-F]{3}){1,2}$/i.test('#ABC')

The only difference here is that

 [0-9A-F]{6}

is replaced with

([0-9A-F]{3}){1,2}

This means that instead of matching exactly 6 characters, it will match exactly 3 characters, but only 1 or 2 times. Allowing ABC and AABBCC, but not ABCD

Combined solution :

var reg=/^#([0-9a-f]{3}){1,2}$/i;
console.log(reg.test('#ABC')); //true
console.log(reg.test('#AABBCC')); //true

Check if a string defines a color

Here is the way to check if the string defines a color using matplotlib:

>>> from matplotlib.colors import is_color_like
>>>
>>> is_color_like('red')
True
>>> is_color_like('re')
False
>>> is_color_like(0.5)
False
>>> is_color_like('0.5')
True
>>> is_color_like(None)
False
>>>
>>> matplotlib.colors.__file__
'/usr/lib/python2.7/site-packages/matplotlib/colors.py'

In the source code of the matplotlib.colors module it's written:

The module also provides functions for checking whether an object can be
interpreted as a color (:func:is_color_like), for converting such an object
to an RGBA tuple (:func:to_rgba) or to an HTML-like hex string in the
#rrggbb format (:func:to_hex), and a sequence of colors to an (n, 4)
RGBA array (:func:to_rgba_array). Caching is used for efficiency.

How to identify a given string is hex color format

Note: This is strictly for validation, i.e. accepting a valid hex color. For actual parsing you won't get the individual parts out of this.

^#(?:[0-9a-fA-F]{3}){1,2}$

For ARGB:

^#(?:[0-9a-fA-F]{3,4}){1,2}$

Dissection:

^              anchor for start of string
# the literal #
( start of group
?: indicate a non-capturing group that doesn't generate backreferences
[0-9a-fA-F] hexadecimal digit
{3} three times
) end of group
{1,2} repeat either once or twice
$ anchor for end of string

This will match an arbitrary hexadecimal color value that can be used in CSS, such as #91bf4a or #f13.

How to check if a string is an rgb hex string

Normally, the best way to see if a string matches some simple format is to actually try to parse it. (Especially if you're only checking so you can then parse it if valid, or print an error if not.) So, let's do that.

The standard library is full of all kinds of useful things, so it's always worth searching. If you want to parse a hex string, the first thing that comes up is binascii.unhexlify. We want to unhexlify everything after the first # character. So:

import binascii

def parse_bgcolor(bgcolor):
if not bgcolor.startswith('#'):
raise ValueError('A bgcolor must start with a "#"')
return binascii.unhexlify(bgcolor[1:])

def is_bgcolor(bgcolor):
try:
parse_bgcolor(bgcolor)
except Exception as e:
return False
else:
return True

This accepts 3-character hex strings (but then so do most data formats that use #-prefixed hex RGB), and even 16-character ones. If you want to add a check for the length, you can add that. Is the rule == 6 or in (3, 6) or % 3 == 0? I don't know, but presumably you do if you have a rule you want to add.

If you start using parse_bgcolor, you'll discover that it's giving you a bytes with 6 values from 0-255, when you really wanted 3 values from 0-65535. You can combine them manually, or you can parse each two-character pair as a number (e.g., with int(pair, 16)), or you can feed the 6-char bytes you already have into, say, struct.unpack('>HHH'). Whatever you need to do is pretty easy once you know exactly what you want to do.

Finally, if you're trying to parse CSS or HTML, things like red or rgb(1, 2, 3) are also valid colors. Do you need to handle those? If so, you'll need something a bit smarter than this. The first thing to do is look at the spec for what you're trying to parse, and work out the rules you need to turn into code. Then you can write the code.

Validating if a string is a valid ARGB

For either language, you can use regular expressions to ensure a string matches your expectations. Here are some examples in Typescript and C#.

Typescript

const argbRegex = /^#[0-9a-fA-F]{8}$/;
argbRegex.test("#ffffffff"); // true
argbRegex.test("#gggggggg"); // false

C#

Regex argbRegex = new Regex("^#[0-9a-fA-F]{8}$");
argbRegex.IsMatch("#ffffffff"); // True
argbRegex.IsMatch("#gggggggg"); // False

Since you didn't mention it in your question, there are some things that you might want to consider that I did not cover:

  • Should a 3 character RGB string be a valid ARGB string?
  • Should a 6 character RGB string be a valid ARGB string?
  • Do you strictly require the # symbol?
  • Do you need to extract the decimal values for each ARGB component?

However, if all you need to do is validate the string is strictly in the 8 characters ARGB format, the above examples will work ok.

Check if string is valid representation of hex number

I would have thought that it's quickest to attempt to convert your string to an integral type and deal with any exception. Use code like this:

int num = Int32.Parse(s, System.Globalization.NumberStyles.HexNumber);

The resulting code is possibly easier to follow than a regular expression and is particularly useful if you need the parsed value (else you could use Int32.TryParse which is adequately documented in other answers).

(One of my favourite quotations is by Jamie Zawinski: "Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems.")



Related Topics



Leave a reply



Submit