Skip to content

Instantly share code, notes, and snippets.

@wavebeem
Created February 21, 2011 23:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wavebeem/837892 to your computer and use it in GitHub Desktop.
Save wavebeem/837892 to your computer and use it in GitHub Desktop.
// author: Brian Mock <mock.brian@gmail.com>
#include <stdio.h>
typedef unsigned int uint;
double clamp(double, double, double);
uint pack_rgb(uint, uint, uint);
uint shade_color(uint, double);
void unpack_rgb(uint, uint*, uint*, uint*);
void rgb_to_hsl(uint, uint, uint, double*, double*, double*);
void hsl_to_rgb(double, double, double, uint*, uint*, uint*);
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
uint
shade_color(uint rgb, double shadeVal) {
uint r, g, b;
double h, s, l;
unpack_rgb(rgb, &r, &g, &b);
printf("RGB: %3d %3d %3d\n", r, g, b);
rgb_to_hsl(r, g, b, &h, &s, &l);
printf("HSL: %.3f %.3f %.3f\n", h, s, l);
l += shadeVal;
l = clamp(l, 0, 1);
printf("HSL: %.3f %.3f %.3f\n", h, s, l);
hsl_to_rgb(h, s, l, &r, &g, &b);
printf("RGB: %3d %3d %3d\n", r, g, b);
rgb = pack_rgb(r, g, b);
return rgb;
}
double
clamp(double x, double a, double b) {
/*
* This solution makes me look cocky
return x < a ? a : x > b ? b : x;
*/
/*
* This solution looks weird... but cool
return
x < a ? a
: x > b ? b
: x;
*/
if(x < a)
return a;
else if(x > b)
return b;
else
return x;
}
uint
pack_rgb(uint r, uint g, uint b)
{
return (r << 16) | (r << 8) | b;
}
void
unpack_rgb(uint rgb, uint *r, uint *g, uint *b)
{
*r = (rgb >> 16) & 0xFF;
*g = (rgb >> 8) & 0xFF;
*b = rgb & 0xFF;
}
void
rgb_to_hsl(uint xr, uint xg, uint xb, double *h, double *s, double *l)
{
double r = xr/255.0;
double g = xg/255.0;
double b = xb/255.0;
double v;
double m;
double vm;
double r2, g2, b2;
*h = 0;
*s = 0;
*l = 0;
v = MAX(r, g);
v = MAX(v, b);
m = MIN(r, g);
m = MIN(m, b);
*l = (m + v)/2.0;
if(*l <= 0.0)
return;
vm = v - m;
*s = vm;
if(*s > 0.0)
*s /= (*l <= 0.5) ? (v + m) : (2.0 - v - m);
else
return;
r2 = (v - r)/vm;
g2 = (v - g)/vm;
b2 = (v - b)/vm;
if(r == v)
*h = (g == m ? 5.0 + b2 : 1.0 - g2);
else if(g == v)
*h = (b == m ? 1.0 + r2 : 3.0 - b2);
else
*h = (r == m ? 3.0 + g2 : 5.0 - r2);
*h /= 6.0;
}
void
hsl_to_rgb(double h, double sl, double l, uint *rx, uint *gx, uint *bx)
{
double v;
double r,g,b;
r = l;
g = l;
b = l;
v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
if (v > 0) {
double m;
double sv;
int sextant;
double fract, vsf, mid1, mid2;
m = l + l - v;
sv = (v - m ) / v;
h *= 6.0;
sextant = (int) h;
fract = h - sextant;
vsf = v * sv * fract;
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;
}
}
*rx = r * 255.0;
*gx = g * 255.0;
*bx = b * 255.0;
}
int
main(int argc, char **argv)
{
puts("Hello there");
uint rgb = 0xFCAF3E;
printf("#%06x\n", shade_color(rgb, 0.00));
printf("#%06x\n", shade_color(rgb, +0.25));
printf("#%06x\n", shade_color(rgb, -0.25));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment