328 lines
4.9 KiB
C
328 lines
4.9 KiB
C
#include "colours.h"
|
|
|
|
#include <tgmath.h>
|
|
|
|
struct ColourRGB CMYKtoRGB(struct ColourCMYK cmyk)
|
|
{
|
|
struct ColourRGB result;
|
|
|
|
result.r = (1.0 - cmyk.c) * (1.0 - cmyk.k);
|
|
result.g = (1.0 - cmyk.m) * (1.0 - cmyk.k);
|
|
result.b = (1.0 - cmyk.y) * (1.0 - cmyk.k);
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourRGB HSVtoRGB(struct ColourHSV hsv)
|
|
{
|
|
struct ColourRGB result;
|
|
double c;
|
|
double x;
|
|
double m;
|
|
|
|
c = hsv.s * hsv.v;
|
|
x = c * (1.0 - fabs(fmod(hsv.h / 60.0, 2) - 1.0));
|
|
m = hsv.v - c;
|
|
|
|
int angle = hsv.h / 60;
|
|
switch (angle)
|
|
{
|
|
// 0 - 60
|
|
case 6:
|
|
case 0:
|
|
result.r = c;
|
|
result.g = x;
|
|
result.b = 0;
|
|
break;
|
|
// 60 - 120
|
|
case 1:
|
|
result.r = x;
|
|
result.g = c;
|
|
result.b = 0;
|
|
break;
|
|
// 120 - 180
|
|
case 2:
|
|
result.r = 0;
|
|
result.g = c;
|
|
result.b = x;
|
|
break;
|
|
// 180 - 240
|
|
case 3:
|
|
result.r = 0;
|
|
result.g = x;
|
|
result.b = c;
|
|
break;
|
|
// 240 - 300
|
|
case 4:
|
|
result.r = x;
|
|
result.g = 0;
|
|
result.b = c;
|
|
break;
|
|
// 300 - 360
|
|
case 5:
|
|
result.r = c;
|
|
result.g = 0;
|
|
result.b = x;
|
|
break;
|
|
// Should never happen
|
|
default:
|
|
result.r = 0;
|
|
result.g = 0;
|
|
result.b = 0;
|
|
break;
|
|
}
|
|
|
|
result.r += m;
|
|
result.g += m;
|
|
result.b += m;
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourRGB HSLtoRGB(struct ColourHSL hsl)
|
|
{
|
|
struct ColourRGB result;
|
|
double c;
|
|
double x;
|
|
double m;
|
|
|
|
c = hsl.s * (1.0 - fabs(2 * hsl.l - 1));
|
|
x = c * (1.0 - fabs(fmod(hsl.h / 60.0, 2) - 1.0));
|
|
m = hsl.l - c/2;
|
|
|
|
int angle = hsl.h / 60;
|
|
switch (angle)
|
|
{
|
|
// 0 - 60
|
|
case 6:
|
|
case 0:
|
|
result.r = c;
|
|
result.g = x;
|
|
result.b = 0;
|
|
break;
|
|
// 60 - 120
|
|
case 1:
|
|
result.r = x;
|
|
result.g = c;
|
|
result.b = 0;
|
|
break;
|
|
// 120 - 180
|
|
case 2:
|
|
result.r = 0;
|
|
result.g = c;
|
|
result.b = x;
|
|
break;
|
|
// 180 - 240
|
|
case 3:
|
|
result.r = 0;
|
|
result.g = x;
|
|
result.b = c;
|
|
break;
|
|
// 240 - 300
|
|
case 4:
|
|
result.r = x;
|
|
result.g = 0;
|
|
result.b = c;
|
|
break;
|
|
// 300 - 360
|
|
case 5:
|
|
result.r = c;
|
|
result.g = 0;
|
|
result.b = x;
|
|
break;
|
|
// Should never happen
|
|
default:
|
|
result.r = 0;
|
|
result.g = 0;
|
|
result.b = 0;
|
|
break;
|
|
}
|
|
|
|
result.r += m;
|
|
result.g += m;
|
|
result.b += m;
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourCMYK RGBtoCMYK(struct ColourRGB rgb)
|
|
{
|
|
struct ColourCMYK result;
|
|
|
|
// max(r,g,b)
|
|
result.k = rgb.r > rgb.g ? rgb.r : rgb.g;
|
|
result.k = rgb.b > result.k ? rgb.b : result.k;
|
|
result.k = 1.0 - result.k;
|
|
|
|
if (1.0 == result.k)
|
|
{
|
|
result.c = 0;
|
|
result.m = 0;
|
|
result.y = 0;
|
|
}
|
|
else
|
|
{
|
|
result.c = (1.0 - rgb.r - result.k) / (1.0 - result.k);
|
|
result.m = (1.0 - rgb.g - result.k) / (1.0 - result.k);
|
|
result.y = (1.0 - rgb.b - result.k) / (1.0 - result.k);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourCMYK HSVtoCMYK(struct ColourHSV hsv)
|
|
{
|
|
struct ColourCMYK result;
|
|
|
|
result = RGBtoCMYK(HSVtoRGB(hsv));
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourCMYK HSLtoCMYK(struct ColourHSL hsl)
|
|
{
|
|
struct ColourCMYK result;
|
|
|
|
result = RGBtoCMYK(HSLtoRGB(hsl));
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourHSV RGBtoHSV(struct ColourRGB rgb)
|
|
{
|
|
struct ColourHSV result;
|
|
|
|
double c_max;
|
|
double c_min;
|
|
double delta;
|
|
|
|
// max(r,g,b)
|
|
c_max = rgb.r > rgb.g ? rgb.r : rgb.g;
|
|
c_max = rgb.b > c_max ? rgb.b : c_max;
|
|
|
|
// min(r,g,b)
|
|
c_min = rgb.r < rgb.g ? rgb.r : rgb.g;
|
|
c_min = rgb.b < c_min ? rgb.b : c_min;
|
|
|
|
delta = c_max - c_min;
|
|
|
|
if (delta > 0)
|
|
{
|
|
if (c_max == rgb.r)
|
|
{
|
|
result.h = 60 * fmod((rgb.g - rgb.b) / delta, 6);
|
|
}
|
|
else if (c_max == rgb.g)
|
|
{
|
|
result.h = 60 * ((rgb.b - rgb.r) / delta + 2);
|
|
}
|
|
else
|
|
{
|
|
result.h = 60 * ((rgb.r - rgb.g) / delta + 4);
|
|
}
|
|
|
|
result.v = c_max;
|
|
result.s = delta / result.v;
|
|
}
|
|
else
|
|
{
|
|
result.h = 0;
|
|
result.s = 0;
|
|
result.v = c_max;
|
|
}
|
|
|
|
if (result.h < 0)
|
|
{
|
|
result.h += 360;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourHSV CMYKtoHSV(struct ColourCMYK cmyk)
|
|
{
|
|
struct ColourHSV result;
|
|
|
|
result = RGBtoHSV(CMYKtoRGB(cmyk));
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourHSV HSLtoHSV(struct ColourHSL hsl)
|
|
{
|
|
struct ColourHSV result;
|
|
|
|
result = RGBtoHSV(HSLtoRGB(hsl));
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourHSL RGBtoHSL(struct ColourRGB rgb)
|
|
{
|
|
struct ColourHSL result;
|
|
|
|
double c_max;
|
|
double c_min;
|
|
double delta;
|
|
|
|
// max(r,g,b)
|
|
c_max = rgb.r > rgb.g ? rgb.r : rgb.g;
|
|
c_max = rgb.b > c_max ? rgb.b : c_max;
|
|
|
|
// min(r,g,b)
|
|
c_min = rgb.r < rgb.g ? rgb.r : rgb.g;
|
|
c_min = rgb.b < c_min ? rgb.b : c_min;
|
|
|
|
delta = c_max - c_min;
|
|
|
|
if (delta > 0)
|
|
{
|
|
if (c_max == rgb.r)
|
|
{
|
|
result.h = 60 * fmod((rgb.g - rgb.b) / delta, 6);
|
|
}
|
|
else if (c_max == rgb.g)
|
|
{
|
|
result.h = 60 * ((rgb.b - rgb.r) / delta + 2);
|
|
}
|
|
else
|
|
{
|
|
result.h = 60 * ((rgb.r - rgb.g) / delta + 4);
|
|
}
|
|
|
|
result.l = (c_max + c_min) / 2;
|
|
result.s = delta / (1.0 - fabs(2 * result.l - 1.0));
|
|
}
|
|
else
|
|
{
|
|
result.h = 0;
|
|
result.s = 0;
|
|
result.l = (c_max + c_min) / 2;
|
|
}
|
|
|
|
if (result.h < 0)
|
|
{
|
|
result.h += 360;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourHSL CMYKtoHSL(struct ColourCMYK cmyk)
|
|
{
|
|
struct ColourHSL result;
|
|
|
|
result = RGBtoHSL(CMYKtoRGB(cmyk));
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourHSL HSVtoHSL(struct ColourHSV hsv)
|
|
{
|
|
struct ColourHSL result;
|
|
|
|
result = RGBtoHSL(HSVtoRGB(hsv));
|
|
|
|
return result;
|
|
}
|