41 #include "compose.hpp"
50 using std::make_shared;
53 using std::shared_ptr;
54 using boost::optional;
58 static auto constexpr DCI_COEFFICIENT = 48.0 / 52.37;
63 std::shared_ptr<const OpenJPEGImage> xyz_image,
69 int const max_colour = pow (2, 16) - 1;
79 int* xyz_x = xyz_image->data (0);
80 int* xyz_y = xyz_image->data (1);
81 int* xyz_z = xyz_image->data (2);
83 double const * lut_in = conversion.out()->lut (12,
false);
84 double const * lut_out = conversion.in()->lut (16,
true);
85 boost::numeric::ublas::matrix<double>
const matrix = conversion.xyz_to_rgb ();
87 double fast_matrix[9] = {
88 matrix (0, 0), matrix (0, 1), matrix (0, 2),
89 matrix (1, 0), matrix (1, 1), matrix (1, 2),
90 matrix (2, 0), matrix (2, 1), matrix (2, 2)
93 int const height = xyz_image->size().height;
94 int const width = xyz_image->size().width;
96 for (
int y = 0; y < height; ++y) {
97 uint8_t* argb_line = argb;
98 for (
int x = 0; x < width; ++x) {
100 DCP_ASSERT (*xyz_x >= 0 && *xyz_y >= 0 && *xyz_z >= 0 && *xyz_x < 4096 && *xyz_y < 4096 && *xyz_z < 4096);
103 s.x = lut_in[*xyz_x++];
104 s.y = lut_in[*xyz_y++];
105 s.z = lut_in[*xyz_z++];
108 s.x /= DCI_COEFFICIENT;
109 s.y /= DCI_COEFFICIENT;
110 s.z /= DCI_COEFFICIENT;
113 d.r = ((s.x * fast_matrix[0]) + (s.y * fast_matrix[1]) + (s.z * fast_matrix[2]));
114 d.g = ((s.x * fast_matrix[3]) + (s.y * fast_matrix[4]) + (s.z * fast_matrix[5]));
115 d.b = ((s.x * fast_matrix[6]) + (s.y * fast_matrix[7]) + (s.z * fast_matrix[8]));
117 d.r = min (d.r, 1.0);
118 d.r = max (d.r, 0.0);
120 d.g = min (d.g, 1.0);
121 d.g = max (d.g, 0.0);
123 d.b = min (d.b, 1.0);
124 d.b = max (d.b, 0.0);
127 *argb_line++ = lut_out[lrint(d.b * max_colour)] * 0xff;
128 *argb_line++ = lut_out[lrint(d.g * max_colour)] * 0xff;
129 *argb_line++ = lut_out[lrint(d.r * max_colour)] * 0xff;
140 shared_ptr<const OpenJPEGImage> xyz_image,
144 optional<NoteHandler> note
156 int* xyz_x = xyz_image->data (0);
157 int* xyz_y = xyz_image->data (1);
158 int* xyz_z = xyz_image->data (2);
160 double const * lut_in = conversion.out()->lut (12,
false);
161 double const * lut_out = conversion.in()->lut (16,
true);
162 auto const matrix = conversion.xyz_to_rgb ();
164 double fast_matrix[9] = {
165 matrix (0, 0), matrix (0, 1), matrix (0, 2),
166 matrix (1, 0), matrix (1, 1), matrix (1, 2),
167 matrix (2, 0), matrix (2, 1), matrix (2, 2)
170 int const height = xyz_image->size().height;
171 int const width = xyz_image->size().width;
173 for (
int y = 0; y < height; ++y) {
174 auto rgb_line =
reinterpret_cast<uint16_t*
> (rgb + y * stride);
175 for (
int x = 0; x < width; ++x) {
181 if (cx < 0 || cx > 4095) {
183 note.get()(NoteType::NOTE, String::compose(
"XYZ value %1 out of range", cx));
185 cx = max (min (cx, 4095), 0);
188 if (cy < 0 || cy > 4095) {
190 note.get()(NoteType::NOTE, String::compose(
"XYZ value %1 out of range", cy));
192 cy = max (min (cy, 4095), 0);
195 if (cz < 0 || cz > 4095) {
197 note.get()(NoteType::NOTE, String::compose(
"XYZ value %1 out of range", cz));
199 cz = max (min (cz, 4095), 0);
208 s.x /= DCI_COEFFICIENT;
209 s.y /= DCI_COEFFICIENT;
210 s.z /= DCI_COEFFICIENT;
213 d.r = ((s.x * fast_matrix[0]) + (s.y * fast_matrix[1]) + (s.z * fast_matrix[2]));
214 d.g = ((s.x * fast_matrix[3]) + (s.y * fast_matrix[4]) + (s.z * fast_matrix[5]));
215 d.b = ((s.x * fast_matrix[6]) + (s.y * fast_matrix[7]) + (s.z * fast_matrix[8]));
217 d.r = min (d.r, 1.0);
218 d.r = max (d.r, 0.0);
220 d.g = min (d.g, 1.0);
221 d.g = max (d.g, 0.0);
223 d.b = min (d.b, 1.0);
224 d.b = max (d.b, 0.0);
226 *rgb_line++ = lrint(lut_out[lrint(d.r * 65535)] * 65535);
227 *rgb_line++ = lrint(lut_out[lrint(d.g * 65535)] * 65535);
228 *rgb_line++ = lrint(lut_out[lrint(d.b * 65535)] * 65535);
236 auto const rgb_to_xyz = conversion.rgb_to_xyz ();
237 auto const bradford = conversion.bradford ();
240 * DCI_COEFFICIENT * 65535;
242 * DCI_COEFFICIENT * 65535;
244 * DCI_COEFFICIENT * 65535;
246 * DCI_COEFFICIENT * 65535;
248 * DCI_COEFFICIENT * 65535;
250 * DCI_COEFFICIENT * 65535;
252 * DCI_COEFFICIENT * 65535;
254 * DCI_COEFFICIENT * 65535;
256 * DCI_COEFFICIENT * 65535;
260 shared_ptr<dcp::OpenJPEGImage>
266 optional<NoteHandler> note
269 auto xyz = make_shared<OpenJPEGImage>(size);
279 auto const * lut_in = conversion.in()->lut (12,
false);
280 auto const * lut_out = conversion.out()->lut (16,
true);
283 double fast_matrix[9];
287 int* xyz_x = xyz->data (0);
288 int* xyz_y = xyz->data (1);
289 int* xyz_z = xyz->data (2);
290 for (
int y = 0; y < size.height; ++y) {
291 auto p =
reinterpret_cast<uint16_t
const *
> (rgb + y * stride);
292 for (
int x = 0; x < size.width; ++x) {
295 s.r = lut_in[*p++ >> 4];
296 s.g = lut_in[*p++ >> 4];
297 s.b = lut_in[*p++ >> 4];
300 d.x = s.r * fast_matrix[0] + s.g * fast_matrix[1] + s.b * fast_matrix[2];
301 d.y = s.r * fast_matrix[3] + s.g * fast_matrix[4] + s.b * fast_matrix[5];
302 d.z = s.r * fast_matrix[6] + s.g * fast_matrix[7] + s.b * fast_matrix[8];
306 if (d.x < 0 || d.y < 0 || d.z < 0 || d.x > 65535 || d.y > 65535 || d.z > 65535) {
310 d.x = max (0.0, d.x);
311 d.y = max (0.0, d.y);
312 d.z = max (0.0, d.z);
313 d.x = min (65535.0, d.x);
314 d.y = min (65535.0, d.y);
315 d.z = min (65535.0, d.z);
318 *xyz_x++ = lrint (lut_out[lrint(d.x)] * 4095);
319 *xyz_y++ = lrint (lut_out[lrint(d.y)] * 4095);
320 *xyz_z++ = lrint (lut_out[lrint(d.z)] * 4095);
324 if (clamped && note) {
325 note.get()(NoteType::NOTE, String::compose(
"%1 XYZ value(s) clamped", clamped));
A representation of all the parameters involved the colourspace conversion of a YUV image to XYZ (via...
Namespace for everything in libdcp.
void combined_rgb_to_xyz(ColourConversion const &conversion, double *matrix)
void xyz_to_rgb(std::shared_ptr< const OpenJPEGImage >, ColourConversion const &conversion, uint8_t *rgb, int stride, boost::optional< NoteHandler > note=boost::optional< NoteHandler >())
std::shared_ptr< OpenJPEGImage > rgb_to_xyz(uint8_t const *rgb, dcp::Size size, int stride, ColourConversion const &conversion, boost::optional< NoteHandler > note=boost::optional< NoteHandler >())
void xyz_to_rgba(std::shared_ptr< const OpenJPEGImage >, ColourConversion const &conversion, uint8_t *rgba, int stride)
Conversion between RGB and XYZ.
The integer, two-dimensional size of something.