FloatImg/funcs/hsv.c

169 lines
3.7 KiB
C

/*
* FloatImg library
* HUE - SATURATION - VALUE
+---------------------------------------------+
| ce code ne fonctionne vraiment PAS ! |
+---------------------------------------------+
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include "../floatimg.h"
extern int verbosity;
/*
https://baillehachepascal.dev/2021/rgb_hsv.php
*/
/* --------------------------------------------------------------------- */
/* helper functions */
static float maxi3f(float a, float b, float c)
{
return ((a > b)? (a > c ? a : c) : (b > c ? b : c));
}
static float mini3f(float a, float b, float c)
{
return ((a < b)? (a < c ? a : c) : (b < c ? b : c));
}
static int pseudoeq(float a, float b)
{
return (fabsf(a-b)<0.00000001); // UGLY HACK ???
}
/* --------------------------------------------------------------------- */
/*
* WARNING : ALL THIS CODE IS STRANGE
*
www.tutorialspoint.com/c-program-to-change-rgb-color-model-to-hsv-color-model
*/
int fimg_rgb2hsv(float rgb[3], float hsv[3], float scale)
{
// float h, s, v;
float cmin, cmax, diff;
// scale input value to [0..1]
rgb[0] /= scale; rgb[1] /= scale; rgb[2] /= scale;
hsv[0] = hsv[1] = hsv[2] = -12345.6789;
cmin = mini3f(rgb[0], rgb[1], rgb[2]);
cmax = maxi3f(rgb[0], rgb[1], rgb[2]);
diff = cmax - cmin;
if (pseudoeq(cmax, cmin)) hsv[0] = 0.0;
else if (pseudoeq(cmax, rgb[0]))
hsv[0] = fmod((60 * ((rgb[1] - rgb[2]) / diff) + 360), 360.0);
else if (pseudoeq(cmax, rgb[1]))
hsv[0] = fmod((60 * ((rgb[2] - rgb[0]) / diff) + 120), 360.0);
else if (pseudoeq(cmax, rgb[2]))
hsv[0] = fmod((60 * ((rgb[0] - rgb[1]) / diff) + 240), 360.0);
if (pseudoeq(cmax, 0.0)) hsv[1] = 0.0;
else hsv[1] = (diff / cmax) / 100.0;
hsv[2] = cmax * 100.0; /* WHAT THE FUCK ? */
#if DEBUG_LEVEL
fprintf(stderr, "cmin/cmax %f %f\n", cmin, cmax);
#endif
return 0;
}
/* --------------------------------------------------------------------- */
int fimg_hsv2rgb(float hsv[3], float rgb[3], float scale)
{
float hh, ff, p, q, t;
long i;
if(hsv[1] <= 0.0) { // < is bogus, just shuts up warnings
rgb[0] = rgb[1] = rgb[2] = hsv[2];
return 0;
}
hh = hsv[0];
if(hh >= 360.0) hh = 0.0;
hh /= 60.0;
i = (long)hh;
ff = hh - i;
p = hsv[2] * (1.0 - hsv[1]);
q = hsv[2] * (1.0 - (hsv[1] * ff));
t = hsv[2] * (1.0 - (hsv[1] * (1.0 - ff)));
switch(i) {
case 0:
rgb[0] = hsv[2]; rgb[1] = t; rgb[2] = p;
break;
case 1:
rgb[0] = q; rgb[1] = hsv[2]; rgb[2] = p;
break;
case 2:
rgb[0] = p; rgb[1] = hsv[2]; rgb[2] = t;
break;
case 3:
rgb[0] = p; rgb[1] = q; rgb[2] = hsv[2];
break;
case 4:
rgb[0] = t; rgb[1] = p; rgb[2] = hsv[2];
break;
case 5:
default:
rgb[0] = hsv[2]; rgb[1] = p; rgb[2] = q;
break;
}
return 0;
}
/* --------------------------------------------------------------------- */
/*
* expect garbage !
*/
int fimg_essai_hsv(char *fname)
{
float colors[3], values[3], newcols[3];
int foo, r, g, b;
#define INC 16
for (r=0; r<255; r+=INC) {
for (g=0; g<255; g+=INC) {
for (b=0; b<255; b+=INC) {
printf("%4d %4d %4d ", r, g, b);
colors[0] = (float)r;
colors[1] = (float)g;
colors[2] = (float)b;
foo = fimg_rgb2hsv(colors, values, 255.0);
if (foo) {
fprintf(stderr, "%s: err %d in rgv->hsv\n", __func__, foo);
exit(1);
}
printf(" %8.4f %8.4f %8.4f ",
values[0], values[1], values[2]);
foo = fimg_hsv2rgb(values, newcols, 255.0);
if (foo) {
fprintf(stderr, "%s: err %d in hsv->rgb\n", __func__, foo);
exit(1);
}
printf(" %8.4f %8.4f %8.4f\n",
newcols[0], newcols[1], newcols[2]);
}
}
}
return -1;
}
/* --------------------------------------------------------------------- */