Каков наиболее эффективный способ сделать это?
Преобразование шестнадцатеричного цвета в RGB и наоборот
Ответ 1
Реальный ответ: зависит от того, какое именно шестнадцатеричное значение цвета вы ищете (например, 565, 555, 888, 8888 и т.д.), количество альфа-бит, фактическое распределение цветов (rgb vs bgr...) и тонны других переменных.
Вот общий алгоритм для большинства значений RGB с использованием шаблонов С++ (прямо из 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);
}
Здесь образец цветовой структуры для 565 (стандартный формат для 16-битных цветов):
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
};
};
Ответ 2
В python:
def hex_to_rgb(value):
"""Return (red, green, blue) for the color given as #rrggbb."""
value = value.lstrip('#')
lv = len(value)
return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
def rgb_to_hex(red, green, blue):
"""Return color as #rrggbb for the given color values."""
return '#%02x%02x%02x' % (red, green, blue)
hex_to_rgb("#ffffff") #==> (255, 255, 255)
hex_to_rgb("#ffffffffffff") #==> (65535, 65535, 65535)
rgb_to_hex(255, 255, 255) #==> '#ffffff'
rgb_to_hex(65535, 65535, 65535) #==> '#ffffffffffff'
Ответ 3
В преобразовании python между шестнадцатеричным и 'rgb' также входит в пакет построения matplotlib
. А именно
import matplotlib.colors as colors
Тогда
colors.hex2color('#ffffff') #==> (1.0, 1.0, 1.0)
colors.rgb2hex((1.0, 1.0, 1.0)) #==> '#ffffff'
Предостережение заключается в том, что значения rgb в цветах считаются между 0.0 и 1.0. Если вы хотите перейти от 0 до 255, вам нужно сделать небольшое преобразование. В частности,
def hex_to_rgb(hex_string):
rgb = colors.hex2color(hex_string)
return tuple([int(255*x) for x in rgb])
def rgb_to_hex(rgb_tuple):
return colors.rgb2hex([1.0*x/255 for x in rgb_tuple])
Другое примечание состоит в том, что colors.hex2color
принимает только допустимые шестнадцатеричные строки цвета.
Ответ 4
просто быстро:
int r = ( hexcolor >> 16 ) & 0xFF;
int g = ( hexcolor >> 8 ) & 0xFF;
int b = hexcolor & 0xFF;
int hexcolor = (r << 16) + (g << 8) + b;
Ответ 5
Изменение ответа на python Джереми для обработки коротких значений CSS rgb, таких как 0, # 999 и #fff (какие браузеры будут отображать как черный, средний серый и белый):
def hex_to_rgb(value):
value = value.lstrip('#')
lv = len(value)
if lv == 1:
v = int(value, 16)*17
return v, v, v
if lv == 3:
return tuple(int(value[i:i+1], 16)*17 for i in range(0, 3))
return tuple(int(value[i:i+lv/3], 16) for i in range(0, lv, lv/3))
Ответ 6
Шестнадцатеричное значение - это только числа RGB, представленные в шестнадцатеричном формате. Поэтому вам просто нужно взять каждую пару шестнадцатеричных цифр и преобразовать их в десятичные.
Пример:
#FF6400 = RGB(0xFF, 0x64, 0x00) = RGB(255, 100, 0)
Ответ 7
#!/usr/bin/env python import re import sys def hex_to_rgb(value): value = value.lstrip('#') lv = len(value) return tuple(int(value[i:i+lv/3], 16) for i in range(0, lv, lv/3)) def rgb_to_hex(rgb): rgb = eval(rgb) r = rgb[0] g = rgb[1] b = rgb[2] return '#%02X%02X%02X' % (r,g,b) def main(): color = raw_input("HEX [#FFFFFF] or RGB [255, 255, 255] value (no value quits program): ") while color: if re.search('\#[a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]', color): converted = hex_to_rgb(color) print converted elif re.search('[0-9]{1,3}, [0-9]{1,3}, [0-9]{1,3}', color): converted = rgb_to_hex(color) print converted elif color == '': sys.exit(0) else: print 'You didn\'t enter a valid value!' color = raw_input("HEX [#FFFFFF] or RGB [255, 255, 255] value (no value quits program): ") if __name__ == '__main__': main()
Ответ 8
Это фрагмент кода, который я создал для моего собственного использования в С++ 11. вы можете отправить шестнадцатеричные значения или строки:
void Color::SetColor(string color) {
// try catch will be necessary if your string is not sanitized before calling this function.
SetColor(std::stoul(color, nullptr, 16));
}
void Color::SetColor(uint32_t number) {
B = number & 0xFF;
number>>= 8;
G = number & 0xFF;
number>>= 8;
R = number & 0xFF;
}
// ex:
SetColor("ffffff");
SetColor(0xFFFFFF);
Ответ 9
Вам нужно только преобразовать значение hex (по частям) в десятичное и наоборот. Также необходимо учитывать, какое значение в шестнадцатеричном виде может содержать 6 или 3 символа (без символа '#').
Реализация на Python 3.5
"""Utils for working with colors."""
import textwrap
def rgb_to_hex(value1, value2, value3):
"""
Convert RGB value (as three numbers each ranges from 0 to 255) to hex format.
>>> rgb_to_hex(235, 244, 66)
'#EBF442'
>>> rgb_to_hex(56, 28, 26)
'#381C1A'
>>> rgb_to_hex(255, 255, 255)
'#FFFFFF'
>>> rgb_to_hex(0, 0, 0)
'#000000'
>>> rgb_to_hex(203, 244, 66)
'#CBF442'
>>> rgb_to_hex(53, 17, 8)
'#351108'
"""
for value in (value1, value2, value3):
if not 0 <= value <= 255:
raise ValueError('Value each slider must be ranges from 0 to 255')
return '#{0:02X}{1:02X}{2:02X}'.format(value1, value2, value3)
def hex_to_rgb(value):
"""
Convert color`s value in hex format to RGB format.
>>> hex_to_rgb('fff')
(255, 255, 255)
>>> hex_to_rgb('ffffff')
(255, 255, 255)
>>> hex_to_rgb('#EBF442')
(235, 244, 66)
>>> hex_to_rgb('#000000')
(0, 0, 0)
>>> hex_to_rgb('#000')
(0, 0, 0)
>>> hex_to_rgb('#54433f')
(84, 67, 63)
>>> hex_to_rgb('#f7efed')
(247, 239, 237)
>>> hex_to_rgb('#191616')
(25, 22, 22)
"""
if value[0] == '#':
value = value[1:]
len_value = len(value)
if len_value not in [3, 6]:
raise ValueError('Incorect a value hex {}'.format(value))
if len_value == 3:
value = ''.join(i * 2 for i in value)
return tuple(int(i, 16) for i in textwrap.wrap(value, 2))
if __name__ == '__main__':
import doctest
doctest.testmod()
Реализация на JavaScript (адаптирована к NodeJS с поддержкой ES6)
const assert = require('assert');
/**
* Return a color`s value in the hex format by passed the RGB format.
* @param {integer} value1 An value in ranges from 0 to 255
* @param {integer} value2 An value in ranges from 0 to 255
* @param {integer} value3 An value in ranges from 0 to 255
* @return {string} A color`s value in the hex format
*/
const RGBtoHex = (value1, value2, value3) => {
const values = [value1, value2, value3];
let result = '#';
for (let i = 0; i < 3; i += 1) {
// validation input
if (values[i] < 0 || values[i] > 255) throw new Error('An each value of RGB format must be ranges from 0 to 255');
// append to result values as hex with at least width 2
result += (('0' + values[i].toString(16)).slice(-2));
}
return result.toUpperCase();
};
/**
* Convert a value from the hex format to RGB and return as an array
* @param {int} value A color`s value in the hex format
* @return {array} Array values of the RGB format
*/
const hexToRGB = (value) => {
let val = value;
val = (value[0] === '#') ? value.slice(1) : value;
if ([3, 6].indexOf(val.length) === -1) throw new Error(`Incorect a value of the hex format: ${value}`);
if (val.length === 3) val = val.split('').map(item => item.repeat(2)).join('');
return val.match(/.{2}/g).map(item => parseInt(`0x${item}`, 16));
};
assert.deepEqual(hexToRGB('fff'), [255, 255, 255]);
assert.deepEqual(hexToRGB('#fff'), [255, 255, 255]);
assert.deepEqual(hexToRGB('#000000'), [0, 0, 0]);
assert.deepEqual(hexToRGB('000000'), [0, 0, 0]);
assert.deepEqual(hexToRGB('#d7dee8'), [215, 222, 232]);
assert.deepEqual(hexToRGB('#1E2F49'), [30, 47, 73]);
assert.deepEqual(hexToRGB('#030914'), [3, 9, 20]);
assert.equal(RGBtoHex(255, 255, 255), '#FFFFFF');
assert.equal(RGBtoHex(0, 0, 0), '#000000');
assert.equal(RGBtoHex(96, 102, 112), '#606670');
assert.equal(RGBtoHex(199, 204, 214), '#C7CCD6');
assert.equal(RGBtoHex(22, 99, 224), '#1663E0');
assert.equal(RGBtoHex(0, 8, 20), '#000814');
module.exports.RGBtoHex = RGBtoHex;
module.exports.hexToRGB = hexToRGB;
Реализация на C (предназначена для стандартного C11)
// a type for a struct of RGB color
typedef struct _ColorRGB {
unsigned short int red;
unsigned short int green;
unsigned short int blue;
} colorRGB_t;
/*
Convert a color`s value from the hex format to the RGB.
Return -1 if a passed value in the hex format is not correct, otherwise - return 0;
*/
static int
convertColorHexToRGB(const char originValue[], colorRGB_t *colorRGB) {
// a full value of color in hex format must constains 6 charapters
char completedValue[6];
size_t lenOriginValue;
size_t lenCompletedValue;
// an intermediary variable for keeping value in the hex format
char hexSingleValue[3];
// a temp pointer to char, need only to the strtol()
char *ptr;
// a variable for keeping a converted number in the hex to the decimal format
long int number;
// validation input
lenOriginValue = strlen(originValue);
if (lenOriginValue > 7 || lenOriginValue < 3) return -1;
// copy value without sign '#', if found as first in the string
(originValue[0] == '#') ? strcpy(completedValue, originValue + 1) : strcpy(completedValue, originValue);
lenCompletedValue = strlen(completedValue);
// if the value has only 3 charapters, dublicate an each after itself
// but if not full version of the hex name of a color (6 charapters), return -1
if (lenCompletedValue == 3) {
completedValue[5] = completedValue[2];
completedValue[4] = completedValue[2];
completedValue[3] = completedValue[1];
completedValue[2] = completedValue[1];
completedValue[1] = completedValue[0];
} else if (lenCompletedValue != 6) return -1;
// convert string, by parts, to decimal values and keep it in a struct
sprintf(hexSingleValue, "%c%c", completedValue[0], completedValue[1]);
number = strtol(hexSingleValue, &ptr, 16);
colorRGB->red = number;
sprintf(hexSingleValue, "%c%c", completedValue[2], completedValue[3]);
number = strtol(hexSingleValue, &ptr, 16);
colorRGB->green = number;
sprintf(hexSingleValue, "%c%c", completedValue[4], completedValue[5]);
number = strtol(hexSingleValue, &ptr, 16);
colorRGB->blue = number;
return 0;
}
/*
Convert a color`s value from the RGB format to the hex
*/
static int
convertColorRGBToHex(const colorRGB_t *colorRGB, char value[8]) {
sprintf(value, "#%02X%02X%02X", colorRGB->red, colorRGB->green, colorRGB->blue);
return 0;
}
/*
Forming a string representation data in an instance of the structure colorRGB_t
*/
static int
getRGBasString(const colorRGB_t *colorRGB, char str[18]) {
sprintf(str, "rgb(%d, %d, %d)", colorRGB->red, colorRGB->green, colorRGB->blue);
return 0;
}
int main (int argv, char **argc)
{
char str[18];
char hex[8];
colorRGB_t *colorRGB_;
colorRGB_ = (colorRGB_t *)malloc(sizeof(colorRGB_));
convertColorHexToRGB("fff", colorRGB_);
getRGBasString(colorRGB_, str);
printf("Hex 'fff' to RGB %s\n", str);
convertColorRGBToHex(colorRGB_, hex);
printf("RGB %s to hex '%s'\n", str, hex);
convertColorHexToRGB("000000", colorRGB_);
getRGBasString(colorRGB_, str);
printf("Hex '000000' to RGB %s\n", str);
convertColorRGBToHex(colorRGB_, hex);
printf("RGB %s to hex '%s'\n", str, hex);
convertColorHexToRGB("#000000", colorRGB_);
getRGBasString(colorRGB_, str);
printf("Hex '#000000' to RGB %s\n", str);
convertColorRGBToHex(colorRGB_, hex);
printf("RGB %s to hex '%s'\n", str, hex);
convertColorHexToRGB("#FFF", colorRGB_);
getRGBasString(colorRGB_, str);
printf("Hex '#FFF' to RGB %s\n", str);
convertColorRGBToHex(colorRGB_, hex);
printf("RGB %s to hex '%s'\n", str, hex);
free(colorRGB_);
}
Результат после компиляции (я использую GCC)
Hex 'fff' to RGB rgb(255, 255, 255)
RGB rgb(255, 255, 255) to hex '#FFFFFF'
Hex '000000' to RGB rgb(0, 0, 0)
RGB rgb(0, 0, 0) to hex '#000000'
Hex '#000000' to RGB rgb(0, 0, 0)
RGB rgb(0, 0, 0) to hex '#000000'
Hex '#FFF' to RGB rgb(255, 255, 255)
RGB rgb(255, 255, 255) to hex '#FFFFFF'