openmv/util/rgb2lab.c
2014-10-01 01:42:06 +02:00

133 lines
5.4 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
//255,50,10 -> [55.6477, 73.3233, 65.9473]
struct color {
union {
uint8_t v[3];
struct {
uint8_t r;
uint8_t g;
uint8_t b;
};
struct {
int h;
int s;
int v;
};
struct {
float L;
float A;
float B;
};
struct {
float x;
float y;
float z;
};
};
};
float lab_distance(struct color *c0, struct color *c1)
{
float sum=0.0f;
sum += (c0->L - c1->L) * (c0->L - c1->L);
sum += (c0->A - c1->A) * (c0->A - c1->A);
sum += (c0->B - c1->B) * (c0->B - c1->B);
return sqrtf(sum);
}
const float xyz_table[256] = {
0.000000f, 0.030353f, 0.060705f, 0.091058f, 0.121411f, 0.151763f, 0.182116f, 0.212469f,
0.242822f, 0.273174f, 0.303527f, 0.334654f, 0.367651f, 0.402472f, 0.439144f, 0.477695f,
0.518152f, 0.560539f, 0.604883f, 0.651209f, 0.699541f, 0.749903f, 0.802319f, 0.856812f,
0.913406f, 0.972122f, 1.032982f, 1.096009f, 1.161224f, 1.228649f, 1.298303f, 1.370208f,
1.444384f, 1.520851f, 1.599629f, 1.680737f, 1.764195f, 1.850022f, 1.938236f, 2.028857f,
2.121901f, 2.217388f, 2.315336f, 2.415763f, 2.518686f, 2.624122f, 2.732089f, 2.842604f,
2.955683f, 3.071344f, 3.189603f, 3.310476f, 3.433981f, 3.560131f, 3.688945f, 3.820436f,
3.954624f, 4.091520f, 4.231141f, 4.373503f, 4.518620f, 4.666508f, 4.817182f, 4.970656f,
5.126946f, 5.286066f, 5.448028f, 5.612849f, 5.780543f, 5.951124f, 6.124607f, 6.301003f,
6.480328f, 6.662595f, 6.847818f, 7.036011f, 7.227186f, 7.421358f, 7.618539f, 7.818743f,
8.021983f, 8.228271f, 8.437622f, 8.650046f, 8.865561f, 9.084172f, 9.305898f, 9.530748f,
9.758737f, 9.989874f, 10.224174f, 10.461649f, 10.702312f, 10.946172f, 11.193243f, 11.443539f,
11.697067f, 11.953843f, 12.213880f, 12.477184f, 12.743770f, 13.013649f, 13.286834f, 13.563335f,
13.843163f, 14.126330f, 14.412848f, 14.702728f, 14.995980f, 15.292616f, 15.592647f, 15.896087f,
16.202940f, 16.513222f, 16.826939f, 17.144112f, 17.464739f, 17.788841f, 18.116423f, 18.447498f,
18.782076f, 19.120165f, 19.461781f, 19.806931f, 20.155624f, 20.507870f, 20.863686f, 21.223072f,
21.586052f, 21.952623f, 22.322798f, 22.696589f, 23.074007f, 23.455065f, 23.839766f, 24.228119f,
24.620140f, 25.015837f, 25.415215f, 25.818291f, 26.225073f, 26.635567f, 27.049786f, 27.467737f,
27.889431f, 28.314880f, 28.744089f, 29.177071f, 29.613832f, 30.054384f, 30.498737f, 30.946899f,
31.398874f, 31.854683f, 32.314323f, 32.777817f, 33.245159f, 33.716366f, 34.191444f, 34.670406f,
35.153271f, 35.640026f, 36.130688f, 36.625271f, 37.123775f, 37.626221f, 38.132610f, 38.642952f,
39.157257f, 39.675529f, 40.197788f, 40.724026f, 41.254269f, 41.788513f, 42.326775f, 42.869057f,
43.415371f, 43.965725f, 44.520126f, 45.078583f, 45.641106f, 46.207706f, 46.778385f, 47.353153f,
47.932022f, 48.514999f, 49.102089f, 49.693306f, 50.288658f, 50.888145f, 51.491779f, 52.099567f,
52.711521f, 53.327648f, 53.947960f, 54.572456f, 55.201149f, 55.834049f, 56.471165f, 57.112492f,
57.758053f, 58.407848f, 59.061890f, 59.720188f, 60.382740f, 61.049568f, 61.720665f, 62.396049f,
63.075722f, 63.759697f, 64.447975f, 65.140572f, 65.837494f, 66.538734f, 67.244324f, 67.954254f,
68.668549f, 69.387192f, 70.110199f, 70.837593f, 71.569359f, 72.305527f, 73.046089f, 73.791054f,
74.540436f, 75.294235f, 76.052460f, 76.815125f, 77.582237f, 78.353790f, 79.129807f, 79.910286f,
80.695236f, 81.484665f, 82.278587f, 83.076996f, 83.879913f, 84.687332f, 85.499268f, 86.315727f,
87.136719f, 87.962234f, 88.792320f, 89.626945f, 90.466133f, 91.309868f, 92.158203f, 93.011093f,
93.868591f, 94.730659f, 95.597351f, 96.468628f, 97.344543f, 98.225060f, 99.110222f, 100.000000f
};
void rgb2lab (struct color *rgb, struct color *lab)
{
float v[3];
float x,y,z;
const float c = 16.0f/ 116.0f;
v[0] = xyz_table[rgb->v[0]];
v[1] = xyz_table[rgb->v[1]];
v[2] = xyz_table[rgb->v[2]];
x = (v[0] * 0.4124f + v[1] * 0.3576f + v[2] * 0.1805f) / 95.047f ;
y = (v[0] * 0.2126f + v[1] * 0.7152f + v[2] * 0.0722f) / 100.0f ;
z = (v[0] * 0.0193f + v[1] * 0.1192f + v[2] * 0.9505f) / 108.883f ;
x = (x>0.008856f)? cbrtf(x) : (x * 7.787f) + c;
y = (y>0.008856f)? cbrtf(y) : (y * 7.787f) + c;
z = (z>0.008856f)? cbrtf(z) : (z * 7.787f) + c;
lab->L = (116.0f * y-16.0f);
lab->A = (500.0f * (x-y));
lab->B = (200.0f * (y-z));
}
static inline int fround(float flt)
{
return (int) floor(flt+0.5f);
}
int main(int argc, char **argv)
{
struct color lab1={0};
struct color rgb1={0};
uint8_t p0,p1;
uint16_t c = 0;
printf("#include <stdint.h>\n");
printf("const int8_t lab_table[196608] = {\n");
for (int i=0; i<65536; i++, c++) {
p0 = ((char*)&c)[0];
p1 = ((char*)&c)[1];
/* map RGB565 to RGB888 */
rgb1.r = (uint8_t) (p0>>3) * 255/31;
rgb1.g = (uint8_t) (((p0&0x07)<<3) | (p1>>5)) * 255/63;
rgb1.b = (uint8_t) (p1&0x1F) * 255/31;
rgb2lab(&rgb1, &lab1);
printf("%d, %d, %d, ", fround(lab1.L), fround(lab1.A), fround(lab1.B));
if ((i+1)%9==0) {
printf("\n");
}
}
printf("};\n");
return 0;
}