|
18 | 18 |
|
19 | 19 | #include <assert.h>
|
20 | 20 | #include <math.h>
|
21 |
| -#include <stdio.h> |
22 |
| -#include <stdlib.h> |
23 | 21 |
|
24 | 22 | #include "cpp/cam/hct_solver.h"
|
25 | 23 | #include "cpp/cam/viewing_conditions.h"
|
@@ -206,4 +204,60 @@ Argb IntFromHcl(double hue, double chroma, double lstar) {
|
206 | 204 | return SolveToInt(hue, chroma, lstar);
|
207 | 205 | }
|
208 | 206 |
|
| 207 | +Cam CamFromXyzAndViewingConditions( |
| 208 | + double x, double y, double z, const ViewingConditions &viewing_conditions) { |
| 209 | + // Convert XYZ to 'cone'/'rgb' responses |
| 210 | + double r_c = 0.401288 * x + 0.650173 * y - 0.051461 * z; |
| 211 | + double g_c = -0.250268 * x + 1.204414 * y + 0.045854 * z; |
| 212 | + double b_c = -0.002079 * x + 0.048952 * y + 0.953127 * z; |
| 213 | + |
| 214 | + // Discount illuminant. |
| 215 | + double r_d = viewing_conditions.rgb_d[0] * r_c; |
| 216 | + double g_d = viewing_conditions.rgb_d[1] * g_c; |
| 217 | + double b_d = viewing_conditions.rgb_d[2] * b_c; |
| 218 | + |
| 219 | + // Chromatic adaptation. |
| 220 | + double r_af = pow(viewing_conditions.fl * fabs(r_d) / 100.0, 0.42); |
| 221 | + double g_af = pow(viewing_conditions.fl * fabs(g_d) / 100.0, 0.42); |
| 222 | + double b_af = pow(viewing_conditions.fl * fabs(b_d) / 100.0, 0.42); |
| 223 | + double r_a = Signum(r_d) * 400.0 * r_af / (r_af + 27.13); |
| 224 | + double g_a = Signum(g_d) * 400.0 * g_af / (g_af + 27.13); |
| 225 | + double b_a = Signum(b_d) * 400.0 * b_af / (b_af + 27.13); |
| 226 | + |
| 227 | + // Redness-greenness |
| 228 | + double a = (11.0 * r_a + -12.0 * g_a + b_a) / 11.0; |
| 229 | + double b = (r_a + g_a - 2.0 * b_a) / 9.0; |
| 230 | + double u = (20.0 * r_a + 20.0 * g_a + 21.0 * b_a) / 20.0; |
| 231 | + double p2 = (40.0 * r_a + 20.0 * g_a + b_a) / 20.0; |
| 232 | + |
| 233 | + double radians = atan2(b, a); |
| 234 | + double degrees = radians * 180.0 / kPi; |
| 235 | + double hue = SanitizeDegreesDouble(degrees); |
| 236 | + double hue_radians = hue * kPi / 180.0; |
| 237 | + double ac = p2 * viewing_conditions.nbb; |
| 238 | + |
| 239 | + double j = 100.0 * pow(ac / viewing_conditions.aw, |
| 240 | + viewing_conditions.c * viewing_conditions.z); |
| 241 | + double q = (4.0 / viewing_conditions.c) * sqrt(j / 100.0) * |
| 242 | + (viewing_conditions.aw + 4.0) * viewing_conditions.fl_root; |
| 243 | + double hue_prime = hue < 20.14 ? hue + 360 : hue; |
| 244 | + double e_hue = 0.25 * (cos(hue_prime * kPi / 180.0 + 2.0) + 3.8); |
| 245 | + double p1 = |
| 246 | + 50000.0 / 13.0 * e_hue * viewing_conditions.n_c * viewing_conditions.ncb; |
| 247 | + double t = p1 * sqrt(a * a + b * b) / (u + 0.305); |
| 248 | + double alpha = |
| 249 | + pow(t, 0.9) * |
| 250 | + pow(1.64 - pow(0.29, viewing_conditions.background_y_to_white_point_y), |
| 251 | + 0.73); |
| 252 | + double c = alpha * sqrt(j / 100.0); |
| 253 | + double m = c * viewing_conditions.fl_root; |
| 254 | + double s = 50.0 * sqrt((alpha * viewing_conditions.c) / |
| 255 | + (viewing_conditions.aw + 4.0)); |
| 256 | + double jstar = (1.0 + 100.0 * 0.007) * j / (1.0 + 0.007 * j); |
| 257 | + double mstar = 1.0 / 0.0228 * log(1.0 + 0.0228 * m); |
| 258 | + double astar = mstar * cos(hue_radians); |
| 259 | + double bstar = mstar * sin(hue_radians); |
| 260 | + return {hue, c, j, q, m, s, jstar, astar, bstar}; |
| 261 | +} |
| 262 | + |
209 | 263 | } // namespace material_color_utilities
|
0 commit comments