1 diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c
2 index 36b7011..d3c3dfe 100644
3 --- a/third_party/qcms/src/iccread.c
4 +++ b/third_party/qcms/src/iccread.c
5 @@ -266,7 +266,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
6 if (profile->color_space != RGB_SIGNATURE)
9 - if (profile->A2B0 || profile->B2A0)
10 + if (qcms_supports_iccv4 && (profile->A2B0 || profile->B2A0))
13 rX = s15Fixed16Number_to_float(profile->redColorant.X);
14 @@ -297,6 +297,11 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
15 sum[1] = rY + gY + bY;
16 sum[2] = rZ + gZ + bZ;
18 +#if defined (_MSC_VER)
19 +#pragma warning(push)
20 +/* Disable double to float truncation warning 4305 */
21 +#pragma warning(disable:4305)
23 // Build our target vector (see mozilla bug 460629)
26 @@ -310,6 +315,10 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
30 +#if defined (_MSC_VER)
31 +/* Restore warnings */
34 // Compare with our tolerance
35 for (i = 0; i < 3; ++i) {
36 if (!(((sum[i] - tolerance[i]) <= target[i]) &&
37 @@ -402,7 +411,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *src, struct tag_inde
38 // present that are not part of the tag_index.
39 static struct curveType *read_curveType(struct mem_source *src, uint32_t offset, uint32_t *len)
41 - static const size_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7};
42 + static const uint32_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7};
43 struct curveType *curve = NULL;
44 uint32_t type = read_u32(src, offset);
46 @@ -657,7 +666,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index
47 uint16_t num_input_table_entries;
48 uint16_t num_output_table_entries;
49 uint8_t in_chan, grid_points, out_chan;
50 - uint32_t clut_offset, output_offset;
51 + size_t clut_offset, output_offset;
55 diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h
56 index 7d83623..1e3e125 100644
57 --- a/third_party/qcms/src/qcms.h
58 +++ b/third_party/qcms/src/qcms.h
59 @@ -102,6 +102,12 @@ typedef enum {
63 +/* Format of the output data for qcms_transform_data_type() */
69 /* the names for the following two types are sort of ugly */
72 @@ -146,6 +152,7 @@ qcms_transform* qcms_transform_create(
73 void qcms_transform_release(qcms_transform *);
75 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length);
76 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type);
78 void qcms_enable_iccv4();
80 diff --git a/third_party/qcms/src/qcmsint.h b/third_party/qcms/src/qcmsint.h
81 index 53a3420..63905de 100644
82 --- a/third_party/qcms/src/qcmsint.h
83 +++ b/third_party/qcms/src/qcmsint.h
84 @@ -45,6 +45,11 @@ struct precache_output
85 #define ALIGN __attribute__(( aligned (16) ))
88 +typedef struct _qcms_format_type {
93 struct _qcms_transform {
94 float ALIGN matrix[3][4];
95 float *input_gamma_table_r;
96 @@ -88,7 +93,7 @@ struct _qcms_transform {
97 struct precache_output *output_table_g;
98 struct precache_output *output_table_b;
100 - void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length);
101 + void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, struct _qcms_format_type output_format);
105 @@ -280,18 +285,22 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm
106 void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
111 + qcms_format_type output_format);
112 void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
117 + qcms_format_type output_format);
118 void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
123 + qcms_format_type output_format);
124 void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
129 + qcms_format_type output_format);
131 extern qcms_bool qcms_supports_iccv4;
132 diff --git a/third_party/qcms/src/qcmstypes.h b/third_party/qcms/src/qcmstypes.h
133 index 56d8de3..9a9b197 100644
134 --- a/third_party/qcms/src/qcmstypes.h
135 +++ b/third_party/qcms/src/qcmstypes.h
136 @@ -87,7 +87,12 @@ typedef unsigned __int64 uint64_t;
138 typedef unsigned __int64 uintptr_t;
140 +#pragma warning(push)
141 +/* Disable benign redefinition of type warning 4142 */
142 +#pragma warning(disable:4142)
143 typedef unsigned long uintptr_t;
144 +/* Restore warnings */
145 +#pragma warning(pop)
149 diff --git a/third_party/qcms/src/transform-sse1.c b/third_party/qcms/src/transform-sse1.c
150 index 2f34db5..aaee1bf 100644
151 --- a/third_party/qcms/src/transform-sse1.c
152 +++ b/third_party/qcms/src/transform-sse1.c
153 @@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] =
154 void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
159 + qcms_format_type output_format)
162 float (*mat)[4] = transform->matrix;
163 @@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
165 /* working variables */
166 __m128 vec_r, vec_g, vec_b, result;
167 + const int r_out = output_format.r;
168 + const int b_out = output_format.b;
172 @@ -116,9 +119,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
175 /* use calc'd indices to output RGB values */
176 - dest[0] = otdata_r[output[0]];
177 - dest[1] = otdata_g[output[1]];
178 - dest[2] = otdata_b[output[2]];
179 + dest[r_out] = otdata_r[output[0]];
180 + dest[1] = otdata_g[output[1]];
181 + dest[b_out] = otdata_b[output[2]];
185 @@ -141,9 +144,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
186 result = _mm_movehl_ps(result, result);
187 *((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
189 - dest[0] = otdata_r[output[0]];
190 - dest[1] = otdata_g[output[1]];
191 - dest[2] = otdata_b[output[2]];
192 + dest[r_out] = otdata_r[output[0]];
193 + dest[1] = otdata_g[output[1]];
194 + dest[b_out] = otdata_b[output[2]];
198 @@ -151,7 +154,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
199 void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
204 + qcms_format_type output_format)
207 float (*mat)[4] = transform->matrix;
208 @@ -187,6 +191,8 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
210 /* working variables */
211 __m128 vec_r, vec_g, vec_b, result;
212 + const int r_out = output_format.r;
213 + const int b_out = output_format.b;
217 @@ -239,9 +245,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
220 /* use calc'd indices to output RGB values */
221 - dest[0] = otdata_r[output[0]];
222 - dest[1] = otdata_g[output[1]];
223 - dest[2] = otdata_b[output[2]];
224 + dest[r_out] = otdata_r[output[0]];
225 + dest[1] = otdata_g[output[1]];
226 + dest[b_out] = otdata_b[output[2]];
230 @@ -266,9 +272,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
231 result = _mm_movehl_ps(result, result);
232 *((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
234 - dest[0] = otdata_r[output[0]];
235 - dest[1] = otdata_g[output[1]];
236 - dest[2] = otdata_b[output[2]];
237 + dest[r_out] = otdata_r[output[0]];
238 + dest[1] = otdata_g[output[1]];
239 + dest[b_out] = otdata_b[output[2]];
243 diff --git a/third_party/qcms/src/transform-sse2.c b/third_party/qcms/src/transform-sse2.c
244 index 6a5faf9..fa7f2d1 100644
245 --- a/third_party/qcms/src/transform-sse2.c
246 +++ b/third_party/qcms/src/transform-sse2.c
247 @@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] =
248 void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
253 + qcms_format_type output_format)
256 float (*mat)[4] = transform->matrix;
257 @@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
259 /* working variables */
260 __m128 vec_r, vec_g, vec_b, result;
261 + const int r_out = output_format.r;
262 + const int b_out = output_format.b;
266 @@ -114,9 +117,9 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
269 /* use calc'd indices to output RGB values */
270 - dest[0] = otdata_r[output[0]];
271 - dest[1] = otdata_g[output[1]];
272 - dest[2] = otdata_b[output[2]];
273 + dest[r_out] = otdata_r[output[0]];
274 + dest[1] = otdata_g[output[1]];
275 + dest[b_out] = otdata_b[output[2]];
279 @@ -137,15 +140,16 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
281 _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result));
283 - dest[0] = otdata_r[output[0]];
284 - dest[1] = otdata_g[output[1]];
285 - dest[2] = otdata_b[output[2]];
286 + dest[r_out] = otdata_r[output[0]];
287 + dest[1] = otdata_g[output[1]];
288 + dest[b_out] = otdata_b[output[2]];
291 void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
296 + qcms_format_type output_format)
299 float (*mat)[4] = transform->matrix;
300 @@ -181,6 +185,8 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
302 /* working variables */
303 __m128 vec_r, vec_g, vec_b, result;
304 + const int r_out = output_format.r;
305 + const int b_out = output_format.b;
309 @@ -231,9 +237,9 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
312 /* use calc'd indices to output RGB values */
313 - dest[0] = otdata_r[output[0]];
314 - dest[1] = otdata_g[output[1]];
315 - dest[2] = otdata_b[output[2]];
316 + dest[r_out] = otdata_r[output[0]];
317 + dest[1] = otdata_g[output[1]];
318 + dest[b_out] = otdata_b[output[2]];
322 @@ -256,7 +262,7 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
324 _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result));
326 - dest[0] = otdata_r[output[0]];
327 - dest[1] = otdata_g[output[1]];
328 - dest[2] = otdata_b[output[2]];
329 + dest[r_out] = otdata_r[output[0]];
330 + dest[1] = otdata_g[output[1]];
331 + dest[b_out] = otdata_b[output[2]];
333 diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c
334 index 9a6562b..7312ced 100644
335 --- a/third_party/qcms/src/transform.c
336 +++ b/third_party/qcms/src/transform.c
337 @@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_point,
339 adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illumination)
341 +#if defined (_MSC_VER)
342 +#pragma warning(push)
343 +/* Disable double to float truncation warning 4305 */
344 +#pragma warning(disable:4305)
346 struct matrix lam_rigg = {{ // Bradford matrix
347 { 0.8951, 0.2664, -0.1614 },
348 { -0.7502, 1.7135, 0.0367 },
349 { 0.0389, -0.0685, 1.0296 }
351 +#if defined (_MSC_VER)
352 +/* Restore warnings */
353 +#pragma warning(pop)
355 return compute_chromatic_adaption(source_illumination, target_illumination, lam_rigg);
358 @@ -230,8 +239,11 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm
362 -static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
363 +static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
365 + const int r_out = output_format.r;
366 + const int b_out = output_format.b;
369 float (*mat)[4] = transform->matrix;
370 for (i=0; i<length; i++) {
371 @@ -251,15 +263,19 @@ static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned
372 float out_device_g = pow(out_linear_g, transform->out_gamma_g);
373 float out_device_b = pow(out_linear_b, transform->out_gamma_b);
375 - *dest++ = clamp_u8(255*out_device_r);
376 - *dest++ = clamp_u8(255*out_device_g);
377 - *dest++ = clamp_u8(255*out_device_b);
378 + dest[r_out] = clamp_u8(out_device_r*255);
379 + dest[1] = clamp_u8(out_device_g*255);
380 + dest[b_out] = clamp_u8(out_device_b*255);
386 -static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
387 +static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
389 + const int r_out = output_format.r;
390 + const int b_out = output_format.b;
393 for (i = 0; i < length; i++) {
394 float out_device_r, out_device_g, out_device_b;
395 @@ -267,13 +283,14 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
397 float linear = transform->input_gamma_table_gray[device];
399 - out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
400 + out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
401 out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
402 out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
404 - *dest++ = clamp_u8(out_device_r*255);
405 - *dest++ = clamp_u8(out_device_g*255);
406 - *dest++ = clamp_u8(out_device_b*255);
407 + dest[r_out] = clamp_u8(out_device_r*255);
408 + dest[1] = clamp_u8(out_device_g*255);
409 + dest[b_out] = clamp_u8(out_device_b*255);
414 @@ -283,8 +300,11 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
415 See: ftp://ftp.alvyray.com/Acrobat/17_Nonln.pdf
418 -static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
419 +static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
421 + const int r_out = output_format.r;
422 + const int b_out = output_format.b;
425 for (i = 0; i < length; i++) {
426 float out_device_r, out_device_g, out_device_b;
427 @@ -293,20 +313,24 @@ static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigne
429 float linear = transform->input_gamma_table_gray[device];
431 - out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
432 + out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
433 out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
434 out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
436 - *dest++ = clamp_u8(out_device_r*255);
437 - *dest++ = clamp_u8(out_device_g*255);
438 - *dest++ = clamp_u8(out_device_b*255);
440 + dest[r_out] = clamp_u8(out_device_r*255);
441 + dest[1] = clamp_u8(out_device_g*255);
442 + dest[b_out] = clamp_u8(out_device_b*255);
449 -static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
450 +static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
452 + const int r_out = output_format.r;
453 + const int b_out = output_format.b;
456 for (i = 0; i < length; i++) {
457 unsigned char device = *src++;
458 @@ -317,14 +341,19 @@ static void qcms_transform_data_gray_out_precache(qcms_transform *transform, uns
459 /* we could round here... */
460 gray = linear * PRECACHE_OUTPUT_MAX;
462 - *dest++ = transform->output_table_r->data[gray];
463 - *dest++ = transform->output_table_g->data[gray];
464 - *dest++ = transform->output_table_b->data[gray];
465 + dest[r_out] = transform->output_table_r->data[gray];
466 + dest[1] = transform->output_table_g->data[gray];
467 + dest[b_out] = transform->output_table_b->data[gray];
472 -static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
474 +static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
476 + const int r_out = output_format.r;
477 + const int b_out = output_format.b;
480 for (i = 0; i < length; i++) {
481 unsigned char device = *src++;
482 @@ -336,15 +365,19 @@ static void qcms_transform_data_graya_out_precache(qcms_transform *transform, un
483 /* we could round here... */
484 gray = linear * PRECACHE_OUTPUT_MAX;
486 - *dest++ = transform->output_table_r->data[gray];
487 - *dest++ = transform->output_table_g->data[gray];
488 - *dest++ = transform->output_table_b->data[gray];
490 + dest[r_out] = transform->output_table_r->data[gray];
491 + dest[1] = transform->output_table_g->data[gray];
492 + dest[b_out] = transform->output_table_b->data[gray];
498 -static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
499 +static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
501 + const int r_out = output_format.r;
502 + const int b_out = output_format.b;
505 float (*mat)[4] = transform->matrix;
506 for (i = 0; i < length; i++) {
507 @@ -370,14 +403,18 @@ static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform,
508 g = out_linear_g * PRECACHE_OUTPUT_MAX;
509 b = out_linear_b * PRECACHE_OUTPUT_MAX;
511 - *dest++ = transform->output_table_r->data[r];
512 - *dest++ = transform->output_table_g->data[g];
513 - *dest++ = transform->output_table_b->data[b];
514 + dest[r_out] = transform->output_table_r->data[r];
515 + dest[1] = transform->output_table_g->data[g];
516 + dest[b_out] = transform->output_table_b->data[b];
521 -static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
522 +static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
524 + const int r_out = output_format.r;
525 + const int b_out = output_format.b;
528 float (*mat)[4] = transform->matrix;
529 for (i = 0; i < length; i++) {
530 @@ -404,16 +441,21 @@ static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform,
531 g = out_linear_g * PRECACHE_OUTPUT_MAX;
532 b = out_linear_b * PRECACHE_OUTPUT_MAX;
534 - *dest++ = transform->output_table_r->data[r];
535 - *dest++ = transform->output_table_g->data[g];
536 - *dest++ = transform->output_table_b->data[b];
538 + dest[r_out] = transform->output_table_r->data[r];
539 + dest[1] = transform->output_table_g->data[g];
540 + dest[b_out] = transform->output_table_b->data[b];
548 -static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
549 +static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
551 + const int r_out = output_format.r;
552 + const int b_out = output_format.b;
556 int x_len = transform->grid_size;
557 @@ -462,15 +504,20 @@ static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *s
558 float b_y2 = lerp(b_x3, b_x4, y_d);
559 float clut_b = lerp(b_y1, b_y2, z_d);
561 - *dest++ = clamp_u8(clut_r*255.0f);
562 - *dest++ = clamp_u8(clut_g*255.0f);
563 - *dest++ = clamp_u8(clut_b*255.0f);
565 + dest[r_out] = clamp_u8(clut_r*255.0f);
566 + dest[1] = clamp_u8(clut_g*255.0f);
567 + dest[b_out] = clamp_u8(clut_b*255.0f);
573 // Using lcms' tetra interpolation algorithm.
574 -static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
575 +static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
577 + const int r_out = output_format.r;
578 + const int b_out = output_format.b;
582 int x_len = transform->grid_size;
583 @@ -577,15 +624,20 @@ static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsig
584 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
585 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
587 - *dest++ = clamp_u8(clut_r*255.0f);
588 - *dest++ = clamp_u8(clut_g*255.0f);
589 - *dest++ = clamp_u8(clut_b*255.0f);
592 + dest[r_out] = clamp_u8(clut_r*255.0f);
593 + dest[1] = clamp_u8(clut_g*255.0f);
594 + dest[b_out] = clamp_u8(clut_b*255.0f);
600 // Using lcms' tetra interpolation code.
601 -static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
602 +static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
604 + const int r_out = output_format.r;
605 + const int b_out = output_format.b;
609 int x_len = transform->grid_size;
610 @@ -691,14 +743,18 @@ static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned c
611 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
612 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
614 - *dest++ = clamp_u8(clut_r*255.0f);
615 - *dest++ = clamp_u8(clut_g*255.0f);
616 - *dest++ = clamp_u8(clut_b*255.0f);
618 + dest[r_out] = clamp_u8(clut_r*255.0f);
619 + dest[1] = clamp_u8(clut_g*255.0f);
620 + dest[b_out] = clamp_u8(clut_b*255.0f);
625 -static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
626 +static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
628 + const int r_out = output_format.r;
629 + const int b_out = output_format.b;
632 float (*mat)[4] = transform->matrix;
633 for (i = 0; i < length; i++) {
634 @@ -726,14 +782,18 @@ static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned
635 out_device_b = lut_interp_linear(out_linear_b,
636 transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
638 - *dest++ = clamp_u8(out_device_r*255);
639 - *dest++ = clamp_u8(out_device_g*255);
640 - *dest++ = clamp_u8(out_device_b*255);
641 + dest[r_out] = clamp_u8(out_device_r*255);
642 + dest[1] = clamp_u8(out_device_g*255);
643 + dest[b_out] = clamp_u8(out_device_b*255);
648 -static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
649 +static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
651 + const int r_out = output_format.r;
652 + const int b_out = output_format.b;
655 float (*mat)[4] = transform->matrix;
656 for (i = 0; i < length; i++) {
657 @@ -762,16 +822,20 @@ static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned
658 out_device_b = lut_interp_linear(out_linear_b,
659 transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
661 - *dest++ = clamp_u8(out_device_r*255);
662 - *dest++ = clamp_u8(out_device_g*255);
663 - *dest++ = clamp_u8(out_device_b*255);
665 + dest[r_out] = clamp_u8(out_device_r*255);
666 + dest[1] = clamp_u8(out_device_g*255);
667 + dest[b_out] = clamp_u8(out_device_b*255);
674 -static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
675 +static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
677 + const int r_out = output_format.r;
678 + const int b_out = output_format.b;
681 float (*mat)[4] = transform->matrix;
682 for (i = 0; i < length; i++) {
683 @@ -787,9 +851,10 @@ static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsign
684 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + mat[2][1]*linear_b;
685 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + mat[2][2]*linear_b;
687 - *dest++ = clamp_u8(out_linear_r*255);
688 - *dest++ = clamp_u8(out_linear_g*255);
689 - *dest++ = clamp_u8(out_linear_b*255);
690 + dest[r_out] = clamp_u8(out_linear_r*255);
691 + dest[1] = clamp_u8(out_linear_g*255);
692 + dest[b_out] = clamp_u8(out_linear_b*255);
697 @@ -815,7 +880,7 @@ void precache_release(struct precache_output *p)
701 -#ifdef HAS_POSIX_MEMALIGN
702 +#ifdef HAVE_POSIX_MEMALIGN
703 static qcms_transform *transform_alloc(void)
706 @@ -994,13 +1059,15 @@ void qcms_profile_precache_output_transform(qcms_profile *profile)
707 if (profile->color_space != RGB_SIGNATURE)
710 - /* don't precache since we will use the B2A LUT */
713 + if (qcms_supports_iccv4) {
714 + /* don't precache since we will use the B2A LUT */
718 - /* don't precache since we will use the mBA LUT */
721 + /* don't precache since we will use the mBA LUT */
726 /* don't precache if we do not have the TRC curves */
727 if (!profile->redTRC || !profile->greenTRC || !profile->blueTRC)
728 @@ -1157,14 +1224,14 @@ qcms_transform* qcms_transform_create(
733 +#if defined(SSE2_ENABLE) && defined(X86)
734 if (sse_version_available() >= 2) {
735 if (in_type == QCMS_DATA_RGB_8)
736 transform->transform_fn = qcms_transform_data_rgb_out_lut_sse2;
738 transform->transform_fn = qcms_transform_data_rgba_out_lut_sse2;
740 -#if !(defined(_MSC_VER) && defined(_M_AMD64))
741 +#if defined(SSE2_ENABLE) && !(defined(_MSC_VER) && defined(_M_AMD64))
742 /* Microsoft Compiler for x64 doesn't support MMX.
743 * SSE code uses MMX so that we disable on x64 */
745 @@ -1256,13 +1323,34 @@ qcms_transform* qcms_transform_create(
749 -#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
750 +/* __force_align_arg_pointer__ is an x86-only attribute, and gcc/clang warns on unused
751 + * attributes. Don't use this on ARM or AMD64. __has_attribute can detect the presence
752 + * of the attribute but is currently only supported by clang */
753 +#if defined(__has_attribute)
754 +#define HAS_FORCE_ALIGN_ARG_POINTER __has_attribute(__force_align_arg_pointer__)
755 +#elif defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) && !defined(__arm__)
756 +#define HAS_FORCE_ALIGN_ARG_POINTER 1
758 +#define HAS_FORCE_ALIGN_ARG_POINTER 0
761 +#if HAS_FORCE_ALIGN_ARG_POINTER
762 /* we need this to avoid crashes when gcc assumes the stack is 128bit aligned */
763 __attribute__((__force_align_arg_pointer__))
765 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length)
767 - transform->transform_fn(transform, src, dest, length);
768 + static const struct _qcms_format_type output_rgbx = { 0, 2 };
770 + transform->transform_fn(transform, src, dest, length, output_rgbx);
773 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type)
775 + static const struct _qcms_format_type output_rgbx = { 0, 2 };
776 + static const struct _qcms_format_type output_bgrx = { 2, 0 };
778 + transform->transform_fn(transform, src, dest, length, type == QCMS_OUTPUT_BGRX ? output_bgrx : output_rgbx);
781 qcms_bool qcms_supports_iccv4;
782 diff --git a/third_party/qcms/src/transform_util.c b/third_party/qcms/src/transform_util.c
783 index e8447e5..f4338b2 100644
784 --- a/third_party/qcms/src/transform_util.c
785 +++ b/third_party/qcms/src/transform_util.c
788 /* value must be a value between 0 and 1 */
789 //XXX: is the above a good restriction to have?
790 -float lut_interp_linear(double value, uint16_t *table, int length)
791 +float lut_interp_linear(double value, uint16_t *table, size_t length)
794 value = value * (length - 1); // scale to length of the array
795 @@ -49,11 +49,11 @@ float lut_interp_linear(double value, uint16_t *table, int length)
798 /* same as above but takes and returns a uint16_t value representing a range from 0..1 */
799 -uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length)
800 +uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t length)
802 /* Start scaling input_value to the length of the array: 65535*(length-1).
803 * We'll divide out the 65535 next */
804 - uint32_t value = (input_value * (length - 1));
805 + uintptr_t value = (input_value * (length - 1));
806 uint32_t upper = (value + 65534) / 65535; /* equivalent to ceil(value/65535) */
807 uint32_t lower = value / 65535; /* equivalent to floor(value/65535) */
808 /* interp is the distance from upper to value scaled to 0..65535 */
809 @@ -67,11 +67,11 @@ uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length)
810 /* same as above but takes an input_value from 0..PRECACHE_OUTPUT_MAX
811 * and returns a uint8_t value representing a range from 0..1 */
813 -uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table, int length)
814 +uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table, size_t length)
816 /* Start scaling input_value to the length of the array: PRECACHE_OUTPUT_MAX*(length-1).
817 * We'll divide out the PRECACHE_OUTPUT_MAX next */
818 - uint32_t value = (input_value * (length - 1));
819 + uintptr_t value = (input_value * (length - 1));
821 /* equivalent to ceil(value/PRECACHE_OUTPUT_MAX) */
822 uint32_t upper = (value + PRECACHE_OUTPUT_MAX-1) / PRECACHE_OUTPUT_MAX;
823 @@ -91,7 +91,7 @@ uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table,
825 /* value must be a value between 0 and 1 */
826 //XXX: is the above a good restriction to have?
827 -float lut_interp_linear_float(float value, float *table, int length)
828 +float lut_interp_linear_float(float value, float *table, size_t length)
831 value = value * (length - 1);
832 @@ -235,6 +235,21 @@ float u8Fixed8Number_to_float(uint16_t x)
836 +/* The SSE2 code uses min & max which let NaNs pass through.
837 + We want to try to prevent that here by ensuring that
838 + gamma table is within expected values. */
839 +void validate_gamma_table(float gamma_table[256])
842 + for (i = 0; i < 256; i++) {
843 + // Note: we check that the gamma is not in range
844 + // instead of out of range so that we catch NaNs
845 + if (!(gamma_table[i] >= 0.f && gamma_table[i] <= 1.f)) {
846 + gamma_table[i] = 0.f;
851 float *build_input_gamma_table(struct curveType *TRC)
854 @@ -254,7 +269,10 @@ float *build_input_gamma_table(struct curveType *TRC)
858 - return gamma_table;
860 + validate_gamma_table(gamma_table);
862 + return gamma_table;
865 struct matrix build_colorant_matrix(qcms_profile *p)
866 @@ -390,7 +408,7 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len
867 which has an maximum error of about 9855 (pixel difference of ~38.346)
869 For now, we punt the decision of output size to the caller. */
870 -static uint16_t *invert_lut(uint16_t *table, int length, int out_length)
871 +static uint16_t *invert_lut(uint16_t *table, int length, size_t out_length)
874 /* for now we invert the lut by creating a lut of size out_length
875 diff --git a/third_party/qcms/src/transform_util.h b/third_party/qcms/src/transform_util.h
876 index 8f358a8..de465f4 100644
877 --- a/third_party/qcms/src/transform_util.h
878 +++ b/third_party/qcms/src/transform_util.h
880 //XXX: could use a bettername
881 typedef uint16_t uint16_fract_t;
883 -float lut_interp_linear(double value, uint16_t *table, int length);
884 -float lut_interp_linear_float(float value, float *table, int length);
885 -uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length);
886 +float lut_interp_linear(double value, uint16_t *table, size_t length);
887 +float lut_interp_linear_float(float value, float *table, size_t length);
888 +uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t length);
891 static inline float lerp(float a, float b, float t)