Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: third_party/qcms/google.patch

Issue 1136283002: qcms: Drop the google.patch file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Integrate review feedback Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/qcms/README.chromium ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c
2 index 36b7011..0deab10 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)
7 return false;
8
9 - if (profile->A2B0 || profile->B2A0)
10 + if (qcms_supports_iccv4 && (profile->A2B0 || profile->B2A0))
11 return false;
12
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;
17
18 +#if defined (_MSC_VER)
19 +#pragma warning(push)
20 +/* Disable double to float truncation warning 4305 */
21 +#pragma warning(disable:4305)
22 +#endif
23 // Build our target vector (see mozilla bug 460629)
24 target[0] = 0.96420;
25 target[1] = 1.00000;
26 @@ -310,6 +315,10 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
27 tolerance[1] = 0.02;
28 tolerance[2] = 0.04;
29
30 +#if defined (_MSC_VER)
31 +/* Restore warnings */
32 +#pragma warning(pop)
33 +#endif
34 // Compare with our tolerance
35 for (i = 0; i < 3; ++i) {
36 if (!(((sum[i] - tolerance[i]) <= target[i]) &&
37 @@ -331,6 +340,8 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile)
38 #define TAG_A2B0 0x41324230
39 #define TAG_B2A0 0x42324130
40 #define TAG_CHAD 0x63686164
41 +#define TAG_desc 0x64657363
42 +#define TAG_vcgt 0x76636774
43
44 static struct tag *find_tag(struct tag_index index, uint32_t tag_id)
45 {
46 @@ -344,6 +355,215 @@ static struct tag *find_tag(struct tag_index index, uint32 _t tag_id)
47 return tag;
48 }
49
50 +#define DESC_TYPE 0x64657363 // 'desc'
51 +#define MLUC_TYPE 0x6d6c7563 // 'mluc'
52 +#define MMOD_TYPE 0x6D6D6F64 // 'mmod'
53 +#define VCGT_TYPE 0x76636774 // 'vcgt'
54 +
55 +// Check unsigned short is uint16_t.
56 +typedef char assert_short_not_16b[(sizeof(unsigned short) == sizeof(uint16_t)) ? 1 : -1];
57 +
58 +qcms_bool read_tag_vcgtType(qcms_profile *profile, struct mem_source *src, stru ct tag_index index) {
59 + size_t tag_offset = find_tag(index, TAG_vcgt)->offset;
60 + uint32_t tag_type = read_u32(src, tag_offset);
61 + uint32_t vcgt_type = read_u32(src, tag_offset + 8);
62 + uint16_t channels = read_u16(src, tag_offset + 12);
63 + uint16_t elements = read_u16(src, tag_offset + 14);
64 + uint16_t byte_depth = read_u16(src, tag_offset + 16);
65 + size_t table_offset = tag_offset + 18;
66 + uint32_t i;
67 + uint16_t *dest;
68 +
69 + if (!src->valid || tag_type != VCGT_TYPE)
70 + goto invalid_vcgt_tag;
71 +
72 + // Only support 3 channels.
73 + if (channels != 3)
74 + return true;
75 + // Only support single or double byte values.
76 + if (byte_depth != 1 && byte_depth != 2)
77 + return true;
78 + // Only support table data, not equation.
79 + if (vcgt_type != 0)
80 + return true;
81 + // Limit the table to a sensible size; 10-bit gamma is a reasonable
82 + // maximum for hardware correction.
83 + if (elements > 1024)
84 + return true;
85 +
86 + // Empty table is invalid.
87 + if (!elements)
88 + goto invalid_vcgt_tag;
89 +
90 + profile->vcgt.length = elements;
91 + profile->vcgt.data = malloc(3 * elements * sizeof(uint16_t));
92 + if (!profile->vcgt.data)
93 + return false;
94 +
95 + dest = profile->vcgt.data;
96 +
97 + for (i = 0; i < 3 * elements; ++i) {
98 + if (byte_depth == 1) {
99 + *dest++ = read_u8(src, table_offset) * 256;
100 + } else {
101 + *dest++ = read_u16(src, table_offset);
102 + }
103 +
104 + table_offset += byte_depth;
105 +
106 + if (!src->valid)
107 + goto invalid_vcgt_tag;
108 + }
109 +
110 + return true;
111 +
112 +invalid_vcgt_tag:
113 + invalid_source(src, "invalid vcgt tag");
114 + return false;
115 +}
116 +
117 +static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, st ruct tag_index index, uint32_t tag_id)
118 +{
119 + struct tag *tag = find_tag(index, tag_id);
120 + if (tag) {
121 + const uint32_t limit = sizeof profile->description;
122 + uint32_t offset = tag->offset;
123 + uint32_t type = read_u32(src, offset);
124 + uint32_t length = read_u32(src, offset+8);
125 + uint32_t i, description_offset;
126 + bool mluc = false;
127 + if (length && type == MLUC_TYPE) {
128 + length = read_u32(src, offset+20);
129 + if (!length || (length & 1) || (read_u32(src, offset+12) != 12))
130 + goto invalid_desc_tag;
131 + description_offset = offset + read_u32(src, offset+24);
132 + if (!src->valid)
133 + goto invalid_desc_tag;
134 + mluc = true;
135 + } else if (length && type == DESC_TYPE) {
136 + description_offset = offset + 12;
137 + } else {
138 + goto invalid_desc_tag;
139 + }
140 + if (length >= limit)
141 + length = limit - 1;
142 + for (i = 0; i < length; ++i) {
143 + uint8_t value = read_u8(src, description_offset + i);
144 + if (!src->valid)
145 + goto invalid_desc_tag;
146 + if (mluc && !value)
147 + value = '.';
148 + profile->description[i] = value;
149 + }
150 + profile->description[length] = 0;
151 + } else {
152 + goto invalid_desc_tag;
153 + }
154 +
155 + if (src->valid)
156 + return true;
157 +
158 +invalid_desc_tag:
159 + invalid_source(src, "invalid description");
160 + return false;
161 +}
162 +
163 +#if defined(__APPLE__)
164 +
165 +// Use the dscm tag to change profile description "Display" to its more specifi c en-localized monitor name, if any.
166 +
167 +#define TAG_dscm 0x6473636D // 'dscm'
168 +
169 +static bool read_tag_dscmType(qcms_profile *profile, struct mem_source *src, st ruct tag_index index, uint32_t tag_id)
170 +{
171 + if (strcmp(profile->description, "Display") != 0)
172 + return true;
173 +
174 + struct tag *tag = find_tag(index, tag_id);
175 + if (tag) {
176 + uint32_t offset = tag->offset;
177 + uint32_t type = read_u32(src, offset);
178 + uint32_t records = read_u32(src, offset+8);
179 +
180 + if (!src->valid || !records || type != MLUC_TYPE)
181 + goto invalid_dscm_tag;
182 + if (read_u32(src, offset+12) != 12) // MLUC record size: bytes
183 + goto invalid_dscm_tag;
184 +
185 + for (uint32_t i = 0; i < records; ++i) {
186 + const uint32_t limit = sizeof profile->description;
187 + const uint16_t isoen = 0x656E; // ISO-3166-1 language 'e n'
188 +
189 + uint16_t language = read_u16(src, offset + 16 + (i * 12) + 0);
190 + uint32_t length = read_u32(src, offset + 16 + (i * 12) + 4);
191 + uint32_t description_offset = read_u32(src, offset + 16 + (i * 12) + 8);
192 +
193 + if (!src->valid || !length || (length & 1))
194 + goto invalid_dscm_tag;
195 + if (language != isoen)
196 + continue;
197 +
198 + // Use a prefix to identify the display description sour ce
199 + strcpy(profile->description, "dscm:");
200 + length += 5;
201 +
202 + if (length >= limit)
203 + length = limit - 1;
204 + for (uint32_t j = 5; j < length; ++j) {
205 + uint8_t value = read_u8(src, offset + descriptio n_offset + j - 5);
206 + if (!src->valid)
207 + goto invalid_dscm_tag;
208 + profile->description[j] = value ? value : '.';
209 + }
210 + profile->description[length] = 0;
211 + break;
212 + }
213 + }
214 +
215 + if (src->valid)
216 + return true;
217 +
218 +invalid_dscm_tag:
219 + invalid_source(src, "invalid dscm tag");
220 + return false;
221 +}
222 +
223 +// Use the mmod tag to change profile description "Display" to its specific mmo d maker model data, if any.
224 +
225 +#define TAG_mmod 0x6D6D6F64 // 'mmod'
226 +
227 +static bool read_tag_mmodType(qcms_profile *profile, struct mem_source *src, st ruct tag_index index, uint32_t tag_id)
228 +{
229 + if (strcmp(profile->description, "Display") != 0)
230 + return true;
231 +
232 + struct tag *tag = find_tag(index, tag_id);
233 + if (tag) {
234 + const uint8_t length = 4 * 4; // Four 4-byte fields: 'mmod', 0, maker, model.
235 +
236 + uint32_t offset = tag->offset;
237 + if (tag->size < 40 || read_u32(src, offset) != MMOD_TYPE)
238 + goto invalid_mmod_tag;
239 +
240 + for (uint8_t i = 0; i < length; ++i) {
241 + uint8_t value = read_u8(src, offset + i);
242 + if (!src->valid)
243 + goto invalid_mmod_tag;
244 + profile->description[i] = value ? value : '.';
245 + }
246 + profile->description[length] = 0;
247 + }
248 +
249 + if (src->valid)
250 + return true;
251 +
252 +invalid_mmod_tag:
253 + invalid_source(src, "invalid mmod tag");
254 + return false;
255 +}
256 +
257 +#endif // __APPLE__
258 +
259 #define XYZ_TYPE 0x58595a20 // 'XYZ '
260 #define CURVE_TYPE 0x63757276 // 'curv'
261 #define PARAMETRIC_CURVE_TYPE 0x70617261 // 'para'
262 @@ -402,7 +622,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source * src, struct tag_inde
263 // present that are not part of the tag_index.
264 static struct curveType *read_curveType(struct mem_source *src, uint32_t offset , uint32_t *len)
265 {
266 - static const size_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7};
267 + static const uint32_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7};
268 struct curveType *curve = NULL;
269 uint32_t type = read_u32(src, offset);
270 uint32_t count;
271 @@ -484,19 +704,23 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu
272 uint32_t channel_offset = 0;
273 int i;
274 for (i = 0; i < num_channels; i++) {
275 - uint32_t tag_len;
276 + uint32_t tag_len = ~0;
277
278 (*curveArray)[i] = read_curveType(src, curve_offset + channel_of fset, &tag_len);
279 if (!(*curveArray)[i]) {
280 invalid_source(src, "invalid nested curveType curve");
281 }
282
283 + if (tag_len == ~0) {
284 + invalid_source(src, "invalid nested curveType tag length ");
285 + return;
286 + }
287 +
288 channel_offset += tag_len;
289 // 4 byte aligned
290 if ((tag_len % 4) != 0)
291 channel_offset += 4 - (tag_len % 4);
292 }
293 -
294 }
295
296 static void mAB_release(struct lutmABType *lut)
297 @@ -540,7 +764,7 @@ static struct lutmABType *read_tag_lutmABType(struct mem_sou rce *src, struct tag
298 // We require 3in/out channels since we only support RGB->XYZ (or RGB->L AB)
299 // XXX: If we remove this restriction make sure that the number of chann els
300 // is less or equal to the maximum number of mAB curves in qcmsint. h
301 - // also check for clut_size overflow.
302 + // also check for clut_size overflow. Also make sure it's != 0
303 if (num_in_channels != 3 || num_out_channels != 3)
304 return NULL;
305
306 @@ -570,6 +794,9 @@ static struct lutmABType *read_tag_lutmABType(struct mem_sou rce *src, struct tag
307 // clut_size can not overflow since lg(256^num_in_channels) = 24 bits.
308 for (i = 0; i < num_in_channels; i++) {
309 clut_size *= read_u8(src, clut_offset + i);
310 + if (clut_size == 0) {
311 + invalid_source(src, "bad clut_size");
312 + }
313 }
314 } else {
315 clut_size = 0;
316 @@ -590,6 +817,9 @@ static struct lutmABType *read_tag_lutmABType(struct mem_sou rce *src, struct tag
317
318 for (i = 0; i < num_in_channels; i++) {
319 lut->num_grid_points[i] = read_u8(src, clut_offset + i);
320 + if (lut->num_grid_points[i] == 0) {
321 + invalid_source(src, "bad grid_points");
322 + }
323 }
324
325 // Reverse the processing of transformation elements for mBA type.
326 @@ -657,7 +887,7 @@ static struct lutType *read_tag_lutType(struct mem_source *s rc, struct tag_index
327 uint16_t num_input_table_entries;
328 uint16_t num_output_table_entries;
329 uint8_t in_chan, grid_points, out_chan;
330 - uint32_t clut_offset, output_offset;
331 + size_t clut_offset, output_offset;
332 uint32_t clut_size;
333 size_t entry_size;
334 struct lutType *lut;
335 @@ -672,6 +902,10 @@ static struct lutType *read_tag_lutType(struct mem_source * src, struct tag_index
336 } else if (type == LUT16_TYPE) {
337 num_input_table_entries = read_u16(src, offset + 48);
338 num_output_table_entries = read_u16(src, offset + 50);
339 + if (num_input_table_entries == 0 || num_output_table_entries == 0) {
340 + invalid_source(src, "Bad channel count");
341 + return NULL;
342 + }
343 entry_size = 2;
344 } else {
345 assert(0); // the caller checks that this doesn't happen
346 @@ -685,15 +919,18 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index
347
348 clut_size = pow(grid_points, in_chan);
349 if (clut_size > MAX_CLUT_SIZE) {
350 + invalid_source(src, "CLUT too large");
351 return NULL;
352 }
353
354 if (in_chan != 3 || out_chan != 3) {
355 + invalid_source(src, "CLUT only supports RGB");
356 return NULL;
357 }
358
359 lut = malloc(sizeof(struct lutType) + (num_input_table_entries * in_chan + clut_size*out_chan + num_output_table_entries * out_chan)*sizeof(float));
360 if (!lut) {
361 + invalid_source(src, "CLUT too large");
362 return NULL;
363 }
364
365 @@ -704,9 +941,9 @@ static struct lutType *read_tag_lutType(struct mem_source *s rc, struct tag_index
366
367 lut->num_input_table_entries = num_input_table_entries;
368 lut->num_output_table_entries = num_output_table_entries;
369 - lut->num_input_channels = read_u8(src, offset + 8);
370 - lut->num_output_channels = read_u8(src, offset + 9);
371 - lut->num_clut_grid_points = read_u8(src, offset + 10);
372 + lut->num_input_channels = in_chan;
373 + lut->num_output_channels = out_chan;
374 + lut->num_clut_grid_points = grid_points;
375 lut->e00 = read_s15Fixed16Number(src, offset+12);
376 lut->e01 = read_s15Fixed16Number(src, offset+16);
377 lut->e02 = read_s15Fixed16Number(src, offset+20);
378 @@ -979,11 +1216,13 @@ qcms_profile* qcms_profile_sRGB(void)
379 return NO_MEM_PROFILE;
380
381 profile = qcms_profile_create_rgb_with_table(D65, Rec709Primaries, table , 1024);
382 + if (profile)
383 + strcpy(profile->description, "sRGB IEC61966-2.1");
384 +
385 free(table);
386 return profile;
387 }
388
389 -
390 /* qcms_profile_from_memory does not hold a reference to the memory passed in * /
391 qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
392 {
393 @@ -997,6 +1236,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, siz e_t size)
394 source.size = size;
395 source.valid = true;
396
397 + if (size < 4)
398 + return INVALID_PROFILE;
399 +
400 length = read_u32(src, 0);
401 if (length <= size) {
402 // shrink the area that we can read if appropriate
403 @@ -1028,12 +1270,26 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size)
404 if (!src->valid || !index.tags)
405 goto invalid_tag_table;
406
407 + if (!read_tag_descType(profile, src, index, TAG_desc))
408 + goto invalid_tag_table;
409 +#if defined(__APPLE__)
410 + if (!read_tag_dscmType(profile, src, index, TAG_dscm))
411 + goto invalid_tag_table;
412 + if (!read_tag_mmodType(profile, src, index, TAG_mmod))
413 + goto invalid_tag_table;
414 +#endif // __APPLE__
415 +
416 if (find_tag(index, TAG_CHAD)) {
417 profile->chromaticAdaption = read_tag_s15Fixed16ArrayType(src, i ndex, TAG_CHAD);
418 } else {
419 profile->chromaticAdaption.invalid = true; //Signal the data is not present
420 }
421
422 + if (find_tag(index, TAG_vcgt)) {
423 + if (!read_tag_vcgtType(profile, src, index))
424 + goto invalid_tag_table;
425 + }
426 +
427 if (profile->class == DISPLAY_DEVICE_PROFILE || profile->class == INPUT_ DEVICE_PROFILE ||
428 profile->class == OUTPUT_DEVICE_PROFILE || profile->class == COLOR _SPACE_PROFILE) {
429 if (profile->color_space == RGB_SIGNATURE) {
430 @@ -1098,6 +1354,16 @@ invalid_profile:
431 return INVALID_PROFILE;
432 }
433
434 +qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2)
435 +{
436 + return memcmp(p1->description, p2->description, sizeof p1->description) == 0;
437 +}
438 +
439 +const char* qcms_profile_get_description(qcms_profile *profile)
440 +{
441 + return profile->description;
442 +}
443 +
444 qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile)
445 {
446 return profile->rendering_intent;
447 @@ -1114,6 +1380,18 @@ static void lut_release(struct lutType *lut)
448 free(lut);
449 }
450
451 +size_t qcms_profile_get_vcgt_channel_length(qcms_profile *profile) {
452 + return profile->vcgt.length;
453 +}
454 +
455 +qcms_bool qcms_profile_get_vcgt_rgb_channels(qcms_profile *profile, unsigned sh ort *data) {
456 + size_t vcgt_channel_bytes = qcms_profile_get_vcgt_channel_length(profile ) * sizeof(uint16_t);
457 + if (!vcgt_channel_bytes || !data)
458 + return false;
459 + memcpy(data, profile->vcgt.data, 3 * vcgt_channel_bytes);
460 + return true;
461 +}
462 +
463 void qcms_profile_release(qcms_profile *profile)
464 {
465 if (profile->output_table_r)
466 @@ -1133,6 +1411,9 @@ void qcms_profile_release(qcms_profile *profile)
467 if (profile->mBA)
468 mAB_release(profile->mBA);
469
470 + if (profile->vcgt.data)
471 + free(profile->vcgt.data);
472 +
473 free(profile->redTRC);
474 free(profile->blueTRC);
475 free(profile->greenTRC);
476 diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h
477 index 7d83623..be74717 100644
478 --- a/third_party/qcms/src/qcms.h
479 +++ b/third_party/qcms/src/qcms.h
480 @@ -40,6 +40,12 @@ sale, use or other dealings in this Software without written
481 authorization from SunSoft Inc.
482 ******************************************************************/
483
484 +/*
485 + * QCMS, in general, is not threadsafe. However, it should be safe to create
486 + * profile and transformation objects on different threads, so long as you
487 + * don't use the same objects on different threads at the same time.
488 + */
489 +
490 /*
491 * Color Space Signatures
492 * Note that only icSigXYZData and icSigLabData are valid
493 @@ -102,6 +108,12 @@ typedef enum {
494 QCMS_DATA_GRAYA_8
495 } qcms_data_type;
496
497 +/* Format of the output data for qcms_transform_data_type() */
498 +typedef enum {
499 + QCMS_OUTPUT_RGBX,
500 + QCMS_OUTPUT_BGRX
501 +} qcms_output_type;
502 +
503 /* the names for the following two types are sort of ugly */
504 typedef struct
505 {
506 @@ -136,16 +148,27 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile);
507 qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile);
508 icColorSpaceSignature qcms_profile_get_color_space(qcms_profile *profile);
509
510 +qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2);
511 +const char* qcms_profile_get_description(qcms_profile *profile);
512 +
513 void qcms_profile_precache_output_transform(qcms_profile *profile);
514
515 +size_t qcms_profile_get_vcgt_channel_length(qcms_profile *profile);
516 +qcms_bool qcms_profile_get_vcgt_rgb_channels(qcms_profile *profile, unsigned sh ort *data);
517 +
518 qcms_transform* qcms_transform_create(
519 qcms_profile *in, qcms_data_type in_type,
520 qcms_profile* out, qcms_data_type out_type,
521 qcms_intent intent);
522
523 -void qcms_transform_release(qcms_transform *);
524 +qcms_bool qcms_transform_create_LUT_zyx_bgra(
525 + qcms_profile *in, qcms_profile* out, qcms_intent intent,
526 + int samples, unsigned char* lut);
527
528 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size _t length);
529 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type);
530 +
531 +void qcms_transform_release(qcms_transform *);
532
533 void qcms_enable_iccv4();
534
535 diff --git a/third_party/qcms/src/qcmsint.h b/third_party/qcms/src/qcmsint.h
536 index 53a3420..6b22c5a 100644
537 --- a/third_party/qcms/src/qcmsint.h
538 +++ b/third_party/qcms/src/qcmsint.h
539 @@ -45,6 +45,11 @@ struct precache_output
540 #define ALIGN __attribute__(( aligned (16) ))
541 #endif
542
543 +typedef struct _qcms_format_type {
544 + int r;
545 + int b;
546 +} qcms_format_type;
547 +
548 struct _qcms_transform {
549 float ALIGN matrix[3][4];
550 float *input_gamma_table_r;
551 @@ -88,7 +93,7 @@ struct _qcms_transform {
552 struct precache_output *output_table_g;
553 struct precache_output *output_table_b;
554
555 - void (*transform_fn)(struct _qcms_transform *transform, unsigned char *s rc, unsigned char *dest, size_t length);
556 + void (*transform_fn)(struct _qcms_transform *transform, unsigned char *s rc, unsigned char *dest, size_t length, struct _qcms_format_type output_format);
557 };
558
559 struct matrix {
560 @@ -200,6 +205,14 @@ struct lutType { // used by lut8Type/lut16Type (mft2) only
561
562 float table_data[];
563 };
564 +
565 +struct vcgtType {
566 + /* data contains three gamma channels: R[length], then G[length], then
567 + * B[length]. */
568 + uint16_t *data;
569 + size_t length;
570 +};
571 +
572 #if 0
573 /* this is from an intial idea of having the struct correspond to the data in
574 * the file. I decided that it wasn't a good idea.
575 @@ -225,6 +238,7 @@ struct tag_value {
576 #define LAB_SIGNATURE 0x4C616220
577
578 struct _qcms_profile {
579 + char description[64];
580 uint32_t class;
581 uint32_t color_space;
582 uint32_t pcs;
583 @@ -241,6 +255,7 @@ struct _qcms_profile {
584 struct lutmABType *mAB;
585 struct lutmABType *mBA;
586 struct matrix chromaticAdaption;
587 + struct vcgtType vcgt;
588
589 struct precache_output *output_table_r;
590 struct precache_output *output_table_g;
591 @@ -280,18 +295,40 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CI E_xyY white_point, qcm
592 void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
593 unsigned char *src,
594 unsigned char *dest,
595 - size_t length);
596 + size_t length,
597 + qcms_format_type output_format);
598 void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
599 unsigned char *src,
600 unsigned char *dest,
601 - size_t length);
602 + size_t length,
603 + qcms_format_type output_format);
604 void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
605 unsigned char *src,
606 unsigned char *dest,
607 - size_t length);
608 + size_t length,
609 + qcms_format_type output_format);
610 void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
611 unsigned char *src,
612 unsigned char *dest,
613 - size_t length);
614 + size_t length,
615 + qcms_format_type output_format);
616
617 extern qcms_bool qcms_supports_iccv4;
618 +
619 +
620 +#ifdef _MSC_VER
621 +
622 +long __cdecl _InterlockedIncrement(long volatile *);
623 +long __cdecl _InterlockedDecrement(long volatile *);
624 +#pragma intrinsic(_InterlockedIncrement)
625 +#pragma intrinsic(_InterlockedDecrement)
626 +
627 +#define qcms_atomic_increment(x) _InterlockedIncrement((long volatile *)&x)
628 +#define qcms_atomic_decrement(x) _InterlockedDecrement((long volatile*)&x)
629 +
630 +#else
631 +
632 +#define qcms_atomic_increment(x) __sync_add_and_fetch(&x, 1)
633 +#define qcms_atomic_decrement(x) __sync_sub_and_fetch(&x, 1)
634 +
635 +#endif
636 diff --git a/third_party/qcms/src/qcmstypes.h b/third_party/qcms/src/qcmstypes.h
637 index 56d8de3..d58f691 100644
638 --- a/third_party/qcms/src/qcmstypes.h
639 +++ b/third_party/qcms/src/qcmstypes.h
640 @@ -22,37 +22,6 @@
641 #ifndef QCMS_TYPES_H
642 #define QCMS_TYPES_H
643
644 -#ifdef MOZ_QCMS
645 -
646 -#include "prtypes.h"
647 -
648 -/* prtypes.h defines IS_LITTLE_ENDIAN and IS_BIG ENDIAN */
649 -
650 -#if defined (__SVR4) && defined (__sun)
651 -/* int_types.h gets included somehow, so avoid redefining the types differently */
652 -#include <sys/int_types.h>
653 -#elif defined (_AIX)
654 -#include <sys/types.h>
655 -#elif !defined(ANDROID) && !defined(__OpenBSD__)
656 -typedef PRInt8 int8_t;
657 -typedef PRUint8 uint8_t;
658 -typedef PRInt16 int16_t;
659 -typedef PRUint16 uint16_t;
660 -typedef PRInt32 int32_t;
661 -typedef PRUint32 uint32_t;
662 -typedef PRInt64 int64_t;
663 -typedef PRUint64 uint64_t;
664 -
665 -#ifdef __OS2__
666 -/* OS/2's stdlib typdefs uintptr_t. So we'll just include that so we don't coll ide */
667 -#include <stdlib.h>
668 -#elif !defined(__intptr_t_defined) && !defined(_UINTPTR_T_DEFINED)
669 -typedef PRUptrdiff uintptr_t;
670 -#endif
671 -#endif
672 -
673 -#else // MOZ_QCMS
674 -
675 #if BYTE_ORDER == LITTLE_ENDIAN
676 #define IS_LITTLE_ENDIAN
677 #elif BYTE_ORDER == BIG_ENDIAN
678 @@ -75,7 +44,7 @@ typedef PRUptrdiff uintptr_t;
679
680 #if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || defined (_sgi ) || defined (__sun) || defined (sun) || defined (__digital__)
681 # include <inttypes.h>
682 -#elif defined (_MSC_VER)
683 +#elif defined (_MSC_VER) && _MSC_VER < 1600
684 typedef __int8 int8_t;
685 typedef unsigned __int8 uint8_t;
686 typedef __int16 int16_t;
687 @@ -87,7 +56,12 @@ typedef unsigned __int64 uint64_t;
688 #ifdef _WIN64
689 typedef unsigned __int64 uintptr_t;
690 #else
691 +#pragma warning(push)
692 +/* Disable benign redefinition of type warning 4142 */
693 +#pragma warning(disable:4142)
694 typedef unsigned long uintptr_t;
695 +/* Restore warnings */
696 +#pragma warning(pop)
697 #endif
698
699 #elif defined (_AIX)
700 @@ -96,8 +70,6 @@ typedef unsigned long uintptr_t;
701 # include <stdint.h>
702 #endif
703
704 -#endif
705 -
706 typedef qcms_bool bool;
707 #define true 1
708 #define false 0
709 diff --git a/third_party/qcms/src/transform-sse1.c b/third_party/qcms/src/transf orm-sse1.c
710 index 2f34db5..aaee1bf 100644
711 --- a/third_party/qcms/src/transform-sse1.c
712 +++ b/third_party/qcms/src/transform-sse1.c
713 @@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] =
714 void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
715 unsigned char *src,
716 unsigned char *dest,
717 - size_t length)
718 + size_t length,
719 + qcms_format_type output_format)
720 {
721 unsigned int i;
722 float (*mat)[4] = transform->matrix;
723 @@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *tran sform,
724
725 /* working variables */
726 __m128 vec_r, vec_g, vec_b, result;
727 + const int r_out = output_format.r;
728 + const int b_out = output_format.b;
729
730 /* CYA */
731 if (!length)
732 @@ -116,9 +119,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *tr ansform,
733 src += 3;
734
735 /* use calc'd indices to output RGB values */
736 - dest[0] = otdata_r[output[0]];
737 - dest[1] = otdata_g[output[1]];
738 - dest[2] = otdata_b[output[2]];
739 + dest[r_out] = otdata_r[output[0]];
740 + dest[1] = otdata_g[output[1]];
741 + dest[b_out] = otdata_b[output[2]];
742 dest += 3;
743 }
744
745 @@ -141,9 +144,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *tr ansform,
746 result = _mm_movehl_ps(result, result);
747 *((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
748
749 - dest[0] = otdata_r[output[0]];
750 - dest[1] = otdata_g[output[1]];
751 - dest[2] = otdata_b[output[2]];
752 + dest[r_out] = otdata_r[output[0]];
753 + dest[1] = otdata_g[output[1]];
754 + dest[b_out] = otdata_b[output[2]];
755
756 _mm_empty();
757 }
758 @@ -151,7 +154,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *tr ansform,
759 void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
760 unsigned char *src,
761 unsigned char *dest,
762 - size_t length)
763 + size_t length,
764 + qcms_format_type output_format)
765 {
766 unsigned int i;
767 float (*mat)[4] = transform->matrix;
768 @@ -187,6 +191,8 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *t ransform,
769
770 /* working variables */
771 __m128 vec_r, vec_g, vec_b, result;
772 + const int r_out = output_format.r;
773 + const int b_out = output_format.b;
774 unsigned char alpha;
775
776 /* CYA */
777 @@ -239,9 +245,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *t ransform,
778 src += 4;
779
780 /* use calc'd indices to output RGB values */
781 - dest[0] = otdata_r[output[0]];
782 - dest[1] = otdata_g[output[1]];
783 - dest[2] = otdata_b[output[2]];
784 + dest[r_out] = otdata_r[output[0]];
785 + dest[1] = otdata_g[output[1]];
786 + dest[b_out] = otdata_b[output[2]];
787 dest += 4;
788 }
789
790 @@ -266,9 +272,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *t ransform,
791 result = _mm_movehl_ps(result, result);
792 *((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
793
794 - dest[0] = otdata_r[output[0]];
795 - dest[1] = otdata_g[output[1]];
796 - dest[2] = otdata_b[output[2]];
797 + dest[r_out] = otdata_r[output[0]];
798 + dest[1] = otdata_g[output[1]];
799 + dest[b_out] = otdata_b[output[2]];
800
801 _mm_empty();
802 }
803 diff --git a/third_party/qcms/src/transform-sse2.c b/third_party/qcms/src/transf orm-sse2.c
804 index 6a5faf9..fa7f2d1 100644
805 --- a/third_party/qcms/src/transform-sse2.c
806 +++ b/third_party/qcms/src/transform-sse2.c
807 @@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] =
808 void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform,
809 unsigned char *src,
810 unsigned char *dest,
811 - size_t length)
812 + size_t length,
813 + qcms_format_type output_format)
814 {
815 unsigned int i;
816 float (*mat)[4] = transform->matrix;
817 @@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *tran sform,
818
819 /* working variables */
820 __m128 vec_r, vec_g, vec_b, result;
821 + const int r_out = output_format.r;
822 + const int b_out = output_format.b;
823
824 /* CYA */
825 if (!length)
826 @@ -114,9 +117,9 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *tr ansform,
827 src += 3;
828
829 /* use calc'd indices to output RGB values */
830 - dest[0] = otdata_r[output[0]];
831 - dest[1] = otdata_g[output[1]];
832 - dest[2] = otdata_b[output[2]];
833 + dest[r_out] = otdata_r[output[0]];
834 + dest[1] = otdata_g[output[1]];
835 + dest[b_out] = otdata_b[output[2]];
836 dest += 3;
837 }
838
839 @@ -137,15 +140,16 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform * transform,
840
841 _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result));
842
843 - dest[0] = otdata_r[output[0]];
844 - dest[1] = otdata_g[output[1]];
845 - dest[2] = otdata_b[output[2]];
846 + dest[r_out] = otdata_r[output[0]];
847 + dest[1] = otdata_g[output[1]];
848 + dest[b_out] = otdata_b[output[2]];
849 }
850
851 void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
852 unsigned char *src,
853 unsigned char *dest,
854 - size_t length)
855 + size_t length,
856 + qcms_format_type output_format)
857 {
858 unsigned int i;
859 float (*mat)[4] = transform->matrix;
860 @@ -181,6 +185,8 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *t ransform,
861
862 /* working variables */
863 __m128 vec_r, vec_g, vec_b, result;
864 + const int r_out = output_format.r;
865 + const int b_out = output_format.b;
866 unsigned char alpha;
867
868 /* CYA */
869 @@ -231,9 +237,9 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *t ransform,
870 src += 4;
871
872 /* use calc'd indices to output RGB values */
873 - dest[0] = otdata_r[output[0]];
874 - dest[1] = otdata_g[output[1]];
875 - dest[2] = otdata_b[output[2]];
876 + dest[r_out] = otdata_r[output[0]];
877 + dest[1] = otdata_g[output[1]];
878 + dest[b_out] = otdata_b[output[2]];
879 dest += 4;
880 }
881
882 @@ -256,7 +262,7 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *t ransform,
883
884 _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result));
885
886 - dest[0] = otdata_r[output[0]];
887 - dest[1] = otdata_g[output[1]];
888 - dest[2] = otdata_b[output[2]];
889 + dest[r_out] = otdata_r[output[0]];
890 + dest[1] = otdata_g[output[1]];
891 + dest[b_out] = otdata_b[output[2]];
892 }
893 diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c
894 index 9a6562b..f669a6b 100644
895 --- a/third_party/qcms/src/transform.c
896 +++ b/third_party/qcms/src/transform.c
897 @@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_poi nt,
898 static struct matrix
899 adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illum ination)
900 {
901 +#if defined (_MSC_VER)
902 +#pragma warning(push)
903 +/* Disable double to float truncation warning 4305 */
904 +#pragma warning(disable:4305)
905 +#endif
906 struct matrix lam_rigg = {{ // Bradford matrix
907 { 0.8951, 0.2664, -0.1614 },
908 { -0.7502, 1.7135, 0.0367 },
909 { 0.0389, -0.0685, 1.0296 }
910 }};
911 +#if defined (_MSC_VER)
912 +/* Restore warnings */
913 +#pragma warning(pop)
914 +#endif
915 return compute_chromatic_adaption(source_illumination, target_illuminati on, lam_rigg);
916 }
917
918 @@ -230,8 +239,11 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE _xyY white_point, qcm
919 }
920
921 #if 0
922 -static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
923 +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)
924 {
925 + const int r_out = output_format.r;
926 + const int b_out = output_format.b;
927 +
928 int i;
929 float (*mat)[4] = transform->matrix;
930 for (i=0; i<length; i++) {
931 @@ -251,15 +263,19 @@ static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned
932 float out_device_g = pow(out_linear_g, transform->out_gamma_g);
933 float out_device_b = pow(out_linear_b, transform->out_gamma_b);
934
935 - *dest++ = clamp_u8(255*out_device_r);
936 - *dest++ = clamp_u8(255*out_device_g);
937 - *dest++ = clamp_u8(255*out_device_b);
938 + dest[r_out] = clamp_u8(out_device_r*255);
939 + dest[1] = clamp_u8(out_device_g*255);
940 + dest[b_out] = clamp_u8(out_device_b*255);
941 + dest += 3;
942 }
943 }
944 #endif
945
946 -static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigne d char *src, unsigned char *dest, size_t length)
947 +static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigne d char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
948 {
949 + const int r_out = output_format.r;
950 + const int b_out = output_format.b;
951 +
952 unsigned int i;
953 for (i = 0; i < length; i++) {
954 float out_device_r, out_device_g, out_device_b;
955 @@ -267,13 +283,14 @@ static void qcms_transform_data_gray_out_lut(qcms_transfor m *transform, unsigned
956
957 float linear = transform->input_gamma_table_gray[device];
958
959 - out_device_r = lut_interp_linear(linear, transform->output_gamm a_lut_r, transform->output_gamma_lut_r_length);
960 + out_device_r = lut_interp_linear(linear, transform->output_gamma _lut_r, transform->output_gamma_lut_r_length);
961 out_device_g = lut_interp_linear(linear, transform->output_gamma _lut_g, transform->output_gamma_lut_g_length);
962 out_device_b = lut_interp_linear(linear, transform->output_gamma _lut_b, transform->output_gamma_lut_b_length);
963
964 - *dest++ = clamp_u8(out_device_r*255);
965 - *dest++ = clamp_u8(out_device_g*255);
966 - *dest++ = clamp_u8(out_device_b*255);
967 + dest[r_out] = clamp_u8(out_device_r*255);
968 + dest[1] = clamp_u8(out_device_g*255);
969 + dest[b_out] = clamp_u8(out_device_b*255);
970 + dest += 3;
971 }
972 }
973
974 @@ -283,8 +300,11 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
975 See: ftp://ftp.alvyray.com/Acrobat/17_Nonln.pdf
976 */
977
978 -static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsign ed char *src, unsigned char *dest, size_t length)
979 +static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsign ed char *src, unsigned char *dest, size_t length, qcms_format_type output_format )
980 {
981 + const int r_out = output_format.r;
982 + const int b_out = output_format.b;
983 +
984 unsigned int i;
985 for (i = 0; i < length; i++) {
986 float out_device_r, out_device_g, out_device_b;
987 @@ -293,20 +313,24 @@ static void qcms_transform_data_graya_out_lut(qcms_transfo rm *transform, unsigne
988
989 float linear = transform->input_gamma_table_gray[device];
990
991 - out_device_r = lut_interp_linear(linear, transform->output_gamm a_lut_r, transform->output_gamma_lut_r_length);
992 + out_device_r = lut_interp_linear(linear, transform->output_gamma _lut_r, transform->output_gamma_lut_r_length);
993 out_device_g = lut_interp_linear(linear, transform->output_gamma _lut_g, transform->output_gamma_lut_g_length);
994 out_device_b = lut_interp_linear(linear, transform->output_gamma _lut_b, transform->output_gamma_lut_b_length);
995
996 - *dest++ = clamp_u8(out_device_r*255);
997 - *dest++ = clamp_u8(out_device_g*255);
998 - *dest++ = clamp_u8(out_device_b*255);
999 - *dest++ = alpha;
1000 + dest[r_out] = clamp_u8(out_device_r*255);
1001 + dest[1] = clamp_u8(out_device_g*255);
1002 + dest[b_out] = clamp_u8(out_device_b*255);
1003 + dest[3] = alpha;
1004 + dest += 4;
1005 }
1006 }
1007
1008
1009 -static void qcms_transform_data_gray_out_precache(qcms_transform *transform, un signed char *src, unsigned char *dest, size_t length)
1010 +static void qcms_transform_data_gray_out_precache(qcms_transform *transform, un signed char *src, unsigned char *dest, size_t length, qcms_format_type output_fo rmat)
1011 {
1012 + const int r_out = output_format.r;
1013 + const int b_out = output_format.b;
1014 +
1015 unsigned int i;
1016 for (i = 0; i < length; i++) {
1017 unsigned char device = *src++;
1018 @@ -317,14 +341,19 @@ static void qcms_transform_data_gray_out_precache(qcms_tra nsform *transform, uns
1019 /* we could round here... */
1020 gray = linear * PRECACHE_OUTPUT_MAX;
1021
1022 - *dest++ = transform->output_table_r->data[gray];
1023 - *dest++ = transform->output_table_g->data[gray];
1024 - *dest++ = transform->output_table_b->data[gray];
1025 + dest[r_out] = transform->output_table_r->data[gray];
1026 + dest[1] = transform->output_table_g->data[gray];
1027 + dest[b_out] = transform->output_table_b->data[gray];
1028 + dest += 3;
1029 }
1030 }
1031
1032 -static void qcms_transform_data_graya_out_precache(qcms_transform *transform, u nsigned char *src, unsigned char *dest, size_t length)
1033 +
1034 +static void qcms_transform_data_graya_out_precache(qcms_transform *transform, u nsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_f ormat)
1035 {
1036 + const int r_out = output_format.r;
1037 + const int b_out = output_format.b;
1038 +
1039 unsigned int i;
1040 for (i = 0; i < length; i++) {
1041 unsigned char device = *src++;
1042 @@ -336,15 +365,19 @@ static void qcms_transform_data_graya_out_precache(qcms_tr ansform *transform, un
1043 /* we could round here... */
1044 gray = linear * PRECACHE_OUTPUT_MAX;
1045
1046 - *dest++ = transform->output_table_r->data[gray];
1047 - *dest++ = transform->output_table_g->data[gray];
1048 - *dest++ = transform->output_table_b->data[gray];
1049 - *dest++ = alpha;
1050 + dest[r_out] = transform->output_table_r->data[gray];
1051 + dest[1] = transform->output_table_g->data[gray];
1052 + dest[b_out] = transform->output_table_b->data[gray];
1053 + dest[3] = alpha;
1054 + dest += 4;
1055 }
1056 }
1057
1058 -static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
1059 +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)
1060 {
1061 + const int r_out = output_format.r;
1062 + const int b_out = output_format.b;
1063 +
1064 unsigned int i;
1065 float (*mat)[4] = transform->matrix;
1066 for (i = 0; i < length; i++) {
1067 @@ -370,14 +403,18 @@ static void qcms_transform_data_rgb_out_lut_precache(qcms_ transform *transform,
1068 g = out_linear_g * PRECACHE_OUTPUT_MAX;
1069 b = out_linear_b * PRECACHE_OUTPUT_MAX;
1070
1071 - *dest++ = transform->output_table_r->data[r];
1072 - *dest++ = transform->output_table_g->data[g];
1073 - *dest++ = transform->output_table_b->data[b];
1074 + dest[r_out] = transform->output_table_r->data[r];
1075 + dest[1] = transform->output_table_g->data[g];
1076 + dest[b_out] = transform->output_table_b->data[b];
1077 + dest += 3;
1078 }
1079 }
1080
1081 -static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform , unsigned char *src, unsigned char *dest, size_t length)
1082 +static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform , unsigned char *src, unsigned char *dest, size_t length, qcms_format_type outpu t_format)
1083 {
1084 + const int r_out = output_format.r;
1085 + const int b_out = output_format.b;
1086 +
1087 unsigned int i;
1088 float (*mat)[4] = transform->matrix;
1089 for (i = 0; i < length; i++) {
1090 @@ -404,16 +441,21 @@ static void qcms_transform_data_rgba_out_lut_precache(qcms _transform *transform,
1091 g = out_linear_g * PRECACHE_OUTPUT_MAX;
1092 b = out_linear_b * PRECACHE_OUTPUT_MAX;
1093
1094 - *dest++ = transform->output_table_r->data[r];
1095 - *dest++ = transform->output_table_g->data[g];
1096 - *dest++ = transform->output_table_b->data[b];
1097 - *dest++ = alpha;
1098 + dest[r_out] = transform->output_table_r->data[r];
1099 + dest[1] = transform->output_table_g->data[g];
1100 + dest[b_out] = transform->output_table_b->data[b];
1101 + dest[3] = alpha;
1102 + dest += 4;
1103 }
1104 }
1105
1106 // Not used
1107 /*
1108 -static void qcms_transform_data_clut(qcms_transform *transform, unsigned char * src, unsigned char *dest, size_t length) {
1109 +static void qcms_transform_data_clut(qcms_transform *transform, unsigned char * src, unsigned char *dest, size_t length, qcms_format_type output_format)
1110 +{
1111 + const int r_out = output_format.r;
1112 + const int b_out = output_format.b;
1113 +
1114 unsigned int i;
1115 int xy_len = 1;
1116 int x_len = transform->grid_size;
1117 @@ -462,15 +504,20 @@ static void qcms_transform_data_clut(qcms_transform *trans form, unsigned char *s
1118 float b_y2 = lerp(b_x3, b_x4, y_d);
1119 float clut_b = lerp(b_y1, b_y2, z_d);
1120
1121 - *dest++ = clamp_u8(clut_r*255.0f);
1122 - *dest++ = clamp_u8(clut_g*255.0f);
1123 - *dest++ = clamp_u8(clut_b*255.0f);
1124 - }
1125 + dest[r_out] = clamp_u8(clut_r*255.0f);
1126 + dest[1] = clamp_u8(clut_g*255.0f);
1127 + dest[b_out] = clamp_u8(clut_b*255.0f);
1128 + dest += 3;
1129 + }
1130 }
1131 */
1132
1133 // Using lcms' tetra interpolation algorithm.
1134 -static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsi gned char *src, unsigned char *dest, size_t length) {
1135 +static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsi gned char *src, unsigned char *dest, size_t length, qcms_format_type output_form at)
1136 +{
1137 + const int r_out = output_format.r;
1138 + const int b_out = output_format.b;
1139 +
1140 unsigned int i;
1141 int xy_len = 1;
1142 int x_len = transform->grid_size;
1143 @@ -577,15 +624,20 @@ static void qcms_transform_data_tetra_clut_rgba(qcms_trans form *transform, unsig
1144 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
1145 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
1146
1147 - *dest++ = clamp_u8(clut_r*255.0f);
1148 - *dest++ = clamp_u8(clut_g*255.0f);
1149 - *dest++ = clamp_u8(clut_b*255.0f);
1150 - *dest++ = in_a;
1151 - }
1152 + dest[r_out] = clamp_u8(clut_r*255.0f);
1153 + dest[1] = clamp_u8(clut_g*255.0f);
1154 + dest[b_out] = clamp_u8(clut_b*255.0f);
1155 + dest[3] = in_a;
1156 + dest += 4;
1157 + }
1158 }
1159
1160 // Using lcms' tetra interpolation code.
1161 -static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
1162 +static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
1163 +{
1164 + const int r_out = output_format.r;
1165 + const int b_out = output_format.b;
1166 +
1167 unsigned int i;
1168 int xy_len = 1;
1169 int x_len = transform->grid_size;
1170 @@ -691,14 +743,18 @@ static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned c
1171 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
1172 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
1173
1174 - *dest++ = clamp_u8(clut_r*255.0f);
1175 - *dest++ = clamp_u8(clut_g*255.0f);
1176 - *dest++ = clamp_u8(clut_b*255.0f);
1177 - }
1178 + dest[r_out] = clamp_u8(clut_r*255.0f);
1179 + dest[1] = clamp_u8(clut_g*255.0f);
1180 + dest[b_out] = clamp_u8(clut_b*255.0f);
1181 + dest += 3;
1182 + }
1183 }
1184
1185 -static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
1186 +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)
1187 {
1188 + const int r_out = output_format.r;
1189 + const int b_out = output_format.b;
1190 +
1191 unsigned int i;
1192 float (*mat)[4] = transform->matrix;
1193 for (i = 0; i < length; i++) {
1194 @@ -726,14 +782,18 @@ static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned
1195 out_device_b = lut_interp_linear(out_linear_b,
1196 transform->output_gamma_lut_b, transform->output _gamma_lut_b_length);
1197
1198 - *dest++ = clamp_u8(out_device_r*255);
1199 - *dest++ = clamp_u8(out_device_g*255);
1200 - *dest++ = clamp_u8(out_device_b*255);
1201 + dest[r_out] = clamp_u8(out_device_r*255);
1202 + dest[1] = clamp_u8(out_device_g*255);
1203 + dest[b_out] = clamp_u8(out_device_b*255);
1204 + dest += 3;
1205 }
1206 }
1207
1208 -static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigne d char *src, unsigned char *dest, size_t length)
1209 +static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigne d char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
1210 {
1211 + const int r_out = output_format.r;
1212 + const int b_out = output_format.b;
1213 +
1214 unsigned int i;
1215 float (*mat)[4] = transform->matrix;
1216 for (i = 0; i < length; i++) {
1217 @@ -762,16 +822,20 @@ static void qcms_transform_data_rgba_out_lut(qcms_transfor m *transform, unsigned
1218 out_device_b = lut_interp_linear(out_linear_b,
1219 transform->output_gamma_lut_b, transform->output _gamma_lut_b_length);
1220
1221 - *dest++ = clamp_u8(out_device_r*255);
1222 - *dest++ = clamp_u8(out_device_g*255);
1223 - *dest++ = clamp_u8(out_device_b*255);
1224 - *dest++ = alpha;
1225 + dest[r_out] = clamp_u8(out_device_r*255);
1226 + dest[1] = clamp_u8(out_device_g*255);
1227 + dest[b_out] = clamp_u8(out_device_b*255);
1228 + dest[3] = alpha;
1229 + dest += 4;
1230 }
1231 }
1232
1233 #if 0
1234 -static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsig ned char *src, unsigned char *dest, size_t length)
1235 +static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsig ned char *src, unsigned char *dest, size_t length, qcms_format_type output_forma t)
1236 {
1237 + const int r_out = output_format.r;
1238 + const int b_out = output_format.b;
1239 +
1240 int i;
1241 float (*mat)[4] = transform->matrix;
1242 for (i = 0; i < length; i++) {
1243 @@ -787,16 +851,25 @@ static void qcms_transform_data_rgb_out_linear(qcms_transf orm *transform, unsign
1244 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m at[2][1]*linear_b;
1245 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m at[2][2]*linear_b;
1246
1247 - *dest++ = clamp_u8(out_linear_r*255);
1248 - *dest++ = clamp_u8(out_linear_g*255);
1249 - *dest++ = clamp_u8(out_linear_b*255);
1250 + dest[r_out] = clamp_u8(out_linear_r*255);
1251 + dest[1] = clamp_u8(out_linear_g*255);
1252 + dest[b_out] = clamp_u8(out_linear_b*255);
1253 + dest += 3;
1254 }
1255 }
1256 #endif
1257
1258 +/*
1259 + * If users create and destroy objects on different threads, even if the same
1260 + * objects aren't used on different threads at the same time, we can still run
1261 + * in to trouble with refcounts if they aren't atomic.
1262 + *
1263 + * This can lead to us prematurely deleting the precache if threads get unlucky
1264 + * and write the wrong value to the ref count.
1265 + */
1266 static struct precache_output *precache_reference(struct precache_output *p)
1267 {
1268 - p->ref_count++;
1269 + qcms_atomic_increment(p->ref_count);
1270 return p;
1271 }
1272
1273 @@ -810,12 +883,12 @@ static struct precache_output *precache_create()
1274
1275 void precache_release(struct precache_output *p)
1276 {
1277 - if (--p->ref_count == 0) {
1278 + if (qcms_atomic_decrement(p->ref_count) == 0) {
1279 free(p);
1280 }
1281 }
1282
1283 -#ifdef HAS_POSIX_MEMALIGN
1284 +#ifdef HAVE_POSIX_MEMALIGN
1285 static qcms_transform *transform_alloc(void)
1286 {
1287 qcms_transform *t;
1288 @@ -994,13 +1067,15 @@ void qcms_profile_precache_output_transform(qcms_profile *profile)
1289 if (profile->color_space != RGB_SIGNATURE)
1290 return;
1291
1292 - /* don't precache since we will use the B2A LUT */
1293 - if (profile->B2A0)
1294 - return;
1295 + if (qcms_supports_iccv4) {
1296 + /* don't precache since we will use the B2A LUT */
1297 + if (profile->B2A0)
1298 + return;
1299
1300 - /* don't precache since we will use the mBA LUT */
1301 - if (profile->mBA)
1302 - return;
1303 + /* don't precache since we will use the mBA LUT */
1304 + if (profile->mBA)
1305 + return;
1306 + }
1307
1308 /* don't precache if we do not have the TRC curves */
1309 if (!profile->redTRC || !profile->greenTRC || !profile->blueTRC)
1310 @@ -1043,28 +1118,31 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_tr ansform *transform, qcms
1311 float* src = NULL;
1312 float* dest = NULL;
1313 float* lut = NULL;
1314 + float inverse;
1315
1316 src = malloc(lutSize*sizeof(float));
1317 dest = malloc(lutSize*sizeof(float));
1318
1319 if (src && dest) {
1320 - /* Prepare a list of points we want to sample */
1321 + /* Prepare a list of points we want to sample: x, y, z order */
1322 l = 0;
1323 + inverse = 1 / (float)(samples-1);
1324 for (x = 0; x < samples; x++) {
1325 for (y = 0; y < samples; y++) {
1326 for (z = 0; z < samples; z++) {
1327 - src[l++] = x / (float)(samples-1);
1328 - src[l++] = y / (float)(samples-1);
1329 - src[l++] = z / (float)(samples-1);
1330 + src[l++] = x * inverse; // r
1331 + src[l++] = y * inverse; // g
1332 + src[l++] = z * inverse; // b
1333 }
1334 }
1335 }
1336
1337 lut = qcms_chain_transform(in, out, src, dest, lutSize);
1338 +
1339 if (lut) {
1340 - transform->r_clut = &lut[0];
1341 - transform->g_clut = &lut[1];
1342 - transform->b_clut = &lut[2];
1343 + transform->r_clut = &lut[0]; // r
1344 + transform->g_clut = &lut[1]; // g
1345 + transform->b_clut = &lut[2]; // b
1346 transform->grid_size = samples;
1347 if (in_type == QCMS_DATA_RGBA_8) {
1348 transform->transform_fn = qcms_transform_data_te tra_clut_rgba;
1349 @@ -1074,11 +1152,12 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_tr ansform *transform, qcms
1350 }
1351 }
1352
1353 -
1354 - //XXX: qcms_modular_transform_data may return either the src or dest buf fer. If so it must not be free-ed
1355 + // XXX: qcms_modular_transform_data may return the lut in either the src or the
1356 + // dest buffer. If so, it must not be free-ed.
1357 if (src && lut != src) {
1358 free(src);
1359 - } else if (dest && lut != src) {
1360 + }
1361 + if (dest && lut != dest) {
1362 free(dest);
1363 }
1364
1365 @@ -1088,6 +1167,71 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_tra nsform *transform, qcms
1366 return transform;
1367 }
1368
1369 +/* Create a transform LUT using the given number of sample points. The transfor m LUT data is stored
1370 + in the output (cube) in bgra format in zyx sample order. */
1371 +qcms_bool qcms_transform_create_LUT_zyx_bgra(qcms_profile *in, qcms_profile *ou t, qcms_intent intent,
1372 + int samples, unsigned char* cube)
1373 +{
1374 + uint16_t z,y,x;
1375 + uint32_t l,index;
1376 + uint32_t lutSize = 3 * samples * samples * samples;
1377 +
1378 + float* src = NULL;
1379 + float* dest = NULL;
1380 + float* lut = NULL;
1381 + float inverse;
1382 +
1383 + src = malloc(lutSize*sizeof(float));
1384 + dest = malloc(lutSize*sizeof(float));
1385 +
1386 + if (src && dest) {
1387 + /* Prepare a list of points we want to sample: z, y, x order */
1388 + l = 0;
1389 + inverse = 1 / (float)(samples-1);
1390 + for (z = 0; z < samples; z++) {
1391 + for (y = 0; y < samples; y++) {
1392 + for (x = 0; x < samples; x++) {
1393 + src[l++] = x * inverse; // r
1394 + src[l++] = y * inverse; // g
1395 + src[l++] = z * inverse; // b
1396 + }
1397 + }
1398 + }
1399 +
1400 + lut = qcms_chain_transform(in, out, src, dest, lutSize);
1401 +
1402 + if (lut) {
1403 + index = l = 0;
1404 + for (z = 0; z < samples; z++) {
1405 + for (y = 0; y < samples; y++) {
1406 + for (x = 0; x < samples; x++) {
1407 + cube[index++] = (int)floorf(lut[ l + 2] * 255.0f + 0.5f); // b
1408 + cube[index++] = (int)floorf(lut[ l + 1] * 255.0f + 0.5f); // g
1409 + cube[index++] = (int)floorf(lut[ l + 0] * 255.0f + 0.5f); // r
1410 + cube[index++] = 255; // a
1411 + l += 3;
1412 + }
1413 + }
1414 + }
1415 + }
1416 + }
1417 +
1418 + // XXX: qcms_modular_transform_data may return the lut data in either th e src or
1419 + // dest buffer so free src, dest, and lut with care.
1420 +
1421 + if (src && lut != src)
1422 + free(src);
1423 + if (dest && lut != dest)
1424 + free(dest);
1425 +
1426 + if (lut) {
1427 + free(lut);
1428 + return true;
1429 + }
1430 +
1431 + return false;
1432 +}
1433 +
1434 #define NO_MEM_TRANSFORM NULL
1435
1436 qcms_transform* qcms_transform_create(
1437 @@ -1157,14 +1301,14 @@ qcms_transform* qcms_transform_create(
1438 return NULL;
1439 }
1440 if (precache) {
1441 -#ifdef X86
1442 +#if defined(SSE2_ENABLE) && defined(X86)
1443 if (sse_version_available() >= 2) {
1444 if (in_type == QCMS_DATA_RGB_8)
1445 transform->transform_fn = qcms_transform_dat a_rgb_out_lut_sse2;
1446 else
1447 transform->transform_fn = qcms_transform_dat a_rgba_out_lut_sse2;
1448
1449 -#if !(defined(_MSC_VER) && defined(_M_AMD64))
1450 +#if defined(SSE2_ENABLE) && !(defined(_MSC_VER) && defined(_M_AMD64))
1451 /* Microsoft Compiler for x64 doesn't support MMX.
1452 * SSE code uses MMX so that we disable on x64 */
1453 } else
1454 @@ -1256,13 +1400,34 @@ qcms_transform* qcms_transform_create(
1455 return transform;
1456 }
1457
1458 -#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
1459 +/* __force_align_arg_pointer__ is an x86-only attribute, and gcc/clang warns on unused
1460 + * attributes. Don't use this on ARM or AMD64. __has_attribute can detect the p resence
1461 + * of the attribute but is currently only supported by clang */
1462 +#if defined(__has_attribute)
1463 +#define HAS_FORCE_ALIGN_ARG_POINTER __has_attribute(__force_align_arg_pointer__ )
1464 +#elif defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) && !defi ned(__arm__) && !defined(__mips__)
1465 +#define HAS_FORCE_ALIGN_ARG_POINTER 1
1466 +#else
1467 +#define HAS_FORCE_ALIGN_ARG_POINTER 0
1468 +#endif
1469 +
1470 +#if HAS_FORCE_ALIGN_ARG_POINTER
1471 /* we need this to avoid crashes when gcc assumes the stack is 128bit aligned * /
1472 __attribute__((__force_align_arg_pointer__))
1473 #endif
1474 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size _t length)
1475 {
1476 - transform->transform_fn(transform, src, dest, length);
1477 + static const struct _qcms_format_type output_rgbx = { 0, 2 };
1478 +
1479 + transform->transform_fn(transform, src, dest, length, output_rgbx);
1480 +}
1481 +
1482 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type)
1483 +{
1484 + static const struct _qcms_format_type output_rgbx = { 0, 2 };
1485 + static const struct _qcms_format_type output_bgrx = { 2, 0 };
1486 +
1487 + transform->transform_fn(transform, src, dest, length, type == QCMS_OUTPU T_BGRX ? output_bgrx : output_rgbx);
1488 }
1489
1490 qcms_bool qcms_supports_iccv4;
1491 diff --git a/third_party/qcms/src/transform_util.c b/third_party/qcms/src/transf orm_util.c
1492 index e8447e5..5eeafa2 100644
1493 --- a/third_party/qcms/src/transform_util.c
1494 +++ b/third_party/qcms/src/transform_util.c
1495 @@ -36,7 +36,7 @@
1496
1497 /* value must be a value between 0 and 1 */
1498 //XXX: is the above a good restriction to have?
1499 -float lut_interp_linear(double value, uint16_t *table, int length)
1500 +float lut_interp_linear(double value, uint16_t *table, size_t length)
1501 {
1502 int upper, lower;
1503 value = value * (length - 1); // scale to length of the array
1504 @@ -49,11 +49,11 @@ float lut_interp_linear(double value, uint16_t *table, int l ength)
1505 }
1506
1507 /* same as above but takes and returns a uint16_t value representing a range fr om 0..1 */
1508 -uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length)
1509 +uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t leng th)
1510 {
1511 /* Start scaling input_value to the length of the array: 65535*(length-1 ).
1512 * We'll divide out the 65535 next */
1513 - uint32_t value = (input_value * (length - 1));
1514 + uintptr_t value = (input_value * (length - 1));
1515 uint32_t upper = (value + 65534) / 65535; /* equivalent to ceil(value/65 535) */
1516 uint32_t lower = value / 65535; /* equivalent to floor(value/6 5535) */
1517 /* interp is the distance from upper to value scaled to 0..65535 */
1518 @@ -67,11 +67,11 @@ uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length)
1519 /* same as above but takes an input_value from 0..PRECACHE_OUTPUT_MAX
1520 * and returns a uint8_t value representing a range from 0..1 */
1521 static
1522 -uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table , int length)
1523 +uint8_t lut_interp_linear_precache_output(uint32_t input_value, uint16_t *table , size_t length)
1524 {
1525 /* Start scaling input_value to the length of the array: PRECACHE_OUTPUT _MAX*(length-1).
1526 * We'll divide out the PRECACHE_OUTPUT_MAX next */
1527 - uint32_t value = (input_value * (length - 1));
1528 + uintptr_t value = (input_value * (length - 1));
1529
1530 /* equivalent to ceil(value/PRECACHE_OUTPUT_MAX) */
1531 uint32_t upper = (value + PRECACHE_OUTPUT_MAX-1) / PRECACHE_OUTPUT_MAX;
1532 @@ -91,7 +91,7 @@ uint8_t lut_interp_linear_precache_output(uint32_t input_value , uint16_t *table,
1533
1534 /* value must be a value between 0 and 1 */
1535 //XXX: is the above a good restriction to have?
1536 -float lut_interp_linear_float(float value, float *table, int length)
1537 +float lut_interp_linear_float(float value, float *table, size_t length)
1538 {
1539 int upper, lower;
1540 value = value * (length - 1);
1541 @@ -235,6 +235,21 @@ float u8Fixed8Number_to_float(uint16_t x)
1542 return x/256.;
1543 }
1544
1545 +/* The SSE2 code uses min & max which let NaNs pass through.
1546 + We want to try to prevent that here by ensuring that
1547 + gamma table is within expected values. */
1548 +void validate_gamma_table(float gamma_table[256])
1549 +{
1550 + int i;
1551 + for (i = 0; i < 256; i++) {
1552 + // Note: we check that the gamma is not in range
1553 + // instead of out of range so that we catch NaNs
1554 + if (!(gamma_table[i] >= 0.f && gamma_table[i] <= 1.f)) {
1555 + gamma_table[i] = 0.f;
1556 + }
1557 + }
1558 +}
1559 +
1560 float *build_input_gamma_table(struct curveType *TRC)
1561 {
1562 float *gamma_table;
1563 @@ -254,7 +269,10 @@ float *build_input_gamma_table(struct curveType *TRC)
1564 }
1565 }
1566 }
1567 - return gamma_table;
1568 +
1569 + validate_gamma_table(gamma_table);
1570 +
1571 + return gamma_table;
1572 }
1573
1574 struct matrix build_colorant_matrix(qcms_profile *p)
1575 @@ -295,7 +313,7 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len
1576
1577 NumZeroes = 0;
1578 while (LutTable[NumZeroes] == 0 && NumZeroes < length-1)
1579 - NumZeroes++;
1580 + NumZeroes++;
1581
1582 // There are no zeros at the beginning and we are trying to find a zero , so
1583 // return anything. It seems zero would be the less destructive choice
1584 @@ -305,26 +323,37 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16 _t LutTable[], int len
1585
1586 NumPoles = 0;
1587 while (LutTable[length-1- NumPoles] == 0xFFFF && NumPoles < length-1)
1588 - NumPoles++;
1589 + NumPoles++;
1590
1591 // Does the curve belong to this case?
1592 if (NumZeroes > 1 || NumPoles > 1)
1593 - {
1594 - int a, b;
1595 + {
1596 + int a, b, sample;
1597
1598 - // Identify if value fall downto 0 or FFFF zone
1599 + // Identify if value fall downto 0 or FFFF zone
1600 if (Value == 0) return 0;
1601 - // if (Value == 0xFFFF) return 0xFFFF;
1602 + // if (Value == 0xFFFF) return 0xFFFF;
1603 + sample = (length-1) * ((double) Value * (1./65535.));
1604 + if (LutTable[sample] == 0)
1605 + return 0;
1606 + if (LutTable[sample] == 0xffff)
1607 + return 0xffff;
1608
1609 // else restrict to valid zone
1610
1611 - a = ((NumZeroes-1) * 0xFFFF) / (length-1);
1612 + a = ((NumZeroes-1) * 0xFFFF) / (length-1);
1613 b = ((length-1 - NumPoles) * 0xFFFF) / (length-1);
1614 -
1615 +
1616 l = a - 1;
1617 r = b + 1;
1618 - }
1619
1620 + // Ensure a valid binary search range
1621 +
1622 + if (l < 1)
1623 + l = 1;
1624 + if (r > 0x10000)
1625 + r = 0x10000;
1626 + }
1627
1628 // Seems not a degenerated case... apply binary search
1629
1630 @@ -332,12 +361,12 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16 _t LutTable[], int len
1631
1632 x = (l + r) / 2;
1633
1634 - res = (int) lut_interp_linear16((uint16_fract_t) (x-1), LutTable , length);
1635 + res = (int) lut_interp_linear16((uint16_fract_t) (x-1), LutTabl e, length);
1636
1637 if (res == Value) {
1638
1639 - // Found exact match.
1640 -
1641 + // Found exact match.
1642 +
1643 return (uint16_fract_t) (x - 1);
1644 }
1645
1646 @@ -347,14 +376,14 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16 _t LutTable[], int len
1647
1648 // Not found, should we interpolate?
1649
1650 -
1651 +
1652 // Get surrounding nodes
1653 -
1654 +
1655 val2 = (length-1) * ((double) (x - 1) / 65535.0);
1656
1657 cell0 = (int) floor(val2);
1658 cell1 = (int) ceil(val2);
1659 -
1660 +
1661 if (cell0 == cell1) return (uint16_fract_t) x;
1662
1663 y0 = LutTable[cell0] ;
1664 @@ -373,8 +402,7 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len
1665 if (f < 0.0) return (uint16_fract_t) 0;
1666 if (f >= 65535.0) return (uint16_fract_t) 0xFFFF;
1667
1668 - return (uint16_fract_t) floor(f + 0.5);
1669 -
1670 + return (uint16_fract_t) floor(f + 0.5);
1671 }
1672
1673 /*
1674 @@ -390,7 +418,7 @@ uint16_fract_t lut_inverse_interp16(uint16_t Value, uint16_t LutTable[], int len
1675 which has an maximum error of about 9855 (pixel difference of ~38.346)
1676
1677 For now, we punt the decision of output size to the caller. */
1678 -static uint16_t *invert_lut(uint16_t *table, int length, int out_length)
1679 +static uint16_t *invert_lut(uint16_t *table, int length, size_t out_length)
1680 {
1681 int i;
1682 /* for now we invert the lut by creating a lut of size out_length
1683 diff --git a/third_party/qcms/src/transform_util.h b/third_party/qcms/src/transf orm_util.h
1684 index 8f358a8..de465f4 100644
1685 --- a/third_party/qcms/src/transform_util.h
1686 +++ b/third_party/qcms/src/transform_util.h
1687 @@ -31,9 +31,9 @@
1688 //XXX: could use a bettername
1689 typedef uint16_t uint16_fract_t;
1690
1691 -float lut_interp_linear(double value, uint16_t *table, int length);
1692 -float lut_interp_linear_float(float value, float *table, int length);
1693 -uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length) ;
1694 +float lut_interp_linear(double value, uint16_t *table, size_t length);
1695 +float lut_interp_linear_float(float value, float *table, size_t length);
1696 +uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t leng th);
1697
1698
1699 static inline float lerp(float a, float b, float t)
OLDNEW
« no previous file with comments | « third_party/qcms/README.chromium ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698