如何将 RGB(A) 值保存在数组中?

How to save RGB(A) values in an array?

我正在尝试编写一个函数,它将采用 RGB(A) 颜色并将其值保存在一个数组中,并提供一个选项来排除 alpha 值。我无法弄清楚如何编写与输入匹配的正则表达式,但我认为我正在寻找这样的东西:

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 );

但感觉很老套,我找不到一个好方法来选择性地 include/exclude alpha。

感谢您的帮助,如果有与 preg_match 完全不同的方法会更好,我洗耳恭听。

改进了一点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 类型转换为 floatint 会从字符串中删除多余的字符:

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

    return array_slice($array, 0, 3 + $include_alpha);
}

如果你想要正则表达式解决方案,这里是:

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

它在开始时匹配 'rgb',然后是一个可选的 'a' 和一个左边的 parenthes,然后它创建 3 个相似的组,匹配一个可选的白色 Space,然后是一个或多个 digits。第四个组是可选的,将匹配一个或多个 digits,可选地后跟一个 dot,以及一个或多个 digits

颜色将位于索引 1、2、3 和 4(如果可用)。

您可以使用 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
)

我的答案不仅会提取您想要的子字符串值,还会执行相当高级别的验证(不是 100% 完美验证)。我修改了 的模式以更准确地解决这个问题。我相信您会发现这个答案是准确、优雅和直接的。

如果你想剥离/简化模式,这样做:(Regex101 Demo)
~^rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([.\d]+))?\)$~

代码:(Demo w/ $include_alpha = true) (Demo 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',
)

p.s。如果你想使用 preg_split() 你可以不那么具体地描述你的模式。这是给你的单线。 (Demo)

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