PHP 中的 RGB 到 HSV

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1773698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 03:47:38  来源:igfitidea点击:

RGB to HSV in PHP

phpimagecolorsrgbhsv

提问by Alix Axel

In PHP, what is the most straightforward way to convert a RGB triplet to HSV values?

在 PHP 中,将 RGB 三元组转换为 HSV 值的最直接方法是什么?

采纳答案by Jacob

<?php
function RGB_TO_HSV ($R, $G, $B)  // RGB Values:Number 0-255
{                                 // HSV Results:Number 0-1
   $HSL = array();

   $var_R = ($R / 255);
   $var_G = ($G / 255);
   $var_B = ($B / 255);

   $var_Min = min($var_R, $var_G, $var_B);
   $var_Max = max($var_R, $var_G, $var_B);
   $del_Max = $var_Max - $var_Min;

   $V = $var_Max;

   if ($del_Max == 0)
   {
      $H = 0;
      $S = 0;
   }
   else
   {
      $S = $del_Max / $var_Max;

      $del_R = ( ( ( $var_Max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
      $del_G = ( ( ( $var_Max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
      $del_B = ( ( ( $var_Max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;

      if      ($var_R == $var_Max) $H = $del_B - $del_G;
      else if ($var_G == $var_Max) $H = ( 1 / 3 ) + $del_R - $del_B;
      else if ($var_B == $var_Max) $H = ( 2 / 3 ) + $del_G - $del_R;

      if ($H<0) $H++;
      if ($H>1) $H--;
   }

   $HSL['H'] = $H;
   $HSL['S'] = $S;
   $HSL['V'] = $V;

   return $HSL;
}

回答by Unsigned

Here is a simple, straightforward method that returns HSV values as degrees and percentages, which is what Photoshop's color picker uses.

这是一个简单、直接的方法,它以度数和百分比的形式返回 HSV 值,这是 Photoshop 的颜色选择器使用的。

Note that the return values are not rounded, you can do that yourself if required. Keep in mind that H(360) == H(0), so Hvalues of 359.5and greater should round to 0

请注意,返回值未四舍五入,您可以根据需要自行完成。请记住H(360) == H(0),因此和更大的H359.5应四舍五入为0

Heavily documented for learning purposes.

大量记录用于学习目的。

/**
 * Licensed under the terms of the BSD License.
 * (Basically, this means you can do whatever you like with it,
 *   but if you just copy and paste my code into your app, you
 *   should give me a shout-out/credit :)
 */

<?php

function RGBtoHSV($R, $G, $B)    // RGB values:    0-255, 0-255, 0-255
{                                // HSV values:    0-360, 0-100, 0-100
    // Convert the RGB byte-values to percentages
    $R = ($R / 255);
    $G = ($G / 255);
    $B = ($B / 255);

    // Calculate a few basic values, the maximum value of R,G,B, the
    //   minimum value, and the difference of the two (chroma).
    $maxRGB = max($R, $G, $B);
    $minRGB = min($R, $G, $B);
    $chroma = $maxRGB - $minRGB;

    // Value (also called Brightness) is the easiest component to calculate,
    //   and is simply the highest value among the R,G,B components.
    // We multiply by 100 to turn the decimal into a readable percent value.
    $computedV = 100 * $maxRGB;

    // Special case if hueless (equal parts RGB make black, white, or grays)
    // Note that Hue is technically undefined when chroma is zero, as
    //   attempting to calculate it would cause division by zero (see
    //   below), so most applications simply substitute a Hue of zero.
    // Saturation will always be zero in this case, see below for details.
    if ($chroma == 0)
        return array(0, 0, $computedV);

    // Saturation is also simple to compute, and is simply the chroma
    //   over the Value (or Brightness)
    // Again, multiplied by 100 to get a percentage.
    $computedS = 100 * ($chroma / $maxRGB);

    // Calculate Hue component
    // Hue is calculated on the "chromacity plane", which is represented
    //   as a 2D hexagon, divided into six 60-degree sectors. We calculate
    //   the bisecting angle as a value 0 <= x < 6, that represents which
    //   portion of which sector the line falls on.
    if ($R == $minRGB)
        $h = 3 - (($G - $B) / $chroma);
    elseif ($B == $minRGB)
        $h = 1 - (($R - $G) / $chroma);
    else // $G == $minRGB
        $h = 5 - (($B - $R) / $chroma);

    // After we have the sector position, we multiply it by the size of
    //   each sector's arc (60 degrees) to obtain the angle in degrees.
    $computedH = 60 * $h;

    return array($computedH, $computedS, $computedV);
}

?>

回答by ashleedawg

Thoroughly tested and compressed, this is the function I'm going to stick with for converting RGBto HSV:

经过彻底测试和压缩,这是我将坚持使用的将RGB转换为HSV的函数:

function RGBtoHSV($r,$g,$b) {
  $r=($r/255); $g=($g/255); $b=($b/255);
  $maxRGB=max($r,$g,$b); $minRGB=min($r,$g,$b); $chroma=$maxRGB-$minRGB;
  if($chroma==0) return array('h'=>0,'s'=>0,'v'=>$maxRGB);
  if($r==$minRGB)$h=3-(($g-$b)/$chroma);
  elseif($b==$minRGB)$h=1-(($r-$g)/$chroma); else $h=5-(($b-$r)/$chroma);
  return array('h'=>60*$h,'s'=>$chroma/$maxRGB,'v'=>$maxRGB);
} 


Example:

例子:

Example using color "DarkSalmon":

使用颜色“ DarkSalmon”的示例:

echo '<pre><code>'. print_r( RGBtoHSV(233,150,122), true ) .'</code></pre>';

...returns:

...返回:

Array
(
    [h] => 15.135135135135
    [s] => 0.47639484978541
    [v] => 0.91372549019608
)

回答by T?ng V?n ??c

I did it like this

我是这样做的

function convertRgbToHsv($rgb)
{

    $r = (int)substr($rgb, 0, 3) / 255;
    $g = (int)substr($rgb, 3, 3) / 255;
    $b = (int)substr($rgb, 6, 3) / 255;

    $max = max($r, $g, $b);
    $min = min($r, $g, $b);
    $delta = $max - $min;

    if (!$delta) {
        $h = 0;
    } else if ($r === $max) {
        $h = 60 * ((($g - $b) / $delta) % 6);
    } else if ($g === $max) {
        $h = 60 * ((($b - $r) / $delta) + 2);
    } else {
        $h = 60 * ((($r - $g) / $delta) + 4);
    }

    $s = !!$max ? $delta / $max : 0;

    $v = $max;

    $hsv = array("h" => $h, "s" => $s, "v" => $v);

    return $hsv;
}

Link to reference material here

链接到此处的参考资料

回答by rodrigo-silveira

Here's my spin on it, along with a unit test. Since the Sand Vvalues are percentages, this code returns them as integers (0, 100) as opposed to (0, 1) - Example, 75instead of 0.75.

这是我对它的看法,以及一个单元测试。由于SV值是百分比,因此此代码将它们返回为整数 (0, 100),而不是 (0, 1) - 示例,75而不是0.75

final class MathService
{    
    /**
     * Converts an RGB point into HSV
     *
     * @param int $r
     * @param int $g
     * @param int $b
     * @return array
     */
    public function rgbToHsv(int $r, int $g, int $b): array
    {
        $rPrime = $r / 255;
        $gPrime = $g / 255;
        $bPrime = $b / 255;

        $max = max([$rPrime, $gPrime, $bPrime]);
        $min = min([$rPrime, $gPrime, $bPrime]);

        $delta = $max - $min;

        // Calculate H
        if ($delta == 0) {
            $h = 0;
        } else {
            if ($max === $rPrime) {
                $h = 60 * ((($gPrime - $bPrime) / $delta) % 6);
            }
            if ($max === $gPrime) {
                $h = 60 * ((($bPrime - $rPrime) / $delta) + 2);
            }
            if ($max === $bPrime) {
                $h = 60 * ((($rPrime - $gPrime) / $delta) + 4);
            }
        }

        // Calculate S
        if ($max == 0) {
            $s = 0;
        } else {
            $s = $delta / $max;
        }

        // Calculate V
        $v = $max;

        return [$h, (int)($s * 100), (int)($v * 100)];
    }
}

PHPUnit test case with PHP 7.2

PHPUnit 测试用例与 PHP 7.2

/**
 * @test
 */
public function rgbToHsv_ComputesCorrectValues(): void
{
    $service = new MathService();
    $samples = [
        // [R, G, B, H, S, V]
        [0, 0, 0, 0, 0, 0],
        [255, 255, 255, 0, 0, 100],
        [255, 0, 0, 0, 100, 100],
        [0, 255, 0, 120, 100, 100],
        [0, 0, 255, 240, 100, 100],
        [255, 255, 0, 60, 100, 100],
        [0, 255, 255, 180, 100, 100],
        [255, 0, 255, 300, 100, 100],
        [192, 192, 192, 0, 0, 75],
        [128, 128, 128, 0, 0, 50],
        [128, 0, 0, 0, 100, 50],
        [128, 128, 0, 60, 100, 50],
        [0, 128, 0, 120, 100, 50],
        [128, 0, 128, 300, 100, 50],
        [0, 128, 128, 180, 100, 50],
        [0, 0, 128, 240, 100, 50],
    ];

    foreach ($samples as $sample) {
        list($r, $g, $b) = array_slice($sample, 0, 3);
        $expected = array_slice($sample, 3);
        $hsv = $service->rgbToHsv($r, $g, $b);
        list($h, $s, $v) = $hsv;

        self::assertEquals($expected, $hsv, "Error converting ({$r}, ${g}, ${b}). Got ({$h}, {$s}, {$v})");
    }
}