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