Use hue-lightness-saturation. More tuitive than rgb space. To compile, do
gcc `imlib2-config --libs --cflags` -Wall -o getcolor getcolor.c
/**
*
* $Id: getcolor.c,v 1.2 2005/12/21 00:31:53 jchen Exp $
*
* Algorithm:
* Get four points from the picture from the one third and two thirds
* cross points. Find out the lightest and the darkest color.
* If the dark color is too dark (<10%), it may be too dark to represent
* the charastic of the picture. Set the dark color to the light color.
* If both the hue and the lightness of the two colors are too close,
* adjust their lightness to make the light lighter and the dark darker.
*
* Author:
* Jingshao Chen (jingshaochen at yahoo com)
*
*/
#include <X11/Xlib.h>
#include <Imlib2.h>
#include <stdio.h>
#include <string.h>
typedef struct {
float h;
float l;
float s;
int a;
} hlsa_color;
void print_color (char * message, hlsa_color c)
{
// For debug
fprintf (stderr, "%s h=%f, l=%f, s=%f, a=%d\n",
message, c.h, c.l, c.s, c.a);
}
float hue2rgb (float m1, float m2, float h)
{
if (h<0) h=h+1;
if (h>1) h=h-1;
if ((h*6)<1) return m1+(m2-m1)*h*6;
if ((h*2)<1) return m2;
if ((h*3)<2) return m1+(m2-m1)*(2.0/3-h)*6;
return m1;
}
Imlib_Color hls2rgb (hlsa_color hls)
{
/** from http://www.w3.org/TR/2003/CR-css3-color-20030514/
HOW TO RETURN hsl.to.rgb(h, s, l):
SELECT:
l<=0.5: PUT l*(s+1) IN m2
ELSE: PUT l+s-l*s IN m2
PUT l*2-m2 IN m1
PUT hue.to.rgb(m1, m2, h+1/3) IN r
PUT hue.to.rgb(m1, m2, h ) IN g
PUT hue.to.rgb(m1, m2, h-1/3) IN b
RETURN (r, g, b)
HOW TO RETURN hue.to.rgb(m1, m2, h):
IF h<0: PUT h+1 IN h
IF h>1: PUT h-1 IN h
IF h*6<1: RETURN m1+(m2-m1)*h*6
IF h*2<1: RETURN m2
IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6
RETURN m1
*/
float h, l, s;
Imlib_Color rgb;
float m1, m2;
h = hls.h/360.0;
l = hls.l;
s = hls.s;
if (l<=0.5)
m2=l*(s+1);
else
m2 = l+s-l*s;
m1 = l*2-m2;
rgb.red = (int)(255*hue2rgb(m1, m2, h+1.0/3));
rgb.green = (int)(255*hue2rgb(m1, m2, h));
rgb.blue = (int)(255*hue2rgb(m1, m2, h-1.0/3));
return rgb;
}
int main(int argc, char **argv) {
const int SAMPLE=3;
Imlib_Image image;
int stepx, stepy, i, j;
hlsa_color light, dark, sample;
Imlib_Color rgb_light, rgb_dark;
float dh;
if ( argc != 2 ) {
fprintf(stderr, "Usage: getcolor imageFile\n");
printf("Function DefaultColorset\n");
return 1;
}
image = imlib_load_image(argv[1]);
if (image) {
imlib_context_set_image(image);
stepx = imlib_image_get_width()/SAMPLE;
stepy = imlib_image_get_height()/SAMPLE;
for (i = 1; i<SAMPLE; i++) {
for (j = 1; j<SAMPLE; j++) {
imlib_image_query_pixel_hlsa(stepx*i, stepy*j,
&sample.h, &sample.l,
&sample.s, &sample.a);
print_color("sample color = ", sample);
if (i==1 && j==1) {
dark = sample;
light = sample;
}
if (dark.l > sample.l)
dark = sample;
if (light.l < sample.l )
light = sample;
}
}
print_color ("After sample, light color is", light);
print_color (" dark color is", dark);
if (dark.l < 0.1) {
print_color ("Too dark, dark is", dark);
dark = light;
}
dh = (light.h>dark.h)? light.h-dark.h : dark.h-light.h;
dh = (dh>180)? 360-dh : dh;
if (dh<30 && (light.l - dark.l) < 0.2) {
print_color ("Too close, light is ", light);
print_color (" dark is ", dark);
if (light.l < 0.618 && light.l > 0.382 )
light.l = 0.618;
else if (light.l < 0.382)
light.l = 0.382;
dark.l = light.l*0.382;
}
print_color ("Final light color is", light);
print_color (" dark color is", dark);
rgb_dark = hls2rgb(dark);
rgb_light = hls2rgb(light);
printf ("Function DynColorSet rgb:%02X/%02X/%02X rgb:%02X/%02X/%02X\n",
rgb_dark.red, rgb_dark.green, rgb_dark.blue,
rgb_light.red, rgb_light.green, rgb_light.blue);
imlib_free_image();
return 0;
}
printf ("Function DefaultColorset\n");
return 1;
}
/**
* History:
*
* $Log: getcolor.c,v $
* Revision 1.2 2005/12/21 00:31:53 jchen
* Added some explaination on the algorithm.
*
* Revision 1.1 2005/12/21 00:07:57 jchen
* Initial revision
*
*
*/