summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-03-01 23:43:56 +0000
committerTavian Barnes <tavianator@gmail.com>2009-03-01 23:43:56 +0000
commit5ac6158f8ff999d4db18fb805c02b5c733e75ddb (patch)
treec595048bae6b2860ef5264e1096eaac8c25b7f52
parentef4dbe789201bcb92596a67eb3fb3f3f03a09b49 (diff)
downloaddimension-5ac6158f8ff999d4db18fb805c02b5c733e75ddb.tar.xz
Use CIE xyY internally, rather than CIE XYZ.
-rw-r--r--libdimension/canvas.c57
-rw-r--r--libdimension/dimension/canvas.h4
-rw-r--r--libdimension/dimension/color.h15
3 files changed, 44 insertions, 32 deletions
diff --git a/libdimension/canvas.c b/libdimension/canvas.c
index c730b53..4e3f89f 100644
--- a/libdimension/canvas.c
+++ b/libdimension/canvas.c
@@ -27,10 +27,16 @@
dmnsn_pixel
dmnsn_pixel_from_color(dmnsn_color color)
{
+ double X, Y, Z; /* CIE XYZ values */
double Rlinear, Glinear, Blinear; /* Linear RGB values - no gamma */
double R, G, B; /* sRGB values */
dmnsn_pixel pixel;
+ /* Convert from CIE xyY to CIE XYZ */
+ Y = color.Y;
+ X = Y*color.x/color.y;
+ Z = Y*(1.0 - color.x - color.y)/color.y;
+
/*
* First, the linear conversion. Expressed as matrix multiplication, it looks
* like this:
@@ -39,9 +45,9 @@ dmnsn_pixel_from_color(dmnsn_color color)
* [Glinear] = [-0.9692 1.8760 0.0416]*[Y]
* [Blinear] [ 0.0556 -0.2040 1.0570] [Z]
*/
- Rlinear = 3.2410*color.X - 1.5374*color.Y - 0.4986*color.Z;
- Glinear = -0.9692*color.X + 1.8760*color.Y + 0.0416*color.Z;
- Blinear = 0.0556*color.X - 0.2040*color.Y + 1.0570*color.Z;
+ Rlinear = 3.2410*X - 1.5374*Y - 0.4986*Z;
+ Glinear = -0.9692*X + 1.8760*Y + 0.0416*Z;
+ Blinear = 0.0556*X - 0.2040*Y + 1.0570*Z;
/*
* If C represents R, G, and B, then the sRGB values are now found as follows:
@@ -71,41 +77,41 @@ dmnsn_pixel_from_color(dmnsn_color color)
/* Now we go from unlimited to limited light, saturating at UINT16_MAX */
- if (R < 0) {
- pixel.r = 0;
- } else if (R > 1) {
+ if (R < 0.0) {
+ pixel.r = 0.0;
+ } else if (R > 1.0) {
pixel.r = UINT16_MAX;
} else {
pixel.r = UINT16_MAX*R;
}
- if (G < 0) {
- pixel.g = 0;
- } else if (G > 1) {
+ if (G < 0.0) {
+ pixel.g = 0.0;
+ } else if (G > 1.0) {
pixel.g = UINT16_MAX;
} else {
pixel.g = UINT16_MAX*G;
}
- if (B < 0) {
- pixel.b = 0;
- } else if (B > 1) {
+ if (B < 0.0) {
+ pixel.b = 0.0;
+ } else if (B > 1.0) {
pixel.b = UINT16_MAX;
} else {
pixel.b = UINT16_MAX*B;
}
- if (color.alpha < 0) {
- pixel.a = 0;
- } else if (color.alpha > 1) {
+ if (color.filter < 0.0) {
+ pixel.a = 0.0;
+ } else if (color.filter > 1.0) {
pixel.a = UINT16_MAX;
} else {
- pixel.a = UINT16_MAX*color.alpha;
+ pixel.a = UINT16_MAX*color.filter;
}
- if (color.trans < 0) {
- pixel.t = 0;
- } else if (color.trans > 1) {
+ if (color.trans < 0.0) {
+ pixel.t = 0.0;
+ } else if (color.trans > 1.0) {
pixel.t = UINT16_MAX;
} else {
pixel.t = UINT16_MAX*color.trans;
@@ -119,6 +125,7 @@ dmnsn_color_from_pixel(dmnsn_pixel pixel)
{
double R, G, B; /* sRGB values */
double Rlinear, Glinear, Blinear; /* Linear RGB values - no gamma */
+ double X, Y, Z; /* CIE XYZ values */
dmnsn_color color;
/* Conversion back to unlimited light */
@@ -162,11 +169,15 @@ dmnsn_color_from_pixel(dmnsn_pixel pixel)
* [X] [0.0193 0.1192 0.9505] [Blinear]
*/
- color.X = 0.4124*Rlinear + 0.3576*Glinear + 0.1805*Blinear;
- color.Y = 0.2126*Rlinear + 0.7152*Glinear + 0.0722*Blinear;
- color.Z = 0.0193*Rlinear + 0.1192*Glinear + 0.9505*Blinear;
+ X = 0.4124*Rlinear + 0.3576*Glinear + 0.1805*Blinear;
+ Y = 0.2126*Rlinear + 0.7152*Glinear + 0.0722*Blinear;
+ Z = 0.0193*Rlinear + 0.1192*Glinear + 0.9505*Blinear;
- color.alpha = ((double)pixel.a)/UINT16_MAX;
+ /* Now convert to CIE xyY colorspace */
+ color.x = X/(X + Y + Z);
+ color.y = Y/(X + Y + Z);
+ color.Y = Y;
+ color.filter = ((double)pixel.a)/UINT16_MAX;
color.trans = ((double)pixel.t)/UINT16_MAX;
return color;
diff --git a/libdimension/dimension/canvas.h b/libdimension/dimension/canvas.h
index 251c64a..8959e12 100644
--- a/libdimension/dimension/canvas.h
+++ b/libdimension/dimension/canvas.h
@@ -27,8 +27,8 @@
/* 48-bit sRGB color for pixels. */
typedef struct {
- uint16_t r, g, b;
- uint16_t a, t;
+ uint16_t r, g, b; /* Red, green, blue */
+ uint16_t a, t; /* Filtered transparancy, normal transparancy */
} dmnsn_pixel;
dmnsn_pixel dmnsn_pixel_from_color(dmnsn_color color);
diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h
index 1f4a42e..34668e3 100644
--- a/libdimension/dimension/color.h
+++ b/libdimension/dimension/color.h
@@ -29,14 +29,15 @@
extern "C" {
#endif
-/* CIE 1931 XYZ color. */
+/* CIE 1931 xyY color. */
typedef struct {
- double X, Y, Z; /* X, Y, and Z are the tristimulus values of a color in CIE
- 1931 XYZ color space. We use an unlimited light model
- here, where the range of X, Y, and Z are unbounded >= 0. */
- double alpha, trans; /* Alpha transparancy only lets light of this color
- through; regular transparancy lets all colors
- through */
+ double x, y, Y; /* x and y are chromaticity coordinates, and Y is luminance,
+ in the CIE 1931 xyZ color space. We use an unlimited light
+ model, so x,y in [0, 1] and Y >= 0, with 1 = diffuse
+ white */
+ double filter, trans; /* Filter transparancy only lets light of this color
+ through; regular transparancy lets all colors
+ through */
} dmnsn_color;
#ifdef __cplusplus