new brightness handling (#430)

* clean color adjustment

* now a prio duration of "0" means infinity

* implement dynamic 'just in time' initialization

* implement new brightness handling

* cahnge access level

* i18n fix

* - cleanup brightness stuff
- update webserver, now with initial ssl support

* - backlightThreshold is now 0-100 instead 0-1
- better performance for brightness - use piecewise linear instead of sqrt
This commit is contained in:
redPanther
2017-04-03 05:19:05 +02:00
committed by GitHub
parent 852f7b86bb
commit 5ea3c752b5
22 changed files with 366 additions and 139 deletions

View File

@@ -162,12 +162,13 @@ RgbTransform* Hyperion::createRgbTransform(const QJsonObject& colorConfig)
{
const double backlightThreshold = colorConfig["backlightThreshold"].toDouble(0.0);
const bool backlightColored = colorConfig["backlightColored"].toBool(false);
const double brightness = colorConfig["brightness"].toDouble(0.5);
const double brightness = colorConfig["brightness"].toInt(100);
const double brightnessComp= colorConfig["brightnessCompensation"].toInt(100);
const double gammaR = colorConfig["gammaRed"].toDouble(1.0);
const double gammaG = colorConfig["gammaGreen"].toDouble(1.0);
const double gammaB = colorConfig["gammaBlue"].toDouble(1.0);
RgbTransform* transform = new RgbTransform(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, brightness);
RgbTransform* transform = new RgbTransform(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, brightness, brightnessComp);
return transform;
}

View File

@@ -106,8 +106,10 @@ void MultiColorAdjustment::applyAdjustment(std::vector<ColorRgb>& ledColors)
uint8_t ored = color.red;
uint8_t ogreen = color.green;
uint8_t oblue = color.blue;
uint8_t B_RGB, B_CMY, B_W;
adjustment->_rgbTransform.transform(ored,ogreen,oblue);
adjustment->_rgbTransform.getBrightnessComponents(B_RGB, B_CMY, B_W);
uint32_t nrng = (uint32_t) (255-ored)*(255-ogreen);
uint32_t rng = (uint32_t) (ored) *(255-ogreen);
@@ -123,15 +125,17 @@ void MultiColorAdjustment::applyAdjustment(std::vector<ColorRgb>& ledColors)
uint8_t yellow = rg *(255-oblue)/65025;
uint8_t white = rg *(oblue) /65025;
uint8_t OR, OG, OB, RR, RG, RB, GR, GG, GB, BR, BG, BB, CR, CG, CB, MR, MG, MB, YR, YG, YB, WR, WG, WB;
adjustment->_rgbBlackAdjustment.apply(black, OR, OG, OB);
adjustment->_rgbRedAdjustment.apply(red, RR, RG, RB);
adjustment->_rgbGreenAdjustment.apply(green, GR, GG, GB);
adjustment->_rgbBlueAdjustment.apply(blue, BR, BG, BB);
adjustment->_rgbCyanAdjustment.apply(cyan, CR, CG, CB);
adjustment->_rgbMagentaAdjustment.apply(magenta, MR, MG, MB);
adjustment->_rgbYellowAdjustment.apply(yellow, YR, YG, YB);
adjustment->_rgbWhiteAdjustment.apply(white, WR, WG, WB);
uint8_t OR, OG, OB, RR, RG, RB, GR, GG, GB, BR, BG, BB;
uint8_t CR, CG, CB, MR, MG, MB, YR, YG, YB, WR, WG, WB;
adjustment->_rgbBlackAdjustment.apply (black , 255 , OR, OG, OB);
adjustment->_rgbRedAdjustment.apply (red , B_RGB, RR, RG, RB);
adjustment->_rgbGreenAdjustment.apply (green , B_RGB, GR, GG, GB);
adjustment->_rgbBlueAdjustment.apply (blue , B_RGB, BR, BG, BB);
adjustment->_rgbCyanAdjustment.apply (cyan , B_CMY, CR, CG, CB);
adjustment->_rgbMagentaAdjustment.apply(magenta, B_CMY, MR, MG, MB);
adjustment->_rgbYellowAdjustment.apply (yellow , B_CMY, YR, YG, YB);
adjustment->_rgbWhiteAdjustment.apply (white , B_W , WR, WG, WB);
color.red = OR + RR + GR + BR + CR + MR + YR + WR;
color.green = OG + RG + GG + BG + CG + MG + YG + WG;

View File

@@ -12,7 +12,7 @@ PriorityMuxer::PriorityMuxer(int ledCount)
, _lowestPriorityInfo()
{
_lowestPriorityInfo.priority = LOWEST_PRIORITY;
_lowestPriorityInfo.timeoutTime_ms = -1;
_lowestPriorityInfo.timeoutTime_ms = 0;
_lowestPriorityInfo.ledColors = std::vector<ColorRgb>(ledCount, {0, 0, 0});
_lowestPriorityInfo.componentId = hyperion::COMP_COLOR;
_lowestPriorityInfo.origin = "System";
@@ -91,7 +91,7 @@ void PriorityMuxer::setCurrentTime(const int64_t& now)
for (auto infoIt = _activeInputs.begin(); infoIt != _activeInputs.end();)
{
if (infoIt->timeoutTime_ms != -1 && infoIt->timeoutTime_ms <= now)
if (infoIt->timeoutTime_ms > 0 && infoIt->timeoutTime_ms <= now)
{
infoIt = _activeInputs.erase(infoIt);
}

View File

@@ -275,13 +275,13 @@
},
"backlightThreshold" :
{
"type" : "number",
"type" : "integer",
"title" : "edt_conf_color_backlightThreshold_title",
"required" : true,
"minimum" : 0.0,
"maximum": 1.0,
"default" : 0.0,
"step" : 0.05,
"minimum" : 0,
"maximum": 100,
"default" : 0,
"append" : "edt_append_percent",
"propertyOrder" : 11
},
"backlightColored" :
@@ -294,15 +294,27 @@
},
"brightness" :
{
"type" : "number",
"type" : "integer",
"title" : "edt_conf_color_brightness_title",
"required" : true,
"minimum" : 0.0,
"maximum": 1.0,
"default" : 1.0,
"step" : 0.05,
"minimum" : 0,
"maximum": 100,
"default" : 100,
"append" : "edt_append_percent",
"propertyOrder" : 13
},
"brightnessCompensation" :
{
"type" : "integer",
"title" : "edt_conf_color_brightnessComp_title",
"required" : true,
"minimum" : 0,
"maximum": 100,
"default" : 90,
"append" : "edt_append_percent",
"access" : "advanced",
"propertyOrder" : 14
},
"gammaRed" :
{
"type" : "number",
@@ -312,7 +324,7 @@
"maximum": 100.0,
"default" : 1.5,
"step" : 0.1,
"propertyOrder" : 14
"propertyOrder" : 15
},
"gammaGreen" :
{
@@ -323,7 +335,7 @@
"maximum": 100.0,
"default" : 1.5,
"step" : 0.1,
"propertyOrder" : 15
"propertyOrder" : 16
},
"gammaBlue" :
{
@@ -334,7 +346,7 @@
"maximum": 100.0,
"default" : 1.5,
"step" : 0.1,
"propertyOrder" : 16
"propertyOrder" : 17
}
},
"additionalProperties" : false

View File

@@ -757,10 +757,11 @@ void JsonClientConnection::handleServerInfoCommand(const QJsonObject&, const QSt
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentG());
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentB());
adjustment.insert("yellow", yellowAdjust);
adjustment["backlightThreshold"] = colorAdjustment->_rgbTransform.getBacklightThreshold();
adjustment["backlightColored"] = colorAdjustment->_rgbTransform.getBacklightColored();
adjustment["brightness"] = colorAdjustment->_rgbTransform.getBrightness();
adjustment["brightnessCompensation"] = colorAdjustment->_rgbTransform.getBrightnessCompensation();
adjustment["gammaRed"] = colorAdjustment->_rgbTransform.getGammaR();
adjustment["gammaGreen"] = colorAdjustment->_rgbTransform.getGammaG();
adjustment["gammaBlue"] = colorAdjustment->_rgbTransform.getGammaB();
@@ -956,7 +957,11 @@ void JsonClientConnection::handleAdjustmentCommand(const QJsonObject& message, c
}
if (adjustment.contains("brightness"))
{
colorAdjustment->_rgbTransform.setBrightness(adjustment["brightness"].toDouble());
colorAdjustment->_rgbTransform.setBrightness(adjustment["brightness"].toInt());
}
if (adjustment.contains("brightnessCompensation"))
{
colorAdjustment->_rgbTransform.setBrightnessCompensation(adjustment["brightnessCompensation"].toInt());
}
// commit the changes

