Skip to content

Commit e174008

Browse files
committed
tweaking and tuning
1 parent e4cae6c commit e174008

File tree

4 files changed

+139
-56
lines changed

4 files changed

+139
-56
lines changed

include/utility.h

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ namespace Color
2222
//Convert RGB straight to CIE xyY
2323
void rgb_to_xy(double& r, double& g, double& b, double& x, double& y, double& Y);
2424

25+
//Fit x,y into hue gamut
26+
void FitInGamut(double& x, double& y);
27+
2528
//Convert RGB to CIE XYZ, optionally performing gamma correction.
2629
//Using formulas from Philips Hue documentation.
2730
template<bool doGammaCorrection = true>

src/entertainment.cpp

+1-49
Original file line numberDiff line numberDiff line change
@@ -459,55 +459,7 @@ void EntertainmentCommThread::run()
459459
double X, Y, Z, x, y;
460460
Color::LCh_to_XYZ(newL, newC, newh, X, Y, Z);
461461
Color::XYZ_to_xy(X, Y, Z, x, y);
462-
463-
double dist = std::sqrt(std::pow(X - Color::D65_x, 2.0) + std::pow(Y - Color::D65_y, 2.0));
464-
465-
if (x < 0 || x > 1.0 || y < 0 || y > 1.0)
466-
{
467-
double diffX = (x - Color::D65_x);
468-
double diffY = (y - Color::D65_y);
469-
double unitX = diffX == 0.0 ? 0.0 : diffX / std::sqrt(std::pow(diffX, 2.0) + std::pow(diffY, 2.0));
470-
double unitY = diffY == 0.0 ? 0.0 : diffY / std::sqrt(std::pow(diffX, 2.0) + std::pow(diffY, 2.0));
471-
double testDist;
472-
double bestDist = 0;
473-
474-
if (unitX > 0.0)
475-
{
476-
testDist = (1.0 - Color::D65_x) / unitX;
477-
if (Color::D65_y + testDist * unitY <= 1.0 && Color::D65_y + testDist * unitY >= 0.0)
478-
{
479-
bestDist = std::max(bestDist, testDist);
480-
}
481-
}
482-
else
483-
{
484-
testDist = (-Color::D65_x) / unitX;
485-
if (Color::D65_y + testDist * unitY <= 1.0 && Color::D65_y + testDist * unitY >= 0.0)
486-
{
487-
bestDist = std::max(bestDist, testDist);
488-
}
489-
}
490-
491-
if (unitY > 0.0)
492-
{
493-
testDist = (1.0 - Color::D65_y) / unitY;
494-
if (Color::D65_x + testDist * unitX <= 1.0 && Color::D65_x + testDist * unitX >= 0.0)
495-
{
496-
bestDist = std::max(bestDist, testDist);
497-
}
498-
}
499-
else
500-
{
501-
testDist = (-Color::D65_y) / unitY;
502-
if (Color::D65_x + testDist * unitX <= 1.0 && Color::D65_x + testDist * unitX >= 0.0)
503-
{
504-
bestDist = std::max(bestDist, testDist);
505-
}
506-
}
507-
508-
x = Color::D65_x + unitX * bestDist;
509-
y = Color::D65_y + unitY * bestDist;
510-
}
462+
Color::FitInGamut(x, y);
511463

512464
quint64 R = x * 0xffff;
513465
quint64 G = y * 0xffff;

src/huestacean.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ void Huestacean::ReadSettings()
109109
setMaxLuminance( settings.value("maxLuminance", 1.0).toDouble());
110110
setMinLuminance( settings.value("minLuminance", 0.0).toDouble());
111111
setChromaBoost( settings.value("chromaBoost", 1.0).toDouble());
112-
setLumaBoost( settings.value("lumaBoost", 1.2).toDouble());
113-
setCenterSlowness( settings.value("centerSlowness", 5.0).toDouble());
114-
setSideSlowness( settings.value("sideSlowness", 8.0).toDouble());
112+
setLumaBoost( settings.value("lumaBoost", 1.5).toDouble());
113+
setCenterSlowness( settings.value("centerSlowness", 8.9).toDouble());
114+
setSideSlowness( settings.value("sideSlowness", 10.0).toDouble());
115115

116116
settings.endGroup();
117117

@@ -297,7 +297,7 @@ void Huestacean::startScreenSync(EntertainmentGroup* eGroup)
297297

298298
size_t maxLeft = chromaSamples.size() * (3.0 / 4.0);
299299
size_t minLeft = chromaSamples.size() * (1.0 / 4.0);
300-
size_t finalSize = std::max(std::min(chromaSamples.size() - i, maxLeft), minLeft);
300+
size_t finalSize = std::max(std::min((size_t) i, maxLeft), minLeft);
301301

302302
chromaSamples.resize(finalSize);
303303
}
@@ -314,15 +314,15 @@ void Huestacean::startScreenSync(EntertainmentGroup* eGroup)
314314
int i;
315315
for (i = 0; i < lumaSamples.size(); ++i)
316316
{
317-
if (lumaSamples[i].L < 0.05)
317+
if (lumaSamples[i].L < 0.5)
318318
{
319319
break;
320320
}
321321
}
322322

323323
size_t maxLeft = lumaSamples.size() * (3.0 / 4.0);
324324
size_t minLeft = lumaSamples.size() * (1.0 / 4.0);
325-
size_t finalSize = std::max(std::min(lumaSamples.size() - i, maxLeft), minLeft);
325+
size_t finalSize = std::max(std::min((size_t) i, maxLeft), minLeft);
326326

327327
lumaSamples.resize(finalSize);
328328
}
@@ -369,7 +369,9 @@ void Huestacean::startScreenSync(EntertainmentGroup* eGroup)
369369

370370
double slowness = Utility::lerp(getCenterSlowness(), getSideSlowness(), std::abs(light.x));
371371

372-
L = (oldL * (slowness - 1.0) + mean.L) / slowness;
372+
L = (oldL * (slowness - 1.0) + mean.L) / (slowness);
373+
374+
slowness *= 2;
373375
C = (oldC * (slowness - 1.0) + mean.C) / slowness;
374376

375377
constexpr double WHITE_C_CUTOFF = 1.5;

src/utility.cpp

+126
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "utility.h"
2+
#include <QDebug>
23

34
void Color::XYZ_to_LCh(double& X, double& Y, double& Z, double& L, double& C, double& h)
45
{
@@ -44,6 +45,131 @@ void Color::LCh_to_XYZ(double& L, double& C, double& h, double& X, double& Y, do
4445
X = D65_Xn * f((L + 16.0) / 116.0 + a / 500.0);
4546
Y = D65_Yn * f((L + 16.0) / 116.0);
4647
Z = D65_Zn * f((L + 16.0) / 116.0 - b / 200.0);
48+
49+
#if 0
50+
//Suppress yellow, the LED is too bright
51+
//0.35 - 2.5
52+
//0.6 to 1.7, 1.15 mid
53+
double yellow = 1.7;
54+
double yellowWidth = 1.1;
55+
56+
double distFromYellow = std::abs(yellow - h);
57+
if (distFromYellow < yellowWidth)
58+
{
59+
double suppression = 1.4 * (1.0 - (distFromYellow / yellowWidth));
60+
suppression = std::min(1.0, suppression);
61+
Y = std::min(L, Utility::lerp(Y, Y * 0.8, suppression));
62+
qDebug() << distFromYellow << h << suppression;
63+
}
64+
#endif
65+
66+
//0.446613 0.384795
67+
//0.400317 0.359206
68+
}
69+
70+
struct vector2d {
71+
double x;
72+
double y;
73+
74+
vector2d(double inx, double iny) : x(inx), y(iny) {
75+
76+
}
77+
};
78+
79+
float dist(vector2d v1, vector2d v2)
80+
{
81+
float dx = v1.x - v2.x;
82+
float dy = v1.y - v2.y;
83+
float dist = sqrt(dx * dx + dy * dy);
84+
85+
return dist;
86+
}
87+
88+
float cross(vector2d v1, vector2d v2)
89+
{
90+
return (v1.x * v2.y - v1.y * v2.x);
91+
}
92+
93+
bool InGamut(vector2d p)
94+
{
95+
//gamut C
96+
vector2d red(0.692, 0.308);
97+
vector2d green(0.17, 0.7);
98+
vector2d blue(0.153, 0.048);
99+
100+
vector2d v1 = vector2d(green.x - red.x, green.y - red.y);
101+
vector2d v2 = vector2d(blue.x - red.x, blue.y - red.y);
102+
103+
vector2d q = vector2d(p.x - red.x, p.y - red.y);
104+
105+
float s = cross(q, v2) / cross(v1, v2);
106+
float t = cross(v1, q) / cross(v1, v2);
107+
108+
if ((s >= 0.0f) && (t >= 0.0f) && (s + t <= 1.0f)) {
109+
return true;
110+
}
111+
else {
112+
return false;
113+
}
114+
}
115+
116+
vector2d getClosestPointToPoints(vector2d A, vector2d B, vector2d P) {
117+
vector2d AP(P.x - A.x, P.y - A.y);
118+
vector2d AB(B.x - A.x, B.y - A.y);
119+
float ab2 = AB.x * AB.x + AB.y * AB.y;
120+
float ap_ab = AP.x * AB.x + AP.y * AB.y;
121+
122+
float t = ap_ab / ab2;
123+
124+
if (t < 0.0f) {
125+
t = 0.0f;
126+
}
127+
else if (t > 1.0f) {
128+
t = 1.0f;
129+
}
130+
131+
vector2d newPoint(A.x + AB.x * t, A.y + AB.y * t);
132+
return newPoint;
133+
}
134+
135+
void Color::FitInGamut(double &x, double& y)
136+
{
137+
//gamut C
138+
vector2d red(0.692, 0.308);
139+
vector2d green(0.17, 0.7);
140+
vector2d blue(0.153, 0.048);
141+
142+
vector2d v(x, y);
143+
144+
bool inGamut = InGamut(v);
145+
if (!inGamut)
146+
{
147+
//Find the closest point on each line in the triangle.
148+
vector2d pAB = getClosestPointToPoints(red, green, v);
149+
vector2d pAC = getClosestPointToPoints(blue, red, v);
150+
vector2d pBC = getClosestPointToPoints(green, blue, v);
151+
152+
//Get the distances per point and see which point is closer to our Point.
153+
float dAB = dist(v, pAB);
154+
float dAC = dist(v, pAC);
155+
float dBC = dist(v, pBC);
156+
157+
float lowest = dAB;
158+
vector2d closestPoint = pAB;
159+
160+
if (dAC < lowest) {
161+
lowest = dAC;
162+
closestPoint = pAC;
163+
}
164+
if (dBC < lowest) {
165+
lowest = dBC;
166+
closestPoint = pBC;
167+
}
168+
169+
//Change the xy value to a value which is within the reach of the lamp.
170+
x = closestPoint.x;
171+
y = closestPoint.y;
172+
}
47173
}
48174

49175
void Color::XYZ_to_xy(double& X, double& Y, double& Z, double& x, double& y)

0 commit comments

Comments
 (0)