RGB do HSV w PHP

W PHP, jaki jest najprostszy sposób na konwersję trypletu RGB na wartości HSV?

Author: Alix Axel, 2009-11-21

3 answers

<?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;
}
 15
Author: Jacob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-21 21:39:43

Oto prosta metoda, która zwraca wartości HSV jako stopnie i procenty, czyli to, czego używa próbnik kolorów Photoshopa.

Zwróć uwagę, że wartości zwrotne nie są zaokrąglane, możesz to zrobić samodzielnie, jeśli jest to wymagane. Należy pamiętać, że H(360) == H(0), Więc H wartości 359.5 i większe powinny zaokrąglać się do 0

Mocno udokumentowane w celach edukacyjnych.

/**
 * 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);
}

?>
 30
Author: Unsigned,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-03 23:36:50

Oto mój spin na nim, wraz z testem jednostkowym. Ponieważ wartości S i V są procentami, ten kod zwraca je jako liczby całkowite (0, 100) W przeciwieństwie do (0, 1) - Przykład, 75 zamiast 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

/**
 * @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})");
    }
}
 0
Author: rodrigo-silveira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-27 12:24:47