Skip to content

Commit

Permalink
simplify rgb to hsv conversion
Browse files Browse the repository at this point in the history
By inlining some values, the starting hue calculation can be reduced from using three subtractions and two divisions to using one subtraction and one division.
"fmod(n+1,1)" can be replaced with "n - floor(n)" due to the second parameter being 1.
The saturation calculation can be done without floating point values.
The "CLIP8"s are unnecessary because the values are already in the correct range.
  • Loading branch information
Yay295 committed Oct 12, 2024
1 parent dc37515 commit 6b8a97a
Showing 1 changed file with 32 additions and 25 deletions.
57 changes: 32 additions & 25 deletions src/libImaging/Convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,40 +310,46 @@ rgb2bgr24(UINT8 *out, const UINT8 *in, int xsize) {
}

static void
rgb2hsv_row(UINT8 *out, const UINT8 *in) { // following colorsys.py
float h, s, rc, gc, bc, cr;
UINT8 maxc, minc;
UINT8 r, g, b;
UINT8 uh, us, uv;

r = in[0];
g = in[1];
b = in[2];
maxc = MAX(r, MAX(g, b));
minc = MIN(r, MIN(g, b));
uv = maxc;
rgb2hsv_row(UINT8 *out, const UINT8 *in) {
// based on Python's colorsys module

const UINT8 r = in[0];
const UINT8 g = in[1];
const UINT8 b = in[2];

const UINT8 maxc = MAX(r, MAX(g, b));
const UINT8 minc = MIN(r, MIN(g, b));

UINT8 uh, us;
const UINT8 uv = maxc;

if (minc == maxc) {
uh = 0;
us = 0;
} else {
cr = (float)(maxc - minc);
s = cr / (float)maxc;
rc = ((float)(maxc - r)) / cr;
gc = ((float)(maxc - g)) / cr;
bc = ((float)(maxc - b)) / cr;
const UINT8 color_range = maxc - minc;
double h;

const double cr = (double)color_range;
if (r == maxc) {
h = bc - gc;
h = (g - b) / cr;
} else if (g == maxc) {
h = 2.0 + rc - bc;
h = 2.0 + (b - r) / cr;
} else {
h = 4.0 + gc - rc;
h = 4.0 + (r - g) / cr;
}
// incorrect hue happens if h/6 is negative.
h = fmod((h / 6.0 + 1.0), 1.0);

uh = (UINT8)CLIP8((int)(h * 255.0));
us = (UINT8)CLIP8((int)(s * 255.0));
// the modulus operator in Python does not exactly match
// the modulus operator or the fmod function in C
// https://stackoverflow.com/a/3883019/3878168
// "h = (h/6.0) % 1.0" in Python can be computed as:
h = h / 6.0;
h = h - floor(h);

uh = (UINT8)(255.0 * h);
us = 255 * color_range / maxc;
}

out[0] = uh;
out[1] = us;
out[2] = uv;
Expand All @@ -359,7 +365,8 @@ rgb2hsv(UINT8 *out, const UINT8 *in, int xsize) {
}

static void
hsv2rgb(UINT8 *out, const UINT8 *in, int xsize) { // following colorsys.py
hsv2rgb(UINT8 *out, const UINT8 *in, int xsize) {
// based on Python's colorsys module

int p, q, t;
UINT8 up, uq, ut;
Expand Down

0 comments on commit 6b8a97a

Please sign in to comment.