00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "color.h"
00025
00026 using namespace lux;
00027
00028 namespace lux
00029 {
00030
00031 static float determinent(const float matrix[3][3])
00032 {
00033 float temp;
00034 temp = matrix[0][0] * matrix[1][1] * matrix[2][2];
00035 temp -= matrix[0][0] * matrix[1][2] * matrix[2][1];
00036 temp -= matrix[1][0] * matrix[0][1] * matrix[2][2];
00037 temp += matrix[1][0] * matrix[0][2] * matrix[2][1];
00038 temp += matrix[2][0] * matrix[0][1] * matrix[1][2];
00039 temp -= matrix[2][0] * matrix[0][2] * matrix[1][1];
00040 return temp;
00041 }
00042 static void inverse(float matrix[3][3])
00043 {
00044 float det = determinent(matrix);
00045 if (det == 0.f)
00046 return;
00047 float a = matrix[0][0], b = matrix[0][1], c = matrix[0][2],
00048 d = matrix[1][0], e = matrix[1][1], f = matrix[1][2],
00049 g = matrix[2][0], h = matrix[2][1], i = matrix[2][2];
00050
00051 matrix[0][0] = (e * i - f * h) / det;
00052 matrix[0][1] = (c * h - b * i) / det;
00053 matrix[0][2] = (b * f - c * e) / det;
00054 matrix[1][0] = (f * g - d * i) / det;
00055 matrix[1][1] = (a * i - c * g) / det;
00056 matrix[1][2] = (c * d - a * f) / det;
00057 matrix[2][0] = (d * h - e * g) / det;
00058 matrix[2][1] = (b * g - a * h) / det;
00059 matrix[2][2] = (a * e - b * d) / det;
00060 }
00061 static void multiply(const float matrix[3][3], const float vector[3], float result[3])
00062 {
00063 result[0] = matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2];
00064 result[1] = matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2];
00065 result[2] = matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2];
00066 }
00067 static void multiply(const float a[3][3], const float b[3][3], float result[3][3])
00068 {
00069 result[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0];
00070 result[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1];
00071 result[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2];
00072 result[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0];
00073 result[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1];
00074 result[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2];
00075 result[2][0] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0];
00076 result[2][1] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1];
00077 result[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2];
00078 }
00079 static float dot(const float a[3], const float b[3])
00080 {
00081 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
00082 }
00083
00100 ColorSystem::ColorSystem(float xR, float yR, float xG, float yG, float xB, float yB,
00101 float xW, float yW, float lum)
00102 : xRed(xR), yRed(yR), xGreen(xG), yGreen(yG), xBlue(xB), yBlue(yB),
00103 xWhite(xW), yWhite(yW), luminance(lum)
00104 {
00105 float red[3] = {xRed / yRed, 1.f, (1.f - xRed - yRed) / yRed};
00106 float green[3] = {xGreen / yGreen, 1.f, (1.f - xGreen - yGreen) / yGreen};
00107 float blue[3] = {xBlue / yBlue, 1.f, (1.f - xBlue - yBlue) / yBlue};
00108 float white[3] = {xWhite / yWhite, 1.f, (1.f - xWhite - yWhite) / yWhite};
00109 float rgb[3][3];
00110 rgb[0][0] = red[0]; rgb[1][0] = red[1]; rgb[2][0] = red[2];
00111 rgb[0][1] = green[0]; rgb[1][1] = green[1]; rgb[2][1] = green[2];
00112 rgb[0][2] = blue[0]; rgb[1][2] = blue[1]; rgb[2][2] = blue[2];
00113 inverse(rgb);
00114 float y[3];
00115 multiply(rgb, white, y);
00116 float x[3] = {y[0] * red[0], y[1] * green[0], y[2] * blue[0]};
00117 float z[3] = {y[0] * red[2], y[1] * green[2], y[2] * blue[2]};
00118 rgb[0][0] = x[0] + white[0]; rgb[1][0] = x[1] + white[0]; rgb[2][0] = x[2] + white[0];
00119 rgb[0][1] = y[0] + white[1]; rgb[1][1] = y[1] + white[1]; rgb[2][1] = y[2] + white[1];
00120 rgb[0][2] = z[0] + white[2]; rgb[1][2] = z[1] + white[2]; rgb[2][2] = z[2] + white[2];
00121 float matrix[3][3];
00122 matrix[0][0] = (dot(x, x) + white[0] * white[0]) * luminance;
00123 matrix[1][0] = (dot(x, y) + white[1] * white[0]) * luminance;
00124 matrix[2][0] = (dot(x, z) + white[2] * white[0]) * luminance;
00125 matrix[0][1] = (dot(y, x) + white[0] * white[1]) * luminance;
00126 matrix[1][1] = (dot(y, y) + white[1] * white[1]) * luminance;
00127 matrix[2][1] = (dot(y, z) + white[2] * white[1]) * luminance;
00128 matrix[0][2] = (dot(z, x) + white[0] * white[2]) * luminance;
00129 matrix[1][2] = (dot(z, y) + white[1] * white[2]) * luminance;
00130 matrix[2][2] = (dot(z, z) + white[2] * white[2]) * luminance;
00131 inverse(matrix);
00132
00133 multiply(rgb, matrix, conversion);
00134 }
00135
00143 static inline bool InsideGamut(const RGBColor &color)
00144 {
00145 return color.c[0] >= 0.f && color.c[1] >= 0.f && color.c[2] >= 0.f;
00146 }
00147
00167 bool ColorSystem::Constrain(const XYZColor &xyz, RGBColor &rgb) const
00168 {
00169
00170 if (!InsideGamut(rgb)) {
00171 float parameter;
00172 float lum = xyz.c[1] / luminance;
00173
00174
00175
00176
00177 if (rgb.c[0] < rgb.c[1] && rgb.c[0] < rgb.c[2]) {
00178 parameter = lum / (lum - rgb.c[0]);
00179 } else if (rgb.c[1] < rgb.c[2]) {
00180 parameter = lum / (lum - rgb.c[1]);
00181 } else {
00182 parameter = lum / (lum - rgb.c[2]);
00183 }
00184
00185
00186 rgb = Lerp(parameter, RGBColor(lum), rgb);
00187 return true;
00188 }
00189 return false;
00190 }
00191
00192 }
00193