sqmk / Phue

Philips Hue client for PHP
Other
203 stars 45 forks source link

RGB value returns higher then 255 #114

Open Robertdegraaf opened 8 years ago

Robertdegraaf commented 8 years ago

When i use $light->getRGB(); I get a value of 291, 191, 114 back for my Hue Bloom. The other lights are 231, 150, 90 this looks right with the color. All the lights have the same color in my Hue app but only the Bloom has a higher Brightness The red value is higher than 255. How can I get the right RGB values of the light?

sqmk commented 8 years ago

You can get an appropriate RGB value by submitting a pull request with a code change to correct the current algo :P . Seems like the algorithm mKeRix contributed isn't up to snuff with all Hue fixtures.

I'll see if there is anything readily available to drop in as a replacement for determining RGB.

Robertdegraaf commented 8 years ago

Can you please give me a example of the code. My code is as following:

foreach ($client->getLights() as $lightId => $light) { if($light->isOn()) { $rgb = $light->getRGB(); } }

hope you can help me out by getting all the right colors of the Hue lights

sgc-fireball commented 7 years ago

+1

EDIT: Red (philius hue app the left bottom cornor)

print_r ( ColorConversion::convertXYToRGB(0.6915, 0.3083, 254) );
Array
(
    [red] => 431
    [green] => 74
    [blue] => -15
)
sgc-fireball commented 7 years ago

i have tried to fixed it with https://developers.meethue.com/documentation/color-conversions-rgb-xy but ... but you can not calculate exact values ... here is my current code:

/**
     * @param float $x
     * @param float $y
     * @param int $brightness
     * @return array(int,int,int)
     */
    public function xyb2rgb(float $x, float $y, int $brightness=254): array
    {
        // Calculate XYZ values Convert using the following formulas
        $z = 1.0 - $x - $y;
        $Y = $brightness;
        $X = ($Y / $y) * $x;
        $Z = ($Y / $y) * $z;

        // Convert to RGB using Wide RGB D65 conversion
        $r = $X * 1.656492 - $Y * 0.354851 - $Z * 0.255038;
        $g = -$X * 0.707196 + $Y * 1.655397 + $Z * 0.036152;
        $b = $X * 0.051713 - $Y * 0.121364 + $Z * 1.011530;

        // Apply reverse gamma correction
        $r = $r <= 0.0031308 ? 12.92 * $r : (1.0 + 0.055) * pow($r, (1.0 / 2.4)) - 0.055;
        $g = $g <= 0.0031308 ? 12.92 * $g : (1.0 + 0.055) * pow($g, (1.0 / 2.4)) - 0.055;
        $b = $b <= 0.0031308 ? 12.92 * $b : (1.0 + 0.055) * pow($b, (1.0 / 2.4)) - 0.055;

        if (($maxValue = max($r, $g, $b)) && $maxValue > 1) {
            $r /= $maxValue;
            $g /= $maxValue;
            $b /= $maxValue;
        }
        $r = (int)max(0, min(255, $r * 255));
        $g = (int)max(0, min(255, $g * 255));
        $b = (int)max(0, min(255, $b * 255));

        return [$r, $g, $b];
    }

    /**
     * @see https://developers.meethue.com/documentation/color-conversions-rgb-xy
     * @param int $red
     * @param int $green
     * @param int $blue
     * @return array(float,float,integer)
     */
    public function rgb2xyb(int $red = 0, int $green = 0, int $blue = 0): array
    {
        // Get the RGB values from your color object and convert them to be between 0 and 1.
        // So the RGB color (255, 0, 100) becomes (1.0, 0.0, 0.39)
        $red /= 255;
        $green /= 255;
        $blue /= 255;

        // Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color
        // displayed on the screen of your device. This gamma correction is also applied to the screen of your
        // computer or phone, thus we need this to create a similar color on the light as on screen.
        // This is done by the following formulas:
        $red = ($red > 0.04045) ? pow(($red + 0.055) / (1.0 + 0.055), 2.4) : ($red / 12.92);
        $green = ($green > 0.04045) ? pow(($green + 0.055) / (1.0 + 0.055), 2.4) : ($green / 12.92);
        $blue = ($blue > 0.04045) ? pow(($blue + 0.055) / (1.0 + 0.055), 2.4) : ($blue / 12.92);

        // Convert the RGB values to XYZ using the Wide RGB D65 conversion formula The formulas used
        $X = $red * 0.664511 + $green * 0.154324 + $blue * 0.162028;
        $Y = $red * 0.283881 + $green * 0.668433 + $blue * 0.047685;
        $Z = $red * 0.000088 + $green * 0.072310 + $blue * 0.986039;

        // Calculate the xy values from the XYZ values
        $x = $X + $Y + $Z;
        $x = $x === 0 ? 0 : $X / $x;
        $y = $X + $Y + $Z;
        $y = $y === 0 ? 0 : $Y / $y;

        // Use the Y value of XYZ as brightness The Y value indicates the brightness of the converted color.
        return [$x,$y,round($Y*255,0)];
    }

https://github.com/peter-murray/node-hue-api/blob/master/test/rgb-tests.js .. may ... ?

mixman68 commented 7 years ago

Hello, i have put a modification in code : https://github.com/djgreg13/Phue/commit/8e4e7638ab371be7769ed4631b9fb65e17b9825d

I have took example on code of home assistant and another python library whiches work correctly

so i wrote a test file :

require_once __DIR__ . '/vendor/autoload.php';

use \Phue\Helper\ColorConversion;

function testConvert($r,$g,$b) {
  $xy = ColorConversion::convertRGBToXY($r,$g,$b);

  $rgbConverted = ColorConversion::convertXYToRGB($xy["x"],$xy["y"],$xy["bri"]);
  echo "$r $g $b => {$rgbConverted['red']} {$rgbConverted['green']} {$rgbConverted['blue']}", PHP_EOL;
}

testConvert(255,0,0);
testConvert(200,50,0);
testConvert(200,50,0);
testConvert(243,50,6);
testConvert(200,143,68);
testConvert(233,230,211);
testConvert(33,232,11);
testConvert(2,32,113);
testConvert(98,23,234);

The conversion to XY is correct, same as other library excepted ignorance of Gamut of bulb So i try to convert to XY and back to RGB and i have these results :

255 0 0 => 254 0 0 200 50 0 => 200 50 0 200 50 0 => 200 50 0 243 50 6 => 242 50 6 200 143 68 => 200 143 68 233 230 211 => 233 230 211 33 232 11 => 33 232 11 2 32 113 => 2 34 119 98 23 234 => 97 23 232

so i'm satisfied by these

neoteknic commented 6 years ago

+1 please merge this fix.

thomaswardiii commented 2 years ago

Please fix this or fix the documentation