Skip to content

Commit

Permalink
sqmk#130 Fix color higher than 255
Browse files Browse the repository at this point in the history
- fixed coding standards in color conversion tool.
- added unit test for the 0..255 range fix.
  • Loading branch information
Alex Buis committed May 1, 2018
1 parent 78c7e94 commit b8b4209
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 19 deletions.
29 changes: 19 additions & 10 deletions library/Phue/Helper/ColorConversion.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static function convertRGBToXY($red, $green, $blue)
$normalizedToOne['red'] = $red / 255;
$normalizedToOne['green'] = $green / 255;
$normalizedToOne['blue'] = $blue / 255;

// Make colors more vivid
foreach ($normalizedToOne as $key => $normalized) {
if ($normalized > 0.04045) {
Expand All @@ -38,12 +38,12 @@ public static function convertRGBToXY($red, $green, $blue)
$color[$key] = $normalized / 12.92;
}
}

// Convert to XYZ using the Wide RGB D65 formula
$xyz['x'] = $color['red'] * 0.664511 + $color['green'] * 0.154324 + $color['blue'] * 0.162028;
$xyz['y'] = $color['red'] * 0.283881 + $color['green'] * 0.668433 + $color['blue'] * 0.047685;
$xyz['z'] = $color['red'] * 0.000000 + $color['green'] * 0.072310 + $color['blue'] * 0.986039;

// Calculate the x/y values
if (array_sum($xyz) == 0) {
$x = 0;
Expand All @@ -52,14 +52,14 @@ public static function convertRGBToXY($red, $green, $blue)
$x = $xyz['x'] / array_sum($xyz);
$y = $xyz['y'] / array_sum($xyz);
}

return array(
'x' => $x,
'y' => $y,
'bri' => round($xyz['y'] * 255)
);
}

/**
* Converts XY (and brightness) values to RGB
*
Expand All @@ -76,24 +76,33 @@ public static function convertXYToRGB($x, $y, $bri = 255)
$xyz['y'] = $bri / 255;
$xyz['x'] = ($xyz['y'] / $y) * $x;
$xyz['z'] = ($xyz['y'] / $y) * $z;

// Convert to RGB using Wide RGB D65 conversion
$color['red'] = $xyz['x'] * 1.656492 - $xyz['y'] * 0.354851 - $xyz['z'] * 0.255038;
$color['green'] = -$xyz['x'] * 0.707196 + $xyz['y'] * 1.655397 + $xyz['z'] * 0.036152;
$color['blue'] = $xyz['x'] * 0.051713 - $xyz['y'] * 0.121364 + $xyz['z'] * 1.011530;


$maxValue = 0;
foreach ($color as $key => $normalized) {
// Apply reverse gamma correction
if ($normalized <= 0.0031308) {
$color[$key] = 12.92 * $normalized;
} else {
$color[$key] = (1.0 + 0.055) * pow($normalized, 1.0 / 2.4) - 0.055;
}

$color[$key] = max(0, $color[$key]);
if ($maxValue < $color[$key]) {
$maxValue = $color[$key];
}
}
foreach ($color as $key => $normalized) {
if ($maxValue > 1) {
$color[$key] /= $maxValue;
}
// Scale back from a maximum of 1 to a maximum of 255
$color[$key] = round($color[$key] * 255);
}

return $color;
}
}
}
25 changes: 16 additions & 9 deletions tests/Phue/Test/Helper/ColorConversionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,32 @@ class ColorConversionTest extends \PHPUnit_Framework_TestCase
{
/**
* Test: convert RGB to XY and brightness
*
*
* @covers \Phue\Helper\ColorConversion::convertRGBToXY
*/
public function testConvertRGBToXY()
{
// Values from: http://www.developers.meethue.com/documentation/hue-xy-values

// Alice Blue
$xy = ColorConversion::convertRGBToXY(239, 247, 255);
$this->assertEquals(0.3088, $xy['x'], '', 0.0001);
$this->assertEquals(0.3212, $xy['y'], '', 0.0001);
$this->assertEquals(233, $xy['bri']);

// Firebrick
$xy = ColorConversion::convertRGBToXY(178, 33, 33);
$this->assertEquals(0.6622, $xy['x'], '', 0.0001);
$this->assertEquals(0.3024, $xy['y'], '', 0.0001);
$this->assertEquals(35, $xy['bri']);

// Medium Sea Green
$xy = ColorConversion::convertRGBToXY(61, 178, 112);
$this->assertEquals(0.1979, $xy['x'], '', 0.0001);
$this->assertEquals(0.5005, $xy['y'], '', 0.0001);
$this->assertEquals(81, $xy['bri']);
}

/**
* Test: convert XY and brightness to RGB
*
Expand All @@ -50,23 +50,30 @@ public function testConvertRGBToXY()
public function testConvertXYToRGB()
{
// Conversion back from the test above

// Alice Blue
$rgb = ColorConversion::convertXYToRGB(0.3088, 0.3212, 233);
$this->assertEquals($rgb['red'], 239);
$this->assertEquals($rgb['green'], 247);
$this->assertEquals($rgb['blue'], 255);

// Firebrick
$rgb = ColorConversion::convertXYToRGB(0.6622, 0.3024, 35);
$this->assertEquals($rgb['red'], 178);
$this->assertEquals($rgb['green'], 33);
$this->assertEquals($rgb['blue'], 33);

// Medium Sea Green
$rgb = ColorConversion::convertXYToRGB(0.1979, 0.5005, 81);
$this->assertEquals($rgb['red'], 61);
$this->assertEquals($rgb['green'], 178);
$this->assertEquals($rgb['blue'], 112);

// Test to make sure single RGB values falls within 0..255 range.
// old situation this was r -18, g 186, b -613.
$rgb = ColorConversion::convertXYToRGB(0.1979, 1.5005, 81);
$this->assertEquals($rgb['red'], 0);
$this->assertEquals($rgb['green'], 186);
$this->assertEquals($rgb['blue'], 0);
}
}
}

0 comments on commit b8b4209

Please sign in to comment.