OLD | NEW |
1 diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c | 1 diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c |
2 index 36b7011..aca19d3 100644 | 2 index 36b7011..6cec34a 100644 |
3 --- a/third_party/qcms/src/iccread.c | 3 --- a/third_party/qcms/src/iccread.c |
4 +++ b/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) | 5 @@ -266,7 +266,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) |
6 if (profile->color_space != RGB_SIGNATURE) | 6 if (profile->color_space != RGB_SIGNATURE) |
7 return false; | 7 return false; |
8 | 8 |
9 - if (profile->A2B0 || profile->B2A0) | 9 - if (profile->A2B0 || profile->B2A0) |
10 + if (qcms_supports_iccv4 && (profile->A2B0 || profile->B2A0)) | 10 + if (qcms_supports_iccv4 && (profile->A2B0 || profile->B2A0)) |
11 return false; | 11 return false; |
12 | 12 |
(...skipping 22 matching lines...) Expand all Loading... |
35 for (i = 0; i < 3; ++i) { | 35 for (i = 0; i < 3; ++i) { |
36 if (!(((sum[i] - tolerance[i]) <= target[i]) && | 36 if (!(((sum[i] - tolerance[i]) <= target[i]) && |
37 @@ -331,6 +340,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) | 37 @@ -331,6 +340,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) |
38 #define TAG_A2B0 0x41324230 | 38 #define TAG_A2B0 0x41324230 |
39 #define TAG_B2A0 0x42324130 | 39 #define TAG_B2A0 0x42324130 |
40 #define TAG_CHAD 0x63686164 | 40 #define TAG_CHAD 0x63686164 |
41 +#define TAG_desc 0x64657363 | 41 +#define TAG_desc 0x64657363 |
42 | 42 |
43 static struct tag *find_tag(struct tag_index index, uint32_t tag_id) | 43 static struct tag *find_tag(struct tag_index index, uint32_t tag_id) |
44 { | 44 { |
45 @@ -344,6 +354,47 @@ static struct tag *find_tag(struct tag_index index, uint32_
t tag_id) | 45 @@ -344,6 +354,152 @@ static struct tag *find_tag(struct tag_index index, uint32
_t tag_id) |
46 return tag; | 46 return tag; |
47 } | 47 } |
48 | 48 |
49 +#define DESC_TYPE 0x64657363 // 'desc' | 49 +#define DESC_TYPE 0x64657363 // 'desc' |
50 +#define MLUC_TYPE 0x6d6c7563 // 'mluc' | 50 +#define MLUC_TYPE 0x6d6c7563 // 'mluc' |
| 51 +#define MMOD_TYPE 0x6D6D6F64 // 'mmod' |
51 + | 52 + |
52 +static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, st
ruct tag_index index, uint32_t tag_id) | 53 +static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, st
ruct tag_index index, uint32_t tag_id) |
53 +{ | 54 +{ |
54 + struct tag *tag = find_tag(index, tag_id); | 55 + struct tag *tag = find_tag(index, tag_id); |
55 + if (tag) { | 56 + if (tag) { |
56 + const uint32_t limit = sizeof profile->description; | 57 + const uint32_t limit = sizeof profile->description; |
57 + uint32_t offset = tag->offset; | 58 + uint32_t offset = tag->offset; |
58 + uint32_t type = read_u32(src, offset); | 59 + uint32_t type = read_u32(src, offset); |
59 + uint32_t length = read_u32(src, offset+8); | 60 + uint32_t length = read_u32(src, offset+8); |
60 +» » uint32_t i, description; | 61 +» » uint32_t i, description_offset; |
| 62 +» » bool mluc = false; |
61 + if (length && type == MLUC_TYPE) { | 63 + if (length && type == MLUC_TYPE) { |
62 + length = read_u32(src, offset+20); | 64 + length = read_u32(src, offset+20); |
63 + if (!length || (length & 1) || (read_u32(src, offset+12)
!= 12)) | 65 + if (!length || (length & 1) || (read_u32(src, offset+12)
!= 12)) |
64 + goto invalid_desc_tag; | 66 + goto invalid_desc_tag; |
65 +» » » description = offset + read_u32(src, offset+24); | 67 +» » » description_offset = offset + read_u32(src, offset+24); |
66 + if (!src->valid) | 68 + if (!src->valid) |
67 + goto invalid_desc_tag; | 69 + goto invalid_desc_tag; |
| 70 + mluc = true; |
68 + } else if (length && type == DESC_TYPE) { | 71 + } else if (length && type == DESC_TYPE) { |
69 +» » » description = offset + 12; | 72 +» » » description_offset = offset + 12; |
70 + } else { | 73 + } else { |
71 + goto invalid_desc_tag; | 74 + goto invalid_desc_tag; |
72 + } | 75 + } |
73 + if (length >= limit) | 76 + if (length >= limit) |
74 + length = limit - 1; | 77 + length = limit - 1; |
75 +» » for (i = 0; i < length; ++i) | 78 +» » for (i = 0; i < length; ++i) { |
76 +» » » profile->description[i] = read_u8(src, description+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 +» » } |
77 + profile->description[length] = 0; | 86 + profile->description[length] = 0; |
78 + } else { | 87 + } else { |
79 + goto invalid_desc_tag; | 88 + goto invalid_desc_tag; |
80 + } | 89 + } |
81 + | 90 + |
82 + if (src->valid) | 91 + if (src->valid) |
83 + return true; | 92 + return true; |
84 + | 93 + |
85 +invalid_desc_tag: | 94 +invalid_desc_tag: |
86 + invalid_source(src, "invalid description"); | 95 + invalid_source(src, "invalid description"); |
87 + return false; | 96 + return false; |
88 +} | 97 +} |
89 + | 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 + |
90 #define XYZ_TYPE 0x58595a20 // 'XYZ ' | 195 #define XYZ_TYPE 0x58595a20 // 'XYZ ' |
91 #define CURVE_TYPE 0x63757276 // 'curv' | 196 #define CURVE_TYPE 0x63757276 // 'curv' |
92 #define PARAMETRIC_CURVE_TYPE 0x70617261 // 'para' | 197 #define PARAMETRIC_CURVE_TYPE 0x70617261 // 'para' |
93 @@ -402,7 +453,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *
src, struct tag_inde | 198 @@ -402,7 +558,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *
src, struct tag_inde |
94 // present that are not part of the tag_index. | 199 // present that are not part of the tag_index. |
95 static struct curveType *read_curveType(struct mem_source *src, uint32_t offset
, uint32_t *len) | 200 static struct curveType *read_curveType(struct mem_source *src, uint32_t offset
, uint32_t *len) |
96 { | 201 { |
97 - static const size_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7}; | 202 - static const size_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7}; |
98 + static const uint32_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7}; | 203 + static const uint32_t COUNT_TO_LENGTH[5] = {1, 3, 4, 5, 7}; |
99 struct curveType *curve = NULL; | 204 struct curveType *curve = NULL; |
100 uint32_t type = read_u32(src, offset); | 205 uint32_t type = read_u32(src, offset); |
101 uint32_t count; | 206 uint32_t count; |
102 @@ -484,19 +535,23 @@ static void read_nested_curveType(struct mem_source *src,
struct curveType *(*cu | 207 @@ -484,19 +640,23 @@ static void read_nested_curveType(struct mem_source *src,
struct curveType *(*cu |
103 uint32_t channel_offset = 0; | 208 uint32_t channel_offset = 0; |
104 int i; | 209 int i; |
105 for (i = 0; i < num_channels; i++) { | 210 for (i = 0; i < num_channels; i++) { |
106 - uint32_t tag_len; | 211 - uint32_t tag_len; |
107 + uint32_t tag_len = ~0; | 212 + uint32_t tag_len = ~0; |
108 | 213 |
109 (*curveArray)[i] = read_curveType(src, curve_offset + channel_of
fset, &tag_len); | 214 (*curveArray)[i] = read_curveType(src, curve_offset + channel_of
fset, &tag_len); |
110 if (!(*curveArray)[i]) { | 215 if (!(*curveArray)[i]) { |
111 invalid_source(src, "invalid nested curveType curve"); | 216 invalid_source(src, "invalid nested curveType curve"); |
112 } | 217 } |
113 | 218 |
114 + if (tag_len == ~0) { | 219 + if (tag_len == ~0) { |
115 + invalid_source(src, "invalid nested curveType tag length
"); | 220 + invalid_source(src, "invalid nested curveType tag length
"); |
116 + return; | 221 + return; |
117 + } | 222 + } |
118 + | 223 + |
119 channel_offset += tag_len; | 224 channel_offset += tag_len; |
120 // 4 byte aligned | 225 // 4 byte aligned |
121 if ((tag_len % 4) != 0) | 226 if ((tag_len % 4) != 0) |
122 channel_offset += 4 - (tag_len % 4); | 227 channel_offset += 4 - (tag_len % 4); |
123 } | 228 } |
124 - | 229 - |
125 } | 230 } |
126 | 231 |
127 static void mAB_release(struct lutmABType *lut) | 232 static void mAB_release(struct lutmABType *lut) |
128 @@ -657,7 +712,7 @@ static struct lutType *read_tag_lutType(struct mem_source *s
rc, struct tag_index | 233 @@ -657,7 +817,7 @@ static struct lutType *read_tag_lutType(struct mem_source *s
rc, struct tag_index |
129 uint16_t num_input_table_entries; | 234 uint16_t num_input_table_entries; |
130 uint16_t num_output_table_entries; | 235 uint16_t num_output_table_entries; |
131 uint8_t in_chan, grid_points, out_chan; | 236 uint8_t in_chan, grid_points, out_chan; |
132 - uint32_t clut_offset, output_offset; | 237 - uint32_t clut_offset, output_offset; |
133 + size_t clut_offset, output_offset; | 238 + size_t clut_offset, output_offset; |
134 uint32_t clut_size; | 239 uint32_t clut_size; |
135 size_t entry_size; | 240 size_t entry_size; |
136 struct lutType *lut; | 241 struct lutType *lut; |
137 @@ -979,6 +1034,9 @@ qcms_profile* qcms_profile_sRGB(void) | 242 @@ -979,6 +1139,9 @@ qcms_profile* qcms_profile_sRGB(void) |
138 return NO_MEM_PROFILE; | 243 return NO_MEM_PROFILE; |
139 | 244 |
140 profile = qcms_profile_create_rgb_with_table(D65, Rec709Primaries, table
, 1024); | 245 profile = qcms_profile_create_rgb_with_table(D65, Rec709Primaries, table
, 1024); |
141 + if (profile) | 246 + if (profile) |
142 + strcpy(profile->description, "sRGB IEC61966-2.1"); | 247 + strcpy(profile->description, "sRGB IEC61966-2.1"); |
143 + | 248 + |
144 free(table); | 249 free(table); |
145 return profile; | 250 return profile; |
146 } | 251 } |
147 @@ -997,6 +1055,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, siz
e_t size) | 252 @@ -997,6 +1160,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, siz
e_t size) |
148 source.size = size; | 253 source.size = size; |
149 source.valid = true; | 254 source.valid = true; |
150 | 255 |
151 + if (size < 4) | 256 + if (size < 4) |
152 + return INVALID_PROFILE; | 257 + return INVALID_PROFILE; |
153 + | 258 + |
154 length = read_u32(src, 0); | 259 length = read_u32(src, 0); |
155 if (length <= size) { | 260 if (length <= size) { |
156 // shrink the area that we can read if appropriate | 261 // shrink the area that we can read if appropriate |
157 @@ -1028,6 +1089,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, si
ze_t size) | 262 @@ -1028,6 +1194,15 @@ qcms_profile* qcms_profile_from_memory(const void *mem, s
ize_t size) |
158 if (!src->valid || !index.tags) | 263 if (!src->valid || !index.tags) |
159 goto invalid_tag_table; | 264 goto invalid_tag_table; |
160 | 265 |
161 + if (!read_tag_descType(profile, src, index, TAG_desc)) | 266 + if (!read_tag_descType(profile, src, index, TAG_desc)) |
162 + goto invalid_tag_table; | 267 + goto invalid_tag_table; |
| 268 +#if defined(__APPLE__) |
| 269 + if (!read_tag_dscmType(profile, src, index, TAG_dscm)) |
| 270 + goto invalid_tag_table; |
| 271 + if (!read_tag_mmodType(profile, src, index, TAG_mmod)) |
| 272 + goto invalid_tag_table; |
| 273 +#endif // __APPLE__ |
163 + | 274 + |
164 if (find_tag(index, TAG_CHAD)) { | 275 if (find_tag(index, TAG_CHAD)) { |
165 profile->chromaticAdaption = read_tag_s15Fixed16ArrayType(src, i
ndex, TAG_CHAD); | 276 profile->chromaticAdaption = read_tag_s15Fixed16ArrayType(src, i
ndex, TAG_CHAD); |
166 } else { | 277 } else { |
167 @@ -1098,6 +1162,16 @@ invalid_profile: | 278 @@ -1098,6 +1273,16 @@ invalid_profile: |
168 return INVALID_PROFILE; | 279 return INVALID_PROFILE; |
169 } | 280 } |
170 | 281 |
171 +qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2) | 282 +qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2) |
172 +{ | 283 +{ |
173 + return memcmp(p1->description, p2->description, sizeof p1->description) ==
0; | 284 + return memcmp(p1->description, p2->description, sizeof p1->description) ==
0; |
174 +} | 285 +} |
175 + | 286 + |
176 +const char* qcms_profile_get_description(qcms_profile *profile) | 287 +const char* qcms_profile_get_description(qcms_profile *profile) |
177 +{ | 288 +{ |
178 + return profile->description; | 289 + return profile->description; |
179 +} | 290 +} |
180 + | 291 + |
181 qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile) | 292 qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile) |
182 { | 293 { |
183 return profile->rendering_intent; | 294 return profile->rendering_intent; |
184 diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h | 295 diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h |
185 index 7d83623..c69a772 100644 | 296 index 7d83623..e9c0b09 100644 |
186 --- a/third_party/qcms/src/qcms.h | 297 --- a/third_party/qcms/src/qcms.h |
187 +++ b/third_party/qcms/src/qcms.h | 298 +++ b/third_party/qcms/src/qcms.h |
188 @@ -40,6 +40,12 @@ sale, use or other dealings in this Software without written | 299 @@ -40,6 +40,12 @@ sale, use or other dealings in this Software without written |
189 authorization from SunSoft Inc. | 300 authorization from SunSoft Inc. |
190 ******************************************************************/ | 301 ******************************************************************/ |
191 | 302 |
192 +/* | 303 +/* |
193 + * QCMS, in general, is not threadsafe. However, it should be safe to create | 304 + * QCMS, in general, is not threadsafe. However, it should be safe to create |
194 + * profile and transformation objects on different threads, so long as you | 305 + * profile and transformation objects on different threads, so long as you |
195 + * don't use the same objects on different threads at the same time. | 306 + * don't use the same objects on different threads at the same time. |
(...skipping 18 matching lines...) Expand all Loading... |
214 @@ -136,6 +148,9 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile); | 325 @@ -136,6 +148,9 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile); |
215 qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile); | 326 qcms_intent qcms_profile_get_rendering_intent(qcms_profile *profile); |
216 icColorSpaceSignature qcms_profile_get_color_space(qcms_profile *profile); | 327 icColorSpaceSignature qcms_profile_get_color_space(qcms_profile *profile); |
217 | 328 |
218 +qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2); | 329 +qcms_bool qcms_profile_match(qcms_profile *p1, qcms_profile *p2); |
219 +const char* qcms_profile_get_description(qcms_profile *profile); | 330 +const char* qcms_profile_get_description(qcms_profile *profile); |
220 + | 331 + |
221 void qcms_profile_precache_output_transform(qcms_profile *profile); | 332 void qcms_profile_precache_output_transform(qcms_profile *profile); |
222 | 333 |
223 qcms_transform* qcms_transform_create( | 334 qcms_transform* qcms_transform_create( |
224 @@ -146,6 +161,7 @@ qcms_transform* qcms_transform_create( | 335 @@ -143,9 +158,14 @@ qcms_transform* qcms_transform_create( |
225 void qcms_transform_release(qcms_transform *); | 336 » » qcms_profile* out, qcms_data_type out_type, |
| 337 » » qcms_intent intent); |
| 338 |
| 339 -void qcms_transform_release(qcms_transform *); |
| 340 +qcms_bool qcms_transform_create_LUT_zyx_bgra( |
| 341 +» » qcms_profile *in, qcms_profile* out, qcms_intent intent, |
| 342 +» » int samples, unsigned char* lut); |
226 | 343 |
227 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size
_t length); | 344 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size
_t length); |
228 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest,
size_t length, qcms_output_type type); | 345 +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest,
size_t length, qcms_output_type type); |
| 346 + |
| 347 +void qcms_transform_release(qcms_transform *); |
229 | 348 |
230 void qcms_enable_iccv4(); | 349 void qcms_enable_iccv4(); |
231 | 350 |
232 diff --git a/third_party/qcms/src/qcmsint.h b/third_party/qcms/src/qcmsint.h | 351 diff --git a/third_party/qcms/src/qcmsint.h b/third_party/qcms/src/qcmsint.h |
233 index 53a3420..4116ed5 100644 | 352 index 53a3420..4116ed5 100644 |
234 --- a/third_party/qcms/src/qcmsint.h | 353 --- a/third_party/qcms/src/qcmsint.h |
235 +++ b/third_party/qcms/src/qcmsint.h | 354 +++ b/third_party/qcms/src/qcmsint.h |
236 @@ -45,6 +45,11 @@ struct precache_output | 355 @@ -45,6 +45,11 @@ struct precache_output |
237 #define ALIGN __attribute__(( aligned (16) )) | 356 #define ALIGN __attribute__(( aligned (16) )) |
238 #endif | 357 #endif |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result)); | 677 _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result)); |
559 | 678 |
560 - dest[0] = otdata_r[output[0]]; | 679 - dest[0] = otdata_r[output[0]]; |
561 - dest[1] = otdata_g[output[1]]; | 680 - dest[1] = otdata_g[output[1]]; |
562 - dest[2] = otdata_b[output[2]]; | 681 - dest[2] = otdata_b[output[2]]; |
563 + dest[r_out] = otdata_r[output[0]]; | 682 + dest[r_out] = otdata_r[output[0]]; |
564 + dest[1] = otdata_g[output[1]]; | 683 + dest[1] = otdata_g[output[1]]; |
565 + dest[b_out] = otdata_b[output[2]]; | 684 + dest[b_out] = otdata_b[output[2]]; |
566 } | 685 } |
567 diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c | 686 diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c |
568 index 9a6562b..08db142 100644 | 687 index 9a6562b..f669a6b 100644 |
569 --- a/third_party/qcms/src/transform.c | 688 --- a/third_party/qcms/src/transform.c |
570 +++ b/third_party/qcms/src/transform.c | 689 +++ b/third_party/qcms/src/transform.c |
571 @@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_poi
nt, | 690 @@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_poi
nt, |
572 static struct matrix | 691 static struct matrix |
573 adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illum
ination) | 692 adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illum
ination) |
574 { | 693 { |
575 +#if defined (_MSC_VER) | 694 +#if defined (_MSC_VER) |
576 +#pragma warning(push) | 695 +#pragma warning(push) |
577 +/* Disable double to float truncation warning 4305 */ | 696 +/* Disable double to float truncation warning 4305 */ |
578 +#pragma warning(disable:4305) | 697 +#pragma warning(disable:4305) |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
974 - /* don't precache since we will use the mBA LUT */ | 1093 - /* don't precache since we will use the mBA LUT */ |
975 - if (profile->mBA) | 1094 - if (profile->mBA) |
976 - return; | 1095 - return; |
977 + /* don't precache since we will use the mBA LUT */ | 1096 + /* don't precache since we will use the mBA LUT */ |
978 + if (profile->mBA) | 1097 + if (profile->mBA) |
979 + return; | 1098 + return; |
980 + } | 1099 + } |
981 | 1100 |
982 /* don't precache if we do not have the TRC curves */ | 1101 /* don't precache if we do not have the TRC curves */ |
983 if (!profile->redTRC || !profile->greenTRC || !profile->blueTRC) | 1102 if (!profile->redTRC || !profile->greenTRC || !profile->blueTRC) |
984 @@ -1078,7 +1153,8 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_tran
sform *transform, qcms | 1103 @@ -1043,28 +1118,31 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_tr
ansform *transform, qcms |
985 » //XXX: qcms_modular_transform_data may return either the src or dest buf
fer. If so it must not be free-ed | 1104 » float* src = NULL; |
| 1105 » float* dest = NULL; |
| 1106 » float* lut = NULL; |
| 1107 +» float inverse; |
| 1108 |
| 1109 » src = malloc(lutSize*sizeof(float)); |
| 1110 » dest = malloc(lutSize*sizeof(float)); |
| 1111 |
| 1112 » if (src && dest) { |
| 1113 -» » /* Prepare a list of points we want to sample */ |
| 1114 +» » /* Prepare a list of points we want to sample: x, y, z order */ |
| 1115 » » l = 0; |
| 1116 +» » inverse = 1 / (float)(samples-1); |
| 1117 » » for (x = 0; x < samples; x++) { |
| 1118 » » » for (y = 0; y < samples; y++) { |
| 1119 » » » » for (z = 0; z < samples; z++) { |
| 1120 -» » » » » src[l++] = x / (float)(samples-1); |
| 1121 -» » » » » src[l++] = y / (float)(samples-1); |
| 1122 -» » » » » src[l++] = z / (float)(samples-1); |
| 1123 +» » » » » src[l++] = x * inverse; // r |
| 1124 +» » » » » src[l++] = y * inverse; // g |
| 1125 +» » » » » src[l++] = z * inverse; // b |
| 1126 » » » » } |
| 1127 » » » } |
| 1128 » » } |
| 1129 |
| 1130 » » lut = qcms_chain_transform(in, out, src, dest, lutSize); |
| 1131 + |
| 1132 » » if (lut) { |
| 1133 -» » » transform->r_clut = &lut[0]; |
| 1134 -» » » transform->g_clut = &lut[1]; |
| 1135 -» » » transform->b_clut = &lut[2]; |
| 1136 +» » » transform->r_clut = &lut[0]; // r |
| 1137 +» » » transform->g_clut = &lut[1]; // g |
| 1138 +» » » transform->b_clut = &lut[2]; // b |
| 1139 » » » transform->grid_size = samples; |
| 1140 » » » if (in_type == QCMS_DATA_RGBA_8) { |
| 1141 » » » » transform->transform_fn = qcms_transform_data_te
tra_clut_rgba; |
| 1142 @@ -1074,11 +1152,12 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_tr
ansform *transform, qcms |
| 1143 » » } |
| 1144 » } |
| 1145 |
| 1146 - |
| 1147 -» //XXX: qcms_modular_transform_data may return either the src or dest buf
fer. If so it must not be free-ed |
| 1148 +» // XXX: qcms_modular_transform_data may return the lut in either the src
or the |
| 1149 +» // dest buffer. If so, it must not be free-ed. |
986 if (src && lut != src) { | 1150 if (src && lut != src) { |
987 free(src); | 1151 free(src); |
988 - } else if (dest && lut != src) { | 1152 - } else if (dest && lut != src) { |
989 + } | 1153 + } |
990 + if (dest && lut != dest) { | 1154 + if (dest && lut != dest) { |
991 free(dest); | 1155 free(dest); |
992 } | 1156 } |
993 | 1157 |
994 @@ -1157,14 +1233,14 @@ qcms_transform* qcms_transform_create( | 1158 @@ -1088,6 +1167,71 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_tra
nsform *transform, qcms |
| 1159 » return transform; |
| 1160 } |
| 1161 |
| 1162 +/* Create a transform LUT using the given number of sample points. The transfor
m LUT data is stored |
| 1163 + in the output (cube) in bgra format in zyx sample order. */ |
| 1164 +qcms_bool qcms_transform_create_LUT_zyx_bgra(qcms_profile *in, qcms_profile *ou
t, qcms_intent intent, |
| 1165 + int samples, unsigned char* cube) |
| 1166 +{ |
| 1167 +» uint16_t z,y,x; |
| 1168 +» uint32_t l,index; |
| 1169 +» uint32_t lutSize = 3 * samples * samples * samples; |
| 1170 + |
| 1171 +» float* src = NULL; |
| 1172 +» float* dest = NULL; |
| 1173 +» float* lut = NULL; |
| 1174 +» float inverse; |
| 1175 + |
| 1176 +» src = malloc(lutSize*sizeof(float)); |
| 1177 +» dest = malloc(lutSize*sizeof(float)); |
| 1178 + |
| 1179 +» if (src && dest) { |
| 1180 +» » /* Prepare a list of points we want to sample: z, y, x order */ |
| 1181 +» » l = 0; |
| 1182 +» » inverse = 1 / (float)(samples-1); |
| 1183 +» » for (z = 0; z < samples; z++) { |
| 1184 +» » » for (y = 0; y < samples; y++) { |
| 1185 +» » » » for (x = 0; x < samples; x++) { |
| 1186 +» » » » » src[l++] = x * inverse; // r |
| 1187 +» » » » » src[l++] = y * inverse; // g |
| 1188 +» » » » » src[l++] = z * inverse; // b |
| 1189 +» » » » } |
| 1190 +» » » } |
| 1191 +» » } |
| 1192 + |
| 1193 +» » lut = qcms_chain_transform(in, out, src, dest, lutSize); |
| 1194 + |
| 1195 +» » if (lut) { |
| 1196 +» » » index = l = 0; |
| 1197 +» » » for (z = 0; z < samples; z++) { |
| 1198 +» » » » for (y = 0; y < samples; y++) { |
| 1199 +» » » » » for (x = 0; x < samples; x++) { |
| 1200 +» » » » » » cube[index++] = (int)floorf(lut[
l + 2] * 255.0f + 0.5f); // b |
| 1201 +» » » » » » cube[index++] = (int)floorf(lut[
l + 1] * 255.0f + 0.5f); // g |
| 1202 +» » » » » » cube[index++] = (int)floorf(lut[
l + 0] * 255.0f + 0.5f); // r |
| 1203 +» » » » » » cube[index++] = 255;
// a |
| 1204 +» » » » » » l += 3; |
| 1205 +» » » » » } |
| 1206 +» » » » } |
| 1207 +» » » } |
| 1208 +» » } |
| 1209 +» } |
| 1210 + |
| 1211 +» // XXX: qcms_modular_transform_data may return the lut data in either th
e src or |
| 1212 +» // dest buffer so free src, dest, and lut with care. |
| 1213 + |
| 1214 +» if (src && lut != src) |
| 1215 +» » free(src); |
| 1216 +» if (dest && lut != dest) |
| 1217 +» » free(dest); |
| 1218 + |
| 1219 +» if (lut) { |
| 1220 +» » free(lut); |
| 1221 +» » return true; |
| 1222 +» } |
| 1223 + |
| 1224 +» return false; |
| 1225 +} |
| 1226 + |
| 1227 #define NO_MEM_TRANSFORM NULL |
| 1228 |
| 1229 qcms_transform* qcms_transform_create( |
| 1230 @@ -1157,14 +1301,14 @@ qcms_transform* qcms_transform_create( |
995 return NULL; | 1231 return NULL; |
996 } | 1232 } |
997 if (precache) { | 1233 if (precache) { |
998 -#ifdef X86 | 1234 -#ifdef X86 |
999 +#if defined(SSE2_ENABLE) && defined(X86) | 1235 +#if defined(SSE2_ENABLE) && defined(X86) |
1000 if (sse_version_available() >= 2) { | 1236 if (sse_version_available() >= 2) { |
1001 if (in_type == QCMS_DATA_RGB_8) | 1237 if (in_type == QCMS_DATA_RGB_8) |
1002 transform->transform_fn = qcms_transform_dat
a_rgb_out_lut_sse2; | 1238 transform->transform_fn = qcms_transform_dat
a_rgb_out_lut_sse2; |
1003 else | 1239 else |
1004 transform->transform_fn = qcms_transform_dat
a_rgba_out_lut_sse2; | 1240 transform->transform_fn = qcms_transform_dat
a_rgba_out_lut_sse2; |
1005 | 1241 |
1006 -#if !(defined(_MSC_VER) && defined(_M_AMD64)) | 1242 -#if !(defined(_MSC_VER) && defined(_M_AMD64)) |
1007 +#if defined(SSE2_ENABLE) && !(defined(_MSC_VER) && defined(_M_AMD64)) | 1243 +#if defined(SSE2_ENABLE) && !(defined(_MSC_VER) && defined(_M_AMD64)) |
1008 /* Microsoft Compiler for x64 doesn't support MMX. | 1244 /* Microsoft Compiler for x64 doesn't support MMX. |
1009 * SSE code uses MMX so that we disable on x64 */ | 1245 * SSE code uses MMX so that we disable on x64 */ |
1010 } else | 1246 } else |
1011 @@ -1256,13 +1332,34 @@ qcms_transform* qcms_transform_create( | 1247 @@ -1256,13 +1400,34 @@ qcms_transform* qcms_transform_create( |
1012 return transform; | 1248 return transform; |
1013 } | 1249 } |
1014 | 1250 |
1015 -#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) | 1251 -#if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) |
1016 +/* __force_align_arg_pointer__ is an x86-only attribute, and gcc/clang warns on
unused | 1252 +/* __force_align_arg_pointer__ is an x86-only attribute, and gcc/clang warns on
unused |
1017 + * attributes. Don't use this on ARM or AMD64. __has_attribute can detect the p
resence | 1253 + * attributes. Don't use this on ARM or AMD64. __has_attribute can detect the p
resence |
1018 + * of the attribute but is currently only supported by clang */ | 1254 + * of the attribute but is currently only supported by clang */ |
1019 +#if defined(__has_attribute) | 1255 +#if defined(__has_attribute) |
1020 +#define HAS_FORCE_ALIGN_ARG_POINTER __has_attribute(__force_align_arg_pointer__
) | 1256 +#define HAS_FORCE_ALIGN_ARG_POINTER __has_attribute(__force_align_arg_pointer__
) |
1021 +#elif defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) && !defi
ned(__arm__) && !defined(__mips__) | 1257 +#elif defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) && !defi
ned(__arm__) && !defined(__mips__) |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 | 1384 |
1149 -float lut_interp_linear(double value, uint16_t *table, int length); | 1385 -float lut_interp_linear(double value, uint16_t *table, int length); |
1150 -float lut_interp_linear_float(float value, float *table, int length); | 1386 -float lut_interp_linear_float(float value, float *table, int length); |
1151 -uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length)
; | 1387 -uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, int length)
; |
1152 +float lut_interp_linear(double value, uint16_t *table, size_t length); | 1388 +float lut_interp_linear(double value, uint16_t *table, size_t length); |
1153 +float lut_interp_linear_float(float value, float *table, size_t length); | 1389 +float lut_interp_linear_float(float value, float *table, size_t length); |
1154 +uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t leng
th); | 1390 +uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t leng
th); |
1155 | 1391 |
1156 | 1392 |
1157 static inline float lerp(float a, float b, float t) | 1393 static inline float lerp(float a, float b, float t) |
OLD | NEW |