RGBWW/CCT Lights: Fix gamma_correct when using constant_brightness (#1043)

This commit is contained in:
Niklas Wagner 2020-06-12 20:17:46 +02:00 committed by GitHub
parent 42007d03d4
commit 8aedac81a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 36 deletions

View file

@ -17,12 +17,13 @@ namespace light {
* Not all values have to be populated though, for example a simple monochromatic light only needs * Not all values have to be populated though, for example a simple monochromatic light only needs
* to access the state and brightness attributes. * to access the state and brightness attributes.
* *
* PLease note all float values are automatically clamped. * Please note all float values are automatically clamped.
* *
* state - Whether the light should be on/off. Represented as a float for transitions. * state - Whether the light should be on/off. Represented as a float for transitions.
* brightness - The brightness of the light. * brightness - The brightness of the light.
* red, green, blue - RGB values. * red, green, blue - RGB values.
* white - The white value for RGBW lights. * white - The white value for RGBW lights.
* color_temperature - Temperature of the white value, range from 0.0 (cold) to 1.0 (warm)
*/ */
class LightColorValues { class LightColorValues {
public: public:
@ -173,30 +174,33 @@ class LightColorValues {
void as_binary(bool *binary) const { *binary = this->state_ == 1.0f; } void as_binary(bool *binary) const { *binary = this->state_ == 1.0f; }
/// Convert these light color values to a brightness-only representation and write them to brightness. /// Convert these light color values to a brightness-only representation and write them to brightness.
void as_brightness(float *brightness) const { *brightness = this->state_ * this->brightness_; } void as_brightness(float *brightness, float gamma = 0) const {
*brightness = gamma_correct(this->state_ * this->brightness_, gamma);
}
/// Convert these light color values to an RGB representation and write them to red, green, blue. /// Convert these light color values to an RGB representation and write them to red, green, blue.
void as_rgb(float *red, float *green, float *blue) const { void as_rgb(float *red, float *green, float *blue, float gamma = 0) const {
*red = this->state_ * this->brightness_ * this->red_; *red = gamma_correct(this->state_ * this->brightness_ * this->red_, gamma);
*green = this->state_ * this->brightness_ * this->green_; *green = gamma_correct(this->state_ * this->brightness_ * this->green_, gamma);
*blue = this->state_ * this->brightness_ * this->blue_; *blue = gamma_correct(this->state_ * this->brightness_ * this->blue_, gamma);
} }
/// Convert these light color values to an RGBW representation and write them to red, green, blue, white. /// Convert these light color values to an RGBW representation and write them to red, green, blue, white.
void as_rgbw(float *red, float *green, float *blue, float *white) const { void as_rgbw(float *red, float *green, float *blue, float *white, float gamma = 0) const {
this->as_rgb(red, green, blue); this->as_rgb(red, green, blue, gamma);
*white = this->state_ * this->brightness_ * this->white_; *white = gamma_correct(this->state_ * this->brightness_ * this->white_, gamma);
} }
/// Convert these light color values to an RGBWW representation with the given parameters. /// Convert these light color values to an RGBWW representation with the given parameters.
void as_rgbww(float color_temperature_cw, float color_temperature_ww, float *red, float *green, float *blue, void as_rgbww(float color_temperature_cw, float color_temperature_ww, float *red, float *green, float *blue,
float *cold_white, float *warm_white, bool constant_brightness = false) const { float *cold_white, float *warm_white, float gamma = 0, bool constant_brightness = false) const {
this->as_rgb(red, green, blue); this->as_rgb(red, green, blue, gamma);
const float color_temp = clamp(this->color_temperature_, color_temperature_cw, color_temperature_ww); const float color_temp = clamp(this->color_temperature_, color_temperature_cw, color_temperature_ww);
const float ww_fraction = (color_temp - color_temperature_cw) / (color_temperature_ww - color_temperature_cw); const float ww_fraction = (color_temp - color_temperature_cw) / (color_temperature_ww - color_temperature_cw);
const float cw_fraction = 1.0f - ww_fraction; const float cw_fraction = 1.0f - ww_fraction;
*cold_white = this->state_ * this->brightness_ * this->white_ * cw_fraction; const float white_level = gamma_correct(this->state_ * this->brightness_ * this->white_, gamma);
*warm_white = this->state_ * this->brightness_ * this->white_ * ww_fraction; *cold_white = white_level * cw_fraction;
*warm_white = white_level * ww_fraction;
if (!constant_brightness) { if (!constant_brightness) {
const float max_cw_ww = std::max(ww_fraction, cw_fraction); const float max_cw_ww = std::max(ww_fraction, cw_fraction);
*cold_white /= max_cw_ww; *cold_white /= max_cw_ww;
@ -206,12 +210,13 @@ class LightColorValues {
/// Convert these light color values to an CWWW representation with the given parameters. /// Convert these light color values to an CWWW representation with the given parameters.
void as_cwww(float color_temperature_cw, float color_temperature_ww, float *cold_white, float *warm_white, void as_cwww(float color_temperature_cw, float color_temperature_ww, float *cold_white, float *warm_white,
bool constant_brightness = false) const { float gamma = 0, bool constant_brightness = false) const {
const float color_temp = clamp(this->color_temperature_, color_temperature_cw, color_temperature_ww); const float color_temp = clamp(this->color_temperature_, color_temperature_cw, color_temperature_ww);
const float ww_fraction = (color_temp - color_temperature_cw) / (color_temperature_ww - color_temperature_cw); const float ww_fraction = (color_temp - color_temperature_cw) / (color_temperature_ww - color_temperature_cw);
const float cw_fraction = 1.0f - ww_fraction; const float cw_fraction = 1.0f - ww_fraction;
*cold_white = this->state_ * this->brightness_ * cw_fraction; const float white_level = gamma_correct(this->state_ * this->brightness_ * this->white_, gamma);
*warm_white = this->state_ * this->brightness_ * ww_fraction; *cold_white = white_level * cw_fraction;
*warm_white = white_level * ww_fraction;
if (!constant_brightness) { if (!constant_brightness) {
const float max_cw_ww = std::max(ww_fraction, cw_fraction); const float max_cw_ww = std::max(ww_fraction, cw_fraction);
*cold_white /= max_cw_ww; *cold_white /= max_cw_ww;

View file

@ -702,39 +702,24 @@ LightOutput *LightState::get_output() const { return this->output_; }
void LightState::set_gamma_correct(float gamma_correct) { this->gamma_correct_ = gamma_correct; } void LightState::set_gamma_correct(float gamma_correct) { this->gamma_correct_ = gamma_correct; }
void LightState::current_values_as_binary(bool *binary) { this->current_values.as_binary(binary); } void LightState::current_values_as_binary(bool *binary) { this->current_values.as_binary(binary); }
void LightState::current_values_as_brightness(float *brightness) { void LightState::current_values_as_brightness(float *brightness) {
this->current_values.as_brightness(brightness); this->current_values.as_brightness(brightness, this->gamma_correct_);
*brightness = gamma_correct(*brightness, this->gamma_correct_);
} }
void LightState::current_values_as_rgb(float *red, float *green, float *blue) { void LightState::current_values_as_rgb(float *red, float *green, float *blue) {
this->current_values.as_rgb(red, green, blue); this->current_values.as_rgb(red, green, blue, this->gamma_correct_);
*red = gamma_correct(*red, this->gamma_correct_);
*green = gamma_correct(*green, this->gamma_correct_);
*blue = gamma_correct(*blue, this->gamma_correct_);
} }
void LightState::current_values_as_rgbw(float *red, float *green, float *blue, float *white) { void LightState::current_values_as_rgbw(float *red, float *green, float *blue, float *white) {
this->current_values.as_rgbw(red, green, blue, white); this->current_values.as_rgbw(red, green, blue, white, this->gamma_correct_);
*red = gamma_correct(*red, this->gamma_correct_);
*green = gamma_correct(*green, this->gamma_correct_);
*blue = gamma_correct(*blue, this->gamma_correct_);
*white = gamma_correct(*white, this->gamma_correct_);
} }
void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white,
bool constant_brightness) { bool constant_brightness) {
auto traits = this->get_traits(); auto traits = this->get_traits();
this->current_values.as_rgbww(traits.get_min_mireds(), traits.get_max_mireds(), red, green, blue, cold_white, this->current_values.as_rgbww(traits.get_min_mireds(), traits.get_max_mireds(), red, green, blue, cold_white,
warm_white, constant_brightness); warm_white, this->gamma_correct_, constant_brightness);
*red = gamma_correct(*red, this->gamma_correct_);
*green = gamma_correct(*green, this->gamma_correct_);
*blue = gamma_correct(*blue, this->gamma_correct_);
*cold_white = gamma_correct(*cold_white, this->gamma_correct_);
*warm_white = gamma_correct(*warm_white, this->gamma_correct_);
} }
void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) { void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) {
auto traits = this->get_traits(); auto traits = this->get_traits();
this->current_values.as_cwww(traits.get_min_mireds(), traits.get_max_mireds(), cold_white, warm_white, this->current_values.as_cwww(traits.get_min_mireds(), traits.get_max_mireds(), cold_white, warm_white,
constant_brightness); this->gamma_correct_, constant_brightness);
*cold_white = gamma_correct(*cold_white, this->gamma_correct_);
*warm_white = gamma_correct(*warm_white, this->gamma_correct_);
} }
void LightState::add_new_remote_values_callback(std::function<void()> &&send_callback) { void LightState::add_new_remote_values_callback(std::function<void()> &&send_callback) {
this->remote_values_callback_.add(std::move(send_callback)); this->remote_values_callback_.add(std::move(send_callback));