View File

@@ -125,20 +125,26 @@
"maximum" : 5.0
},
"backlightThreshold" : {
"type" : "number",
"type" : "integer",
"required" : false,
"minimum" : 0.0,
"maximum" : 1.0
"minimum" : 0,
"maximum" : 100
},
"backlightColored" : {
"type" : "boolean",
"required" : false
},
"brightness" : {
"type" : "number",
"type" : "integer",
"required" : false,
"minimum" : 0.0,
"maximum" : 1.0
"minimum" : 0,
"maximum" : 100
},
"brightnessCompensation" : {
"type" : "integer",
"required" : false,
"minimum" : 0,
"maximum" : 100
}
},
"additionalProperties": false

View File

@@ -9,8 +9,9 @@
RgbChannelAdjustment::RgbChannelAdjustment(QString channelName)
: _channelName(channelName)
, _log(Logger::getInstance(channelName))
, _brightness(0)
{
//setAdjustment(UINT8_MAX, UINT8_MAX, UINT8_MAX);
resetInitialized();
}
RgbChannelAdjustment::RgbChannelAdjustment(uint8_t adjustR, uint8_t adjustG, uint8_t adjustB, QString channelName)
@@ -24,12 +25,18 @@ RgbChannelAdjustment::~RgbChannelAdjustment()
{
}
void RgbChannelAdjustment::resetInitialized()
{
Debug(_log, "initialize mapping with %d,%d,%d", _adjust[RED], _adjust[GREEN], _adjust[BLUE]);
memset(_initialized, false, sizeof(_initialized));
}
void RgbChannelAdjustment::setAdjustment(uint8_t adjustR, uint8_t adjustG, uint8_t adjustB)
{
_adjust[RED] = adjustR;
_adjust[GREEN] = adjustG;
_adjust[BLUE] = adjustB;
initializeMapping();
resetInitialized();
}
uint8_t RgbChannelAdjustment::getAdjustmentR() const
@@ -47,20 +54,22 @@ uint8_t RgbChannelAdjustment::getAdjustmentB() const
return _adjust[BLUE];
}
void RgbChannelAdjustment::apply(uint8_t input, uint8_t & red, uint8_t & green, uint8_t & blue)
void RgbChannelAdjustment::apply(uint8_t input, uint8_t brightness, uint8_t & red, uint8_t & green, uint8_t & blue)
{
red = _mapping[RED][input];
green = _mapping[GREEN][input];
blue = _mapping[BLUE][input];
}
if (_brightness != brightness)
{
_brightness = brightness;
resetInitialized();
}
void RgbChannelAdjustment::initializeMapping()
{
Debug(_log, "initialize mapping with %d,%d,%d", _adjust[RED], _adjust[GREEN], _adjust[BLUE]);
// initialize linear mapping
for (unsigned channel=0; channel<3; channel++)
for (unsigned idx=0; idx<=UINT8_MAX; idx++)
{
_mapping[channel][idx] = std::min( ((idx * _adjust[channel]) / UINT8_MAX), (unsigned)UINT8_MAX);
}
if (!_initialized[input])
{
_mapping[RED ][input] = std::min( ((_brightness * input * _adjust[RED ]) / 65025), UINT8_MAX);
_mapping[GREEN][input] = std::min( ((_brightness * input * _adjust[GREEN]) / 65025), UINT8_MAX);
_mapping[BLUE ][input] = std::min( ((_brightness * input * _adjust[BLUE ]) / 65025), UINT8_MAX);
_initialized[input] = true;
}
red = _mapping[RED ][input];
green = _mapping[GREEN][input];
blue = _mapping[BLUE ][input];
}

View File

@@ -5,21 +5,22 @@
RgbTransform::RgbTransform()
{
init(1.0, 1.0, 1.0, 0.0, false, 1.0);
init(1.0, 1.0, 1.0, 0.0, false, 100, 100);
}
RgbTransform::RgbTransform(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, double brightnessHigh)
RgbTransform::RgbTransform(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation)
{
init(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, brightnessHigh);
init(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, brightness, brightnessCompensation);
}
void RgbTransform::init(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, double brightnessHigh)
void RgbTransform::init(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation)
{
_backLightEnabled = true;
setGamma(gammaR,gammaG,gammaB);
setBacklightThreshold(backlightThreshold);
setBacklightColored(backlightColored);
setBrightness(brightnessHigh);
setBrightness(brightness);
setBrightnessCompensation(brightnessCompensation);
initializeMapping();
}
@@ -61,15 +62,15 @@ void RgbTransform::initializeMapping()
}
double RgbTransform::getBacklightThreshold() const
int RgbTransform::getBacklightThreshold() const
{
return _backlightThreshold;
}
void RgbTransform::setBacklightThreshold(double backlightThreshold)
void RgbTransform::setBacklightThreshold(int backlightThreshold)
{
_backlightThreshold = backlightThreshold;
_sumBrightnessLow = 765.0 * ((std::pow(2.0,backlightThreshold*2)-1) / 3.0);
_sumBrightnessLow = 765.0 * ((std::pow(2.0,(_backlightThreshold/100)*2)-1) / 3.0);
}
bool RgbTransform::getBacklightColored() const
@@ -92,15 +93,53 @@ void RgbTransform::setBackLightEnabled(bool enable)
_backLightEnabled = enable;
}
double RgbTransform::getBrightness() const
uint8_t RgbTransform::getBrightness() const
{
return _brightnessHigh;
return _brightness;
}
void RgbTransform::setBrightness(double brightness)
void RgbTransform::setBrightness(uint8_t brightness)
{
_brightnessHigh = brightness;
_sumBrightnessHigh = 765.0 * ((std::pow(2.0,brightness*2)-1) / 3.0);
_brightness = brightness;
updateBrightnessComponents();
}
void RgbTransform::setBrightnessCompensation(uint8_t brightnessCompensation)
{
_brightnessCompensation = brightnessCompensation;
updateBrightnessComponents();
}
uint8_t RgbTransform::getBrightnessCompensation() const
{
return _brightnessCompensation;
}
void RgbTransform::updateBrightnessComponents()
{
double Fw = _brightnessCompensation*2.0/100.0+1.0;
double Fcmy = _brightnessCompensation/100.0+1.0;
double B_in= 0;
_brightness_rgb = 0;
_brightness_cmy = 0;
_brightness_w = 0;
if (_brightness > 0)
{
B_in = (_brightness<50)? -0.09*_brightness+7.5 : -0.04*_brightness+5.0;
_brightness_rgb = std::ceil(std::min(255.0,255.0/B_in));
_brightness_cmy = std::ceil(std::min(255.0,255.0/(B_in*Fcmy)));
_brightness_w = std::ceil(std::min(255.0,255.0/(B_in*Fw)));
}
}
void RgbTransform::getBrightnessComponents(uint8_t & rgb, uint8_t & cmy, uint8_t & w )
{
rgb = _brightness_rgb;
cmy = _brightness_cmy;
w = _brightness_w;
}
void RgbTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue)
@@ -114,14 +153,7 @@ void RgbTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue)
// apply brightnesss
int rgbSum = red+green+blue;
if (_sumBrightnessHigh > 0 && rgbSum > _sumBrightnessHigh)
{
double cH = _sumBrightnessHigh / rgbSum;
red *= cH;
green *= cH;
blue *= cH;
}
else if ( _backLightEnabled && _sumBrightnessLow>0 && rgbSum < _sumBrightnessLow)
if ( _backLightEnabled && _sumBrightnessLow>0 && rgbSum < _sumBrightnessLow)
{
if (_backlightColored)
{
@@ -147,3 +179,4 @@ void RgbTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue)
}
//std::cout << _sumBrightnessLow << " " << (int)red << " " << (int)green << " " << (int)blue << std::endl;
}

View File

@@ -4,18 +4,41 @@
#include "QtHttpReply.h"
#include "QtHttpClientWrapper.h"
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QDebug>
#include <QUrlQuery>
const QString & QtHttpServer::HTTP_VERSION = QStringLiteral ("HTTP/1.1");
QtHttpServerWrapper::QtHttpServerWrapper (QObject * parent)
: QTcpServer (parent)
, m_useSsl (false)
{ }
QtHttpServerWrapper::~QtHttpServerWrapper (void) { }
void QtHttpServerWrapper::setUseSecure (const bool ssl) {
m_useSsl = ssl;
}
void QtHttpServerWrapper::incomingConnection (qintptr handle) {
QTcpSocket * sock = (m_useSsl
? new QSslSocket (this)
: new QTcpSocket (this));
if (sock->setSocketDescriptor (handle)) {
addPendingConnection (sock);
}
else {
delete sock;
}
}
QtHttpServer::QtHttpServer (QObject * parent)
: QObject (parent)
, m_useSsl (false)
, m_serverName (QStringLiteral ("The Qt5 HTTP Server"))
{
m_sockServer = new QTcpServer (this);
connect (m_sockServer, &QTcpServer::newConnection, this, &QtHttpServer::onClientConnected);
m_sockServer = new QtHttpServerWrapper (this);
connect (m_sockServer, &QtHttpServerWrapper::newConnection, this, &QtHttpServer::onClientConnected);
}
const QString & QtHttpServer::getServerName (void) const {
@@ -50,21 +73,59 @@ void QtHttpServer::setServerName (const QString & serverName) {
m_serverName = serverName;
}
void QtHttpServer::setUseSecure (const bool ssl) {
m_useSsl = ssl;
m_sockServer->setUseSecure (m_useSsl);
}
void QtHttpServer::setPrivateKey (const QSslKey & key) {
m_sslKey = key;
}
void QtHttpServer::setCertificates (const QList<QSslCertificate> & certs) {
m_sslCerts = certs;
}
void QtHttpServer::onClientConnected (void) {
while (m_sockServer->hasPendingConnections ()) {
QTcpSocket * sockClient = m_sockServer->nextPendingConnection ();
QtHttpClientWrapper * wrapper = new QtHttpClientWrapper (sockClient, this);
connect (sockClient, &QTcpSocket::disconnected, this, &QtHttpServer::onClientDisconnected);
m_socksClientsHash.insert (sockClient, wrapper);
emit clientConnected (wrapper->getGuid ());
if (QTcpSocket * sock = m_sockServer->nextPendingConnection ()) {
connect (sock, &QTcpSocket::disconnected, this, &QtHttpServer::onClientDisconnected);
if (m_useSsl) {
if (QSslSocket * ssl = qobject_cast<QSslSocket *> (sock)) {
connect (ssl, SslErrorSignal (&QSslSocket::sslErrors), this, &QtHttpServer::onClientSslErrors);
connect (ssl, &QSslSocket::encrypted, this, &QtHttpServer::onClientSslEncrypted);
connect (ssl, &QSslSocket::peerVerifyError, this, &QtHttpServer::onClientSslPeerVerifyError);
connect (ssl, &QSslSocket::modeChanged, this, &QtHttpServer::onClientSslModeChanged);
ssl->setLocalCertificateChain (m_sslCerts);
ssl->setPrivateKey (m_sslKey);
ssl->setPeerVerifyMode (QSslSocket::AutoVerifyPeer);
ssl->startServerEncryption ();
}
}
QtHttpClientWrapper * wrapper = new QtHttpClientWrapper (sock, this);
m_socksClientsHash.insert (sock, wrapper);
emit clientConnected (wrapper->getGuid ());
}
}
}
void QtHttpServer::onClientSslEncrypted (void) { }
void QtHttpServer::onClientSslPeerVerifyError (const QSslError & err) {
Q_UNUSED (err)
}
void QtHttpServer::onClientSslErrors (const QList<QSslError> & errors) {
Q_UNUSED (errors)
}
void QtHttpServer::onClientSslModeChanged (QSslSocket::SslMode mode) {
Q_UNUSED (mode)
}
void QtHttpServer::onClientDisconnected (void) {
QTcpSocket * sockClient = qobject_cast<QTcpSocket *> (sender ());
if (sockClient) {
QtHttpClientWrapper * wrapper = m_socksClientsHash.value (sockClient, Q_NULLPTR);
if (wrapper) {
if (QTcpSocket * sockClient = qobject_cast<QTcpSocket *> (sender ())) {
if (QtHttpClientWrapper * wrapper = m_socksClientsHash.value (sockClient, Q_NULLPTR)) {
emit clientDisconnected (wrapper->getGuid ());
wrapper->deleteLater ();
m_socksClientsHash.remove (sockClient);

View File

@@ -4,6 +4,12 @@
#include <QObject>
#include <QString>
#include <QHash>
#include <QTcpServer>
#include <QTcpSocket>
#include <QSslCertificate>
#include <QSslKey>
#include <QSslSocket>
#include <QHostAddress>
class QTcpSocket;
class QTcpServer;
@@ -12,6 +18,22 @@ class QtHttpRequest;
class QtHttpReply;
class QtHttpClientWrapper;
class QtHttpServerWrapper : public QTcpServer {
Q_OBJECT
public:
explicit QtHttpServerWrapper (QObject * parent = Q_NULLPTR);
virtual ~QtHttpServerWrapper (void);
void setUseSecure (const bool ssl = true);
protected:
void incomingConnection (qintptr handle) Q_DECL_OVERRIDE;
private:
bool m_useSsl;
};
class QtHttpServer : public QObject {
Q_OBJECT
@@ -19,14 +41,21 @@ public:
explicit QtHttpServer (QObject * parent = Q_NULLPTR);
static const QString & HTTP_VERSION;
typedef void (QSslSocket::* SslErrorSignal) (const QList<QSslError> &);
const QString & getServerName (void) const;
quint16 getServerPort (void) const;
quint16 getServerPort (void) const;
QString getErrorString (void) const;
public slots:
void start (quint16 port = 0);
void stop (void);
void setServerName (const QString & serverName);
void start (quint16 port = 0);
void stop (void);
void setServerName (const QString & serverName);
void setUseSecure (const bool ssl = true);
void setPrivateKey (const QSslKey & key);
void setCertificates (const QList<QSslCertificate> & certs);
signals:
void started (quint16 port);
@@ -37,13 +66,21 @@ signals:
void requestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
private slots:
void onClientConnected (void);
void onClientDisconnected (void);
void onClientConnected (void);
void onClientDisconnected (void);
void onClientSslEncrypted (void);
void onClientSslPeerVerifyError (const QSslError & err);
void onClientSslErrors (const QList<QSslError> & errors);
void onClientSslModeChanged (QSslSocket::SslMode mode);
private:
bool m_useSsl;
QSslKey m_sslKey;
QList<QSslCertificate> m_sslCerts;
QString m_serverName;
QTcpServer * m_sockServer;
QtHttpServerWrapper * m_sockServer;
QHash<QTcpSocket *, QtHttpClientWrapper *> m_socksClientsHash;
};
#endif // QTHTTPSERVER_H