Skip to content

Commit

Permalink
Merge pull request #107 from mKeRix/master
Browse files Browse the repository at this point in the history
Added RGB setter/getter wrappers
  • Loading branch information
sqmk committed May 29, 2016
2 parents 10bce82 + 2126222 commit d81c620
Show file tree
Hide file tree
Showing 9 changed files with 425 additions and 2 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ echo $light->getId(), "\n",
$light->getSaturation(), "\n",
$light->getXY()['x'], "\n",
$light->getXY()['y'], "\n",
$light->getRGB()['red'], "\n",
$light->getRGB()['green'], "\n",
$light->getRGB()['blue'], "\n",
$light->getEffect(), "\n",
$light->getColorTemp(), "\n",
$light->getColorMode(), "\n";
Expand All @@ -203,6 +206,9 @@ $light->setSaturation(255);
// Changes color mode to 'xy'
$light->setXY(0.25, 0.5);

// Set rgb (0 to 255 each), is converted to XY and brightness
$light->setRGB(30, 100, 50);

// Set color temp (153 min, 500 max), changes color mode to 'ct'
$light->setColorTemp(300);

Expand Down Expand Up @@ -317,6 +323,9 @@ echo $group->getId(), "\n",
$group->getSaturation(), "\n",
$group->getXY()['x'], "\n",
$group->getXY()['y'], "\n",
$group->getRGB()['red'], "\n",
$group->getRGB()['green'], "\n",
$group->getRGB()['blue'], "\n",
$group->getColorTemp(), "\n",
$group->getColorMode(), "\n",
$group->getEffect(), "\n";
Expand Down Expand Up @@ -347,6 +356,9 @@ $group->setSaturation(255);
// Changes color mode to 'xy'
$group->setXY(0.25, 0.5);

// Set rgb (0 to 255 each), is converted to XY and brightness
$group->setRGB(30, 100, 50);

// Set color temp (153 min, 500 max), changes color mode to 'ct'
$group->setColorTemp(300);

Expand Down
46 changes: 46 additions & 0 deletions library/Phue/Command/SetLightState.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace Phue\Command;

use Phue\Client;
use Phue\Helper\ColorConversion;
use Phue\Transport\TransportInterface;

/**
Expand Down Expand Up @@ -57,6 +58,16 @@ class SetLightState implements CommandInterface, ActionableInterface
*/
const XY_MAX = 1.0;

/**
* RGB Min
*/
const RGB_MIN = 0;

/**
* RGB Max
*/
const RGB_MAX = 255;

/**
* Color temperature min
*/
Expand Down Expand Up @@ -268,6 +279,41 @@ public function xy($x, $y)
return $this;
}

/**
* Sets xy and brightness calculated from RGB
*
* @param int $red
* Red value
* @param int $green
* Green value
* @param int $blue
* Blue value
*
* @throws \InvalidArgumentException
*
* @return self This object
*/
public function rgb($red, $green, $blue)
{
// Don't continue if rgb values are invalid
foreach (array(
$red,
$green,
$blue
) as $value) {
if (! (self::RGB_MIN <= $value && $value <= self::RGB_MAX)) {
throw new \InvalidArgumentException(
"RGB values must be between " . self::RGB_MIN . " and " .
self::RGB_MAX
);
}
}

$xy = ColorConversion::convertRGBToXY($red, $green, $blue);

return $this->xy($xy['x'], $xy['y'])->brightness($xy['bri']);
}

/**
* Set color temperature
*
Expand Down
103 changes: 103 additions & 0 deletions library/Phue/Helper/ColorConversion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
/**
* Phue: Philips Hue PHP Client
*
* @author Michael Squires <[email protected]>
* @copyright Copyright (c) 2012 Michael K. Squires
* @license http://github.com/sqmk/Phue/wiki/License
*/
namespace Phue\Helper;


class ColorConversion
{
/**
* Converts RGB values to XY values
* Based on: http://stackoverflow.com/a/22649803
*
* @param int $red
* Red value
* @param int $green
* Green value
* @param int $blue
* Blue value
*
* @return array x, y, bri key/value
*/
public static function convertRGBToXY($red, $green, $blue)
{
// Normalize the values to 1
$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) {
$color[$key] = pow(($normalized + 0.055) / (1.0 + 0.055), 2.4);
} else {
$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;
$y = 0;
} else {
$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
*
* @param float $x
* X value
* @param float $y
* Y value
* @param int $bri
* Brightness value
*
* @return array red, green, blue key/value
*/
public static function convertXYToRGB($x, $y, $bri = 255)
{
// Calculate XYZ
$z = 1.0 - $x - $y;
$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;

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;
}

// Scale back from a maximum of 1 to a maximum of 255
$color[$key] = round($color[$key] * 255);
}

return $color;
}
}
45 changes: 45 additions & 0 deletions library/Phue/Light.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace Phue;

use Phue\Command\SetLightState;
use Phue\Helper\ColorConversion;
use Phue\LightModel\AbstractLightModel;
use Phue\LightModel\LightModelFactory;

Expand Down Expand Up @@ -359,6 +360,50 @@ public function setXY($x, $y)
return $this;
}

/**
* Get calculated RGB
*
* @return array red, green, blue key/value
*/
public function getRGB()
{
$xy = $this->getXY();
$bri = $this->getBrightness();
$rgb = ColorConversion::convertXYToRGB($xy['x'], $xy['y'], $bri);

return $rgb;
}

/**
* Set XY and brightness calculated from RGB
*
* @param int $red
* Red value
* @param int $green
* Green value
* @param int $blue
* Blue value
*
* @return self This object
*/
public function setRGB($red, $green, $blue)
{
$x = new SetLightState($this);
$y = $x->rgb((int) $red, (int) $green, (int) $blue);
$this->client->sendCommand($y);

// Change internal xy, brightness and colormode state
$xy = ColorConversion::convertRGBToXY($red, $green, $blue);
$this->attributes->state->xy = array(
$xy['x'],
$xy['y']
);
$this->attributes->state->bri = $xy['bri'];
$this->attributes->state->colormode = 'xy';

return $this;
}

/**
* Get Color temperature
*
Expand Down
2 changes: 1 addition & 1 deletion library/Phue/Transport/Adapter/Curl.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,6 @@ public function getContentType()
public function close()
{
curl_close($this->curl);
unset($this->curl);
$this->curl = null;
}
}
2 changes: 1 addition & 1 deletion library/Phue/Transport/Adapter/Streaming.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,6 @@ public function close()
fclose($this->fileStream);
}

unset($this->streamContext);
$this->streamContext = null;
}
}
Loading

0 comments on commit d81c620

Please sign in to comment.