Как сохранить значения RGB (A) в массиве?

Я пытаюсь написать функцию, которая будет принимать цвет RGB (A) и сохранять его значения в массиве, с возможностью исключить альфа-значение. У меня возникают проблемы с выяснением, как написать регулярное выражение, которое будет соответствовать входным данным, но я думаю, что что-то вроде этого — то, что я ищу:

function rgb_array( $color, $include_alpha = true ) {

$pattern = 'what goes here?';

$color = preg_match( $pattern, $color, $matches);

if ( $include_alpha == true && ! empty( $matches[4] ) ) {
$color = array( $matches[1], $matches[2], $matches[3], $matches[4] );
} else {
$color = array( $matches[1], $matches[2], $matches[3] );
}

return $color;
}

Я хотел бы иметь возможность кормить его любой допустимой формой rgb / rgba:

rgb(0,0,0)
rgb(00,00,00)
rgb(0, 0, 0)
rgb(00, 00, 00)
rgba(0,0,0,0.5)
rgba(255, 255, 255, 1)
etc...

И пусть он производит массив:

[0] => '00', // red
[1] => '00', // green
[2] => '00', // blue
[3] => '1' // alpha only included if available and desired.

На данный момент я могу сделать это через str_replace:

$color  = 'rgb(12, 14, 85)';
$remove = array( 'rgb', 'a', '(', ')', ' ' );
$color  = str_replace( $remove, '', $color );
$color  = explode( ',', $color );

Но это кажется хакерским, и я не могу найти хороший способ опционально включить / исключить альфа.

Спасибо за вашу помощь, и если есть совершенно другой подход, чем preg_match это было бы лучше, я все уши.

2

Решение

Мой ответ не только извлечет значения подстроки, которые вы хотите, но и дополнительно обеспечит достаточно высокий уровень проверки (а не 100% -ную проверку). Я изменил шаблон из https://stackoverflow.com/a/31245990/2943403 точнее ответить на этот вопрос. Я надеюсь, что вы найдете этот ответ точным, элегантным и прямым.

Если вы хотите сократить / упростить шаблон, это будет делать: (Regex101 Demo)
~^rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([.\d]+))?\)$~

Код: (Демо w / $ include_alpha = true) (Демо w / $ include_alpha = false) (Regex101 Demo)

function rgb_array($color, $include_alpha = true) {
$pattern = '~^rgba?\((25[0-5]|2[0-4]\d|1\d{2}|\d\d?)\s*,\s*(25[0-5]|2[0-4]\d|1\d{2}|\d\d?)\s*,\s*(25[0-5]|2[0-4]\d|1\d{2}|\d\d?)\s*(?:,\s*([01]\.?\d*?))?\)$~';

if (!preg_match($pattern, $color, $matches)) {
return [];  // disqualified / no match
}

return array_slice($matches, 1, $include_alpha ? 4 : 3);
}

$strings = [
'rgb(0,0,0)',
'rgb(00,00,00)',
'rgb(0, 0, 0)',
'donkey eggs',
'rgb(00, 00, 00)',
'rgba(0,0,0,0.5)',
'rgba(255, 255, 255, 1)'
];

foreach ($strings as $string) {
echo "Process: $string\n";
var_export(rgb_array($string));
echo "\n";
}

Выход:

Process: rgb(0,0,0)
array (
0 => '0',
1 => '0',
2 => '0',
)
Process: rgb(00,00,00)
array (
0 => '00',
1 => '00',
2 => '00',
)
Process: rgb(0, 0, 0)
array (
0 => '0',
1 => '0',
2 => '0',
)
Process: donkey eggs
array (
)
Process: rgb(00, 00, 00)
array (
0 => '00',
1 => '00',
2 => '00',
)
Process: rgba(0,0,0,0.5)
array (
0 => '0',
1 => '0',
2 => '0',
3 => '0.5',
)
Process: rgba(255, 255, 255, 1)
array (
0 => '255',
1 => '255',
2 => '255',
3 => '1',
)

постскриптум Если вы хотите использовать preg_split() Вы можете быть гораздо менее конкретным в отношении своего паттерна. Вот вам одна строчка (демонстрация)

function rgb_array($color, $include_alpha = true) {
return array_slice(preg_split('~[^\d.]+~', $color, -1, PREG_SPLIT_NO_EMPTY), 0, $include_alpha + 3);
}
3

Другие решения

Если вам нужно решение для регулярных выражений, вот оно:

rgba?\((\s?\d+),(\s?\d+),(\s?\d+)(?:,\s?(\d+(?:\.\d+)?))?\)

Это соответствует 'rgb' в начале, затем необязательный 'a' и левый parenthesзатем он создает 3 одинаковые группы, соответствующие оптиналу белому Space сопровождаемый одним или несколькими digits, Четвертая группа является необязательной и соответствует одному или нескольким digitsс последующим dotи один или несколько digits,

Цвета будут в индексах 1, 2, 3 и 4 (при наличии).

2

Вы могли бы использовать preg_split разделить строку на составные части. Регулярное выражение разбивает строку в одном из ведущих rgba(, , или отставая ), PREG_SPLIT_NO_EMPTY Флаг используется, чтобы избежать пустых значений в выходном массиве.

$strings = array('rgb(0,0,0)',
'rgb(00,00,00)',
'rgb(0, 0, 0)',
'rgb(00, 00, 00)',
'rgba(0,0,0,0.5)',
'rgba(255, 255, 255, 1)');
foreach ($strings as $string) {
print_r(preg_split('/rgba?\(\s*|\s*,\s*|\s*\)/', $string, -1, PREG_SPLIT_NO_EMPTY));
}

Выход:

Array
(
[0] => 0
[1] => 0
[2] => 0
)
Array
(
[0] => 00
[1] => 00
[2] => 00
)
Array
(
[0] => 0
[1] => 0
[2] => 0
)
Array
(
[0] => 00
[1] => 00
[2] => 00
)
Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0.5
)
Array
(
[0] => 255
[1] => 255
[2] => 255
[3] => 1
)
2

Немного улучшилось explode решение:

function rgb_array($color, $include_alpha = true)
{
$color = trim($color, 'rgba()');       # "rgba(255, 255, 255, 1)" => "255, 255, 255, 1"$color = str_replace(' ', '', $color); # "255, 255, 255, 1"       => "255,255,255,1"$color = explode(',', $color);         # "255,255,255,1"          => ["255", "255", "255", "1"]
$color[] = 1;                          # add extra value to be sure that all parsed colors have transparency

return array_slice($color, 0, 3 + $include_alpha); # length is 3 or 4, depends on $include_alpha value
}

Вы также можете извлечь числа из строки, основываясь на том факте, что встроенный тип PHP приведен к float а также int удаляет лишние символы из строки:

function rgb_array($color, $include_alpha = true)
{
$array = array_map('floatval', explode(',', $color));
$array[] = 1;

return array_slice($array, 0, 3 + $include_alpha);
}
0
По вопросам рекламы [email protected]