Wednesday, June 25, 2008

Integer conversion from HSL to RGB

A hue-saturation-lumination to RGB conversion that uses no floating point.

Inputs and outputs are in the range 0 to 255.

Derived from an incredibly old floating-point algorithm.
void HSL_to_RGB(int hue, int sat, int lum, int* r, int* g, int* b)
{
int v;

v = (lum < 128) ? (lum * (256 + sat)) >> 8 :
(((lum + sat) << 8) - lum * sat) >> 8;
if (v <= 0) {
*r = *g = *b = 0;
} else {
int m;
int sextant;
int fract, vsf, mid1, mid2;

m = lum + lum - v;
hue *= 6;
sextant = hue >> 8;
fract = hue - (sextant << 8);
vsf = v * fract * (v - m) / v >> 8;
mid1 = m + vsf;
mid2 = v - vsf;
switch (sextant) {
case 0: *r = v; *g = mid1; *b = m; break;
case 1: *r = mid2; *g = v; *b = m; break;
case 2: *r = m; *g = v; *b = mid1; break;
case 3: *r = m; *g = mid2; *b = v; break;
case 4: *r = mid1; *g = m; *b = v; break;
case 5: *r = v; *g = m; *b = mid2; break;
}
}
}

Wednesday, June 04, 2008

Circular Template References in C++

I wanted to have three template classes, designed to work together, that could use facilities in one another, in such a way that any of the three classes could be replaced with a different version--something like what "Boris" describes here, just more complex.

It didn't seem possible and I had just about given up--I decided instead that I would give each class a non-template base class with limited functionality, and then each class would access the other two classes through this more limited interface. But on the train on the way home from work it hit me: a special "traits" class would make it possible to use circular references between templates. Here is an example:
#include <stdio.h>

template<class Combo> struct A
{
typedef typename Combo::b_t B;
B* b;
};

template<class Combo> struct B
{
typedef typename Combo::a_t A;
A* a;
};

struct MyCombo {
typedef A<MyCombo> a_t;
typedef B<MyCombo> b_t;
};

int main(int argc, char* argv[])
{
A<MyCombo> a;
B<MyCombo> b;
a.b = &b;
b.a = &a;
return 0;
}