add HSV support and convertion helper functions

This commit is contained in:
jacekpoz 2024-08-14 00:08:59 +02:00
parent 60cc86ec41
commit a06c109665
Signed by: poz
SSH key fingerprint: SHA256:JyLeVWE4bF3tDnFeUpUaJsPsNlJyBldDGV/dIKSLyN8
2 changed files with 131 additions and 13 deletions

View file

@ -14,19 +14,6 @@ typedef union {
};
} PtkRGB;
typedef union {
struct {
float h;
float s;
float v;
};
struct {
float hue;
float saturation;
float value;
};
} PtkHSV;
typedef union {
struct {
float r;
@ -42,6 +29,20 @@ typedef union {
};
} PtkRGBA;
// all values in range [0.0, 360.0]
typedef union {
struct {
float h;
float s;
float v;
};
struct {
float hue;
float saturation;
float value;
};
} PtkHSV;
typedef union {
struct {
float h;
@ -57,4 +58,10 @@ typedef union {
};
} PtkHSVA;
PtkHSV ptk_rgb_to_hsv(const PtkRGB rgb);
PtkRGB ptk_hsv_to_rgb(const PtkHSV hsv);
PtkHSVA ptk_rgba_to_hsva(const PtkRGBA rgba);
PtkRGBA ptk_hsva_to_rgba(const PtkHSVA hsva);
#endif // PTK_PTK_COLOR_H_

111
src/ptk_color.c Normal file
View file

@ -0,0 +1,111 @@
#include <ptk_color.h>
#include <math.h>
// https://github.com/raysan5/raylib/blob/65c40035/src/rtextures.c#L4933
PtkHSV ptk_rgb_to_hsv(const PtkRGB rgb) {
PtkHSV hsv = {0};
float min, max;
min = rgb.r < rgb.g ? rgb.r : rgb.g;
min = min < rgb.b ? min : rgb.b;
max = rgb.r > rgb.g ? rgb.r : rgb.g;
max = max > rgb.b ? max : rgb.b;
hsv.v = max;
const float delta = max - min;
if (delta < 0.00001f) {
hsv.s = 0.0f;
hsv.h = 0.0f;
return hsv;
}
if (max > 0.0f) {
hsv.s = delta / max;
} else {
hsv.s = 0.0f;
hsv.h = NAN;
}
if (rgb.r >= max) {
hsv.h = (rgb.g - rgb.b) / delta;
} else {
if (rgb.g >= max) {
hsv.h = 2.0f + (rgb.b - rgb.r) / delta;
} else {
hsv.h = 4.0f + (rgb.r - rgb.g) / delta;
}
}
hsv.h *= 60.0f;
if (hsv.h < 0.0f) {
hsv.h += 360.0f;
}
return hsv;
}
// https://github.com/raysan5/raylib/blob/65c40035/src/rtextures.c#L4988
PtkRGB ptk_hsv_to_rgb(const PtkHSV hsv) {
PtkRGB rgb = {0};
const float s = hsv.s / 360.0f;
const float v = hsv.v / 360.0f;
float k = fmodf(5.0f + hsv.h / 60.0f, 6);
float t = 4.0f - k;
k = t < k ? t : k;
k = k < 1 ? k : 1;
k = k > 0 ? k : 0;
rgb.r = v - v * s * k;
k = fmodf(3.0f + hsv.h / 60.0f, 6);
t = 4.0f - k;
k = t < k ? t : k;
k = k < 1 ? k : 1;
k = k > 0 ? k : 0;
rgb.g = v - v * s * k;
k = fmodf(1.0f + hsv.h / 60.0f, 6);
t = 4.0f - k;
k = t < k ? t : k;
k = k < 1 ? k : 1;
k = k > 0 ? k : 0;
rgb.b = v - v * s * k;
return rgb;
}
PtkHSVA ptk_rgba_to_hsva(const PtkRGBA rgba) {
PtkHSV hsv = ptk_rgb_to_hsv((PtkRGB){
.r = rgba.r,
.g = rgba.g,
.b = rgba.b
});
return (PtkHSVA){
.h = hsv.h,
.s = hsv.s,
.v = hsv.v,
.a = rgba.a * 360.0f,
};
}
PtkRGBA ptk_hsva_to_rgba(const PtkHSVA hsva) {
PtkRGB rgb = ptk_hsv_to_rgb((PtkHSV){
.h = hsva.h,
.s = hsva.s,
.v = hsva.v,
});
return (PtkRGBA){
.r = rgb.r,
.g = rgb.g,
.b = rgb.b,
.a = hsva.a / 360.0f,
};
}