Here is my rotation on it, along with the unit test. Since the values ββof S and V are percentages, this code returns them as integers (0, 100), and not (0, 1) - an example, 75 instead of 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})"); } }