Re: [AD] Faster hsv_to_rgb() |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
Inspired by your efforts, I rearranged rgb_to_hsv() (conversion the
other way) a bit. A call to the new version takes 60% of the time that a
call to previous version took. I ran through all possible r,g,b triples,
and it gives the same result to a factor within 0.0000001, and I also
verified that converting back the hsv values computed by rgb_to_hsv()
always gives the original rgb. The patch is attached and I put my test
program at http://peg.it.uu.se/~sven/test.c. OK to commit?
Sven
Index: src/color.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/color.c,v
retrieving revision 1.16
diff -u -r1.16 color.c
--- src/color.c 7 Feb 2003 13:29:06 -0000 1.16
+++ src/color.c 16 Apr 2003 20:40:06 -0000
@@ -383,36 +383,53 @@
*/
void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v)
{
- float min, max, delta, rc, gc, bc;
+ int delta;
- rc = (float)r / 255.0f;
- gc = (float)g / 255.0f;
- bc = (float)b / 255.0f;
- max = MAX(rc, MAX(gc, bc));
- min = MIN(rc, MIN(gc, bc));
- delta = max - min;
- *v = max;
-
- if (max != 0.0f)
- *s = delta / max;
- else
- *s = 0.0f;
-
- if (*s == 0.0f) {
- *h = 0.0f;
+ if (r > g) {
+ if (b > r) {
+ /* b>r>g */
+ delta = b-g;
+ *h = 240.0f + ((r-g) * 60) / (float)delta;
+ *s = (float)delta / (float)b;
+ *v = (float)b * (1.0f/255.0f);
+ }
+ else {
+ /* r>g and r>b */
+ delta = r - MIN(g, b);
+ *h = ((g-b) * 60) / (float)delta;
+ if (*h < 0)
+ *h += 360;
+ *s = (float)delta / (float)r;
+ *v = (float)r * (1/255.0f);
+ }
}
else {
- if (rc == max)
- *h = (gc - bc) / delta;
- else if (gc == max)
- *h = 2.0f + (bc - rc) / delta;
- else if (bc == max)
- *h = 4.0f + (rc - gc) / delta;
-
- *h *= 60.0f;
- if (*h < 0.0f)
- *h += 360.0f;
- }
+ if (b > g) {
+ /* b>g>=r */
+ delta = b-r;
+ *h = 240.0 + ((r-g) * 60) / (float)delta;
+ *s = (float)delta / (float)b;
+ *v = (float)b * (1/255.0f);
+ }
+ else {
+ /* g>=b and g>=r */
+ delta = g - MIN(r, b);
+ if (delta == 0) {
+ *h = 0.0f;
+ if (g == 0)
+ *s = *v = 0;
+ else {
+ *s = (float)delta / (float)g;
+ *v = (float)g * (1/255.0f);
+ }
+ }
+ else {
+ *h = 120.0 + ((b-r) * 60) / (float)delta;
+ *s = (float)delta / (float)g;
+ *v = (float)g * (1/255.0f);
+ }
+ }
+ }
}