UIColor from hex string, once again

Tue, 26. Nov 2013

Categories: en development Tags: Cocoa Hex NSString Objective C UIColor

I end up doing this once per year โ€“ at least it’s getting leaner each time.

 1static inline NSInteger NSIntegerFromHexDigit(const unichar c)
 2{
 3  switch( c ) {
 4  case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
 5    return c - '0';
 6  case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 7    return c - 'a' + 10;
 8  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 9    return c - 'A' + 10;
10  default:
11    return -1;
12  }
13}
14
15typedef NSUInteger RGBA32;
16
17/** RGBA hex color matching /^(?:0x|#)?([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?$/i
18 */
19static BOOL RGBAFromNSStringHex(NSString *hex, RGBA32 *value)
20{
21  const NSUInteger len = hex.length;
22  if( len < 6 || len > 9 )
23    return NO;
24  unichar buffer[len];
25  [hex getCharacters:buffer range:NSMakeRange(0, len)];
26
27  // check if either 6 or 8 char hex
28  const BOOL hasHashPrefix = buffer[0] == '#';
29  const NSInteger netlen = len - hasHashPrefix;
30  if( netlen != 6 && netlen != 8 )
31    return NO;
32
33  // turn hex to integer
34  NSUInteger ret = 0;
35  assert(sizeof(ret) >= 4); // need at least 4 bytes
36  for( NSInteger i = hasHashPrefix; i < len; i++ ) {
37    const NSInteger v = NSIntegerFromHexDigit(buffer[i]);
38    if( v < 0 )
39      return NO;
40    ret <<= 4;
41    ret |= v;
42  }
43  // if 6-char hex assume alpha 0xFF
44  if( netlen == 6 ) {
45    ret <<= 8;
46    ret |= 0xFF;
47  }
48
49  if( value )
50    *value = ret;
51  return YES;
52}

How to get a UIColor from here should be straightforward.

P.S.: Wikipedia about ‘RGBA’