-(void) getHue:(float *)hue saturation:(float *)saturation brightness:(float *)brightness alpha:(float *)alpha
, -(float) brightnessComponent
, -(float) saturationComponent
and -(float) hueComponent
.To see the problem, just launch from Lave using the latest trunk and with the console invoke the planet's airColor with system.mainPlanet.airColor. Although the planetinfo key sets it to blue ("0 0 1 1"), the response you will get is [0, 0, 0.5, 1] - a darker blue. Other colors will yield even weirder responses.
After looking at this a bit, I think the issue is with the conversion from rgb to hsb itself. The b (brightness) component calculation seems to be particularly incorrect. After some research, I would propose the following changes to fix this, but would appreciate some more testing before committing it.
Here is the patch:
Code: Select all
diff --git a/src/Core/OOColor.m b/src/Core/OOColor.m
index 346f36b4..27e40309 100644
--- a/src/Core/OOColor.m
+++ b/src/Core/OOColor.m
@@ -400,26 +400,25 @@ MA 02110-1301, USA.
{
float maxrgb = (rgba[0] > rgba[1])? ((rgba[0] > rgba[2])? rgba[0]:rgba[2]):((rgba[1] > rgba[2])? rgba[1]:rgba[2]);
float minrgb = (rgba[0] < rgba[1])? ((rgba[0] < rgba[2])? rgba[0]:rgba[2]):((rgba[1] < rgba[2])? rgba[1]:rgba[2]);
- if (maxrgb == minrgb)
- {
- return 0.0f;
- }
float delta = maxrgb - minrgb;
+ float fRed = rgba[0], fGreen = rgba[1], fBlue = rgba[2];
float hue = 0.0f;
- if (rgba[0] == maxrgb)
+ if (maxrgb == fRed && fGreen >= fBlue)
+ {
+ hue = 60.0f * (fGreen - fBlue) / delta;
+ }
+ else if (maxrgb == fRed && fGreen < fBlue)
{
- hue = (rgba[1] - rgba[2]) / delta;
+ hue = 60.0f * (fGreen - fBlue) / delta + 360.0f;
}
- else if (rgba[1] == maxrgb)
+ else if (maxrgb == fGreen)
{
- hue = 2.0f + (rgba[2] - rgba[0]) / delta;
+ hue = 60.0f * (fBlue - fRed) / delta + 120.0f;
}
- else if (rgba[2] == maxrgb)
+ else if (maxrgb == fBlue)
{
- hue = 4.0f + (rgba[0] - rgba[1]) / delta;
+ hue = 60.0f * (fRed - fGreen) / delta + 240.0f;
}
- hue *= 60.0f;
- while (hue < 0.0f) hue += 360.0f;
return hue;
}
@@ -427,17 +426,13 @@ MA 02110-1301, USA.
{
float maxrgb = (rgba[0] > rgba[1])? ((rgba[0] > rgba[2])? rgba[0]:rgba[2]):((rgba[1] > rgba[2])? rgba[1]:rgba[2]);
float minrgb = (rgba[0] < rgba[1])? ((rgba[0] < rgba[2])? rgba[0]:rgba[2]):((rgba[1] < rgba[2])? rgba[1]:rgba[2]);
- float brightness = 0.5f * (maxrgb + minrgb);
- if (maxrgb == minrgb) return 0.0f;
- float delta = maxrgb - minrgb;
- return (brightness <= 0.5f) ? (delta / (maxrgb + minrgb)) : (delta / (2.0f - (maxrgb + minrgb)));
+ return maxrgb == 0.0f ? 0.0f : (1.0f - (minrgb / maxrgb));
}
- (float) brightnessComponent
{
float maxrgb = (rgba[0] > rgba[1])? ((rgba[0] > rgba[2])? rgba[0]:rgba[2]):((rgba[1] > rgba[2])? rgba[1]:rgba[2]);
- float minrgb = (rgba[0] < rgba[1])? ((rgba[0] < rgba[2])? rgba[0]:rgba[2]):((rgba[1] < rgba[2])? rgba[1]:rgba[2]);
- return 0.5f * (maxrgb + minrgb);
+ return maxrgb;
}
- (void) getHue:(float *)hue saturation:(float *)saturation brightness:(float *)brightness alpha:(float *)alpha
@@ -446,32 +441,33 @@ MA 02110-1301, USA.
*alpha = rgba[3];
- int maxrgb = (rgba[0] > rgba[1])? ((rgba[0] > rgba[2])? 0:2):((rgba[1] > rgba[2])? 1:2);
- int minrgb = (rgba[0] < rgba[1])? ((rgba[0] < rgba[2])? 0:2):((rgba[1] < rgba[2])? 1:2);
- *brightness = 0.5f * (rgba[maxrgb] + rgba[minrgb]);
- if (rgba[maxrgb] == rgba[minrgb])
+ float fRed = rgba[0], fGreen = rgba[1], fBlue = rgba[2];
+ float maxrgb = fmax(fRed, fmax(fGreen, fBlue));
+ float minrgb = fmin(fRed, fmin(fGreen, fBlue));
+ float delta = maxrgb - minrgb;
+ float h = 0.0f;
+ if (maxrgb == fRed && fGreen >= fBlue)
{
- *saturation = 0.0f;
- *hue = 0.0f;
- return;
+ h = 60.0f * (fGreen - fBlue) / delta;
}
- float delta = rgba[maxrgb] - rgba[minrgb];
- *saturation = (*brightness <= 0.5f) ? (delta / (rgba[maxrgb] + rgba[minrgb])) : (delta / (2.0f - (rgba[maxrgb] + rgba[minrgb])));
-
- if (maxrgb == 0)
+ else if (maxrgb == fRed && fGreen < fBlue)
{
- *hue = (rgba[1] - rgba[2]) / delta;
+ h = 60.0f * (fGreen - fBlue) / delta + 360.0f;
}
- else if (maxrgb == 1)
+ else if (maxrgb == fGreen)
{
- *hue = 2.0f + (rgba[2] - rgba[0]) / delta;
+ h = 60.0f * (fBlue - fRed) / delta + 120.0f;
}
- else if (maxrgb == 2)
+ else if (maxrgb == fBlue)
{
- *hue = 4.0f + (rgba[0] - rgba[1]) / delta;
+ h = 60.0f * (fRed - fGreen) / delta + 240.0f;
}
- *hue *= 60.0f;
- while (*hue < 0.0f) *hue += 360.0f;
+
+ float s = (maxrgb == 0.0f) ? 0.0f : (1.0f - (minrgb / maxrgb));
+
+ *hue = h;
+ *saturation = s;
+ *brightness = maxrgb;
}