What would be a good way to convert hex color values like #ffffff
into the single RGB values 255 255 255
using PHP?
Answers
Note: both versions of rgbToHex
expect integer values for r
, g
and b
, so you'll need to do your own rounding if you have non-integer values.
The following will do to the RGB to hex conversion and add any required zero padding:
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function rgbToHex(r, g, b) {
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
alert(rgbToHex(0, 51, 255)); // #0033ff
Converting the other way:
function hexToRgb(hex) {
var result = /^#?([a-fd]{2})([a-fd]{2})([a-fd]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
alert(hexToRgb("#0033ff").g); // "51";
Finally, an alternative version of rgbToHex()
, as discussed in @casablanca's answer and suggested in the comments by @cwolves:
function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
alert(rgbToHex(0, 51, 255)); // #0033ff
Update 3 December 2012
Here's a version of hexToRgb()
that also parses a shorthand hex triplet such as "#03F":
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-fd])([a-fd])([a-fd])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-fd]{2})([a-fd]{2})([a-fd]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
alert(hexToRgb("#0033ff").g); // "51";
alert(hexToRgb("#03f").g); // "51";
var hexDigits = new Array
("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
//Function to convert rgb color to hex format
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb((d+),s*(d+),s*(d+))$/);
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
function hex(x) {
return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16];
}
(Source)
Real answer: Depends on what kind of hexadecimal color value you are looking for (e.g. 565, 555, 888, 8888, etc), the amount of alpha bits, the actual color distribution (rgb vs bgr...) and a ton of other variables.
Here's a generic algorithm for most RGB values using C++ templates (straight from ScummVM).
template<class T>
uint32 RGBToColor(uint8 r, uint8 g, uint8 b) {
return T::kAlphaMask |
(((r << T::kRedShift) >> (8 - T::kRedBits)) & T::kRedMask) |
(((g << T::kGreenShift) >> (8 - T::kGreenBits)) & T::kGreenMask) |
(((b << T::kBlueShift) >> (8 - T::kBlueBits)) & T::kBlueMask);
}
Here's a sample color struct for 565 (the standard format for 16 bit colors):
template<>
struct ColorMasks<565> {
enum {
highBits = 0xF7DEF7DE,
lowBits = 0x08210821,
qhighBits = 0xE79CE79C,
qlowBits = 0x18631863,
kBytesPerPixel = 2,
kAlphaBits = 0,
kRedBits = 5,
kGreenBits = 6,
kBlueBits = 5,
kAlphaShift = kRedBits+kGreenBits+kBlueBits,
kRedShift = kGreenBits+kBlueBits,
kGreenShift = kBlueBits,
kBlueShift = 0,
kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
kRedMask = ((1 << kRedBits) - 1) << kRedShift,
kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
kBlueMask = ((1 << kBlueBits) - 1) << kBlueShift,
kRedBlueMask = kRedMask | kBlueMask
};
};
Looking at the sample I guess you mean that a string array is actually an array of HEX representation of bytes, don't you?
If yes, then for each string item I would do the following:
- check that a string consists only of 2 characters
- these chars are in '0'..'9' or 'a'..'f' interval (take their case into account as well)
- convert each character to a corresponding number, subtracting code value of '0' or 'a'
build a byte value, where first char is higher bits and second char is lower ones. E.g.
int byteVal = (firstCharNumber << 4) | secondCharNumber;
Check out PHP's
hexdec()
anddechex()
functions: http://php.net/manual/en/function.hexdec.phpExample: