Review Request: KColorSpace::KHCY::KHCY(const & QColor) constructor floating point precision error

Matthew Woehlke mw_triad at users.sourceforge.net
Thu Jun 25 17:21:56 BST 2009


(Please do not quote my e-mail address unobfuscated in message bodies.)

Benoit Jacob wrote:
> Guys, maybe I see this a bit late, but the file in SVN still uses
> operator== between qreal's and that's a "no go".

In this case I'm not sure I agree. I /want/ to treat the values as not 
equal even if they differ by a small amount; as long as the math stays 
consistent, we should get a reasonable chroma. Probably the best thing 
would be to simply build the whole module with -ffloat-store and leave 
it at that. But that adds complication to the build system that's only
needed for one platform.

(Besides, this code is already slow, and simultaneously something you 
might want in a critical path. I'm not entirely comfortable making it 
even slower...)

Hmm... right now you pointed out that the code as-is should always work. 
And for the moment, it /is/ working (and there is now a unit test in 
place to catch if it starts misbehaving the same way again).

I'm really not sure I want to change this. Right now, the precision of 
QColor means it shouldn't ever break. Conversely, if QColor ever gets to 
where 0.9999999999, 0.9999999975, 1.0 can be represented, I'm worried 
that a fuzzy compare will wrongly consider this "pure white", which /it 
isn't/. (In fact, this color has chroma == 1.0.)

> *** But I just want to avoid division by 0 ! So for an expression like
> a/(b-c) the check that I want is really b==c, right ?

More specifically, catch anything that will cause the result of that 
expression to be greater than one. For now. If we ever go HDR, then the 
constraints need to be re-thought. (Maybe. Actually I don't think chroma 
can exceed 1.0 unless you have "darklight", i.e. negative RGB values.)

Additionally, treating arbitrarily-small values as 0 would be /wrong/, 
since there is no constraint against having the not-quite-black color 
1.7e-50, 1.4e-50, 1.9e-42. This color has a pretty strong chroma despite 
that it's luma is ludicrously small.

So you can't just look at the denominator, you have to look at the result.

The original problem occurred due to loss of precision when the r,g,b 
channels should have been (in fact, were) equal, but imprecise 
conversion resulted in the luma being slightly off. The problem is 
you're dealing with behavior near a singularity, which isn't easy to get 
right.

On a side note, this problem occurs due to trying to model light in an 
LDR color space. Moving to HDR (assuming it is implemented correctly) 
would make this problem go away :-).

> *** What if I know that my numbers are between -1 and 1, or even
> between 0 and 1, and i know furthermore that a number can be declared
> "negligible" as soon as it is negligible when compared to 1? (Note:
> this is the case in kcolorspaces.cpp)

No it isn't the case. The last assumption is wrong; see above.

-- 
Matthew
"Who wants to sing?" -- Orcs (Warcraft II)





More information about the kde-core-devel mailing list