[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
> Do you mean if hue is so close to 360.0 (but still strictly smaller),
> that hue/60.0 is represented exactly as 6?
At least gives 6 after casting to int.
> I'm not sure if this can happen, but I think my code treats this case
> correctly too.
This was precisely the bug: the original routine was
else {
while (h < 0)
h += 360;
h = fmod(h, 360) / 60.0;
i = (int)h;
f = h - i;
[...]
switch (i) {
case 0: *r = v; *g = z; *b = x; break;
case 1: *r = y; *g = v; *b = x; break;
case 2: *r = x; *g = v; *b = z; break;
case 3: *r = x; *g = y; *b = v; break;
case 4: *r = z; *g = x; *b = v; break;
case 5: *r = v; *g = x; *b = y; break;
}
Some pixels were missed, because i=6 for them.
> To convince yourself, first consider the case when hue is pretty close
> to 360, say 359.94, so that hue/60.0 is close to, but still strictly
> smaller than 6.0, namely 5.999. In this case:
> i=5,
> f=0.999,
> x is very close to v*(1-s),
> y is very close to v*(1-s),
> so
> *r=v,
> *g=v*(1-s),
> *b=v*(1-s).
>
> Now consider the case when hue is so close to 360 that hue/60.0 is equal
> to 6.0. In this case:
> i=6,
> f=0,
> x=v*(1-s),
> z=v*(1-s),
> so
> *r=v,
> *g=v*(1-s),
> *b=v*(1-s).
>
> So the two cases produce the same results, as the user would expect.
> Magic! :-) This works because the hue parameter really is periodic, with
> period 360.0.
Hmm... yes, you're right. And the tiny patch contained in my previous
message is wrong, because it wrongly assumes the continuity of the
transformation of h into (i, f), which of course doesn't exist because of
fmod(). So 360-epsilon should indeed be treated like 0-60.
I applied your patch to the branch. Thanks.
--
Eric Botcazou
ebotcazou@xxxxxxxxxx