在 PowerShell 中以编程方式旋转基于十六进制的颜色

问题描述 投票:0回答:1

我正在研究一种能够以编程方式将深色主题应用于 HTML/CSS 文件的方法。该过程的一部分是反转所有检测到的颜色,然后将色调旋转 180 度。例如:


  1. 解析颜色
    • #00DD00
  2. 反转
    • #00DD00→#FF22FF
  3. 色相旋转 180∘
    • #FF22FF → #22FF22

  1. 解析颜色
    • #CC1100
  2. 反转
    • #CC1100→#33EEFF
  3. 色相旋转 180∘
    • #33EEFF → #FF4433

第 1 步和第 2 步很简单,但第 3 步让我很困惑,因为我不知道如何去做。

这是我的第 2 步:

$parsedColor = '#123456'  # this would normally be automatically parsed from a HTML file


# New StringBuilder object that starts with #
$invertedColor = [Text.StringBuilder]'#'


# Split into groups of 2 characters, ignoring # and empty:
$parsedColor -split '([^#][^#])' -ne '#' -ne '' | &{process{

  # Append value to StringBuilder:
  $invertedColor.Append(

    # Format as hexidecimal string after flipping the bit
    '{0:X}' -f ([byte]"0x$_" -bxor 0xFF)

  )

# Suppress .Append noise
}} | Out-Null


# Output StringBuilder as String
$invertedColor -as [string]
powershell colors hex
1个回答
0
投票

基于

https://drafts.fxtf.org/filter-effects/#feColorMatrixElement
上的 css hue-rotate 算法参考以及本网站上的一些其他参考...

...在 PowerShell 中应用

hue-rotate
的函数将是这样的:

function Invoke-HueRotate
{
    param( [uint] $Color, [decimal] $Degrees )

    # split color into r, g and b channels
    $r = $Color -shr 16 -band 0xFF;
    $g = $Color -shr  8 -band 0xFF;
    $b = $Color -shr  0 -band 0xFF;

    # convert degrees to radians and evaluate cos / sin
    $cos = [Math]::Cos($Degrees * [Math]::PI / 180);
    $sin = [Math]::Sin($Degrees * [Math]::PI / 180);

    # long-hand matrix definition
    # see https://drafts.fxtf.org/filter-effects/#feColorMatrixElement
    # where it says 'For type="hueRotate"'
    $a00 = 0.213 + ( 0.787 * $cos) + (-0.213 * $sin);
    $a01 = 0.715 + (-0.715 * $cos) + (-0.715 * $sin);
    $a02 = 0.072 + (-0.072 * $cos) + ( 0.928 * $sin);
    $a10 = 0.213 + (-0.213 * $cos) + ( 0.143 * $sin);
    $a11 = 0.715 + ( 0.285 * $cos) + ( 0.140 * $sin);
    $a12 = 0.072 + (-0.072 * $cos) + (-0.283 * $sin);
    $a20 = 0.213 + (-0.213 * $cos) + (-0.787 * $sin);
    $a21 = 0.715 + (-0.715 * $cos) + ( 0.715 * $sin);
    $a22 = 0.072 + ( 0.928 * $cos) + ( 0.072 * $sin);

    # long-hand matrix multiplication
    $r2 = ($a00 * $r) + ($a01 * $g) + ($a02 * $b);
    $g2 = ($a10 * $r) + ($a11 * $g) + ($a12 * $b);
    $b2 = ($a20 * $r) + ($a21 * $g) + ($a22 * $b);

    # re-combine r, g and b channels
    $result = [uint](
        ([Math]::Clamp([int]$r2, 0, 255) -shl 16) `
        -bor
        ([Math]::Clamp([int]$g2, 0, 255) -shl 8) `
        -bor
        ([Math]::Clamp([int]$b2, 0, 255) -shl 0) `
    );

    return $result;

}

(我已经避免使用任何矩阵库以保持其独立性,但是如果您不介意依赖于可以使数学更清晰的东西,则可以简化它。)

如果您还添加以下实用方法:

function Invoke-InvertColor
{
    param( [uint] $Color, [decimal] $Degrees )
    return $Color -bxor 0xFFFFFF;
}

function ConvertFrom-HtmlColor
{
    param( [string] $Value )
    return [System.Convert]::ToUInt32($Value.Substring(1), 16);
}

function ConvertTo-HtmlColor
{
    param( [uint] $Value )
    return "#" + $Value.ToString("X2").PadLeft(6, "0");
}

您可以按如下方式使用它:

$color = "#CC1100"

$original = ConvertFrom-HtmlColor -Value "#CC1100";
ConvertTo-HtmlColor $original;
#CC1100

$inverted = Invoke-InvertColor -Color $original;
ConvertTo-HtmlColor $inverted;
#33EEFF

$rotated = Invoke-HueRotate -Color $inverted -Degrees 180;
ConvertTo-HtmlColor $rotated;
#FFA190

请注意,这会给您的示例带来不同的结果

         Invert           Hue-rotate 180∘
#CC1100    ->     #33EEFF        ->       #FF4433

但结果似乎与此答案中第一个链接中的公式相符,并获得与其他链接中的实现相同的结果,因此您可能需要详细说明您使用的算法/实现

hue-rotate 
如果您追求不同的结果...

© www.soinside.com 2019 - 2024. All rights reserved.