OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkColorSpace.h" | 8 #include "SkColorSpace.h" |
9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
10 #include "SkEndian.h" | 10 #include "SkEndian.h" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
194 } | 194 } |
195 | 195 |
196 // This is equal to the header size according to the ICC specification (128) | 196 // This is equal to the header size according to the ICC specification (128) |
197 // plus the size of the tag count (4). We include the tag count since we | 197 // plus the size of the tag count (4). We include the tag count since we |
198 // always require it to be present anyway. | 198 // always require it to be present anyway. |
199 static constexpr size_t kICCHeaderSize = 132; | 199 static constexpr size_t kICCHeaderSize = 132; |
200 | 200 |
201 // Contains a signature (4), offset (4), and size (4). | 201 // Contains a signature (4), offset (4), and size (4). |
202 static constexpr size_t kICCTagTableEntrySize = 12; | 202 static constexpr size_t kICCTagTableEntrySize = 12; |
203 | 203 |
204 static constexpr uint32_t kRGB_ColorSpace = SkSetFourByteTag('R', 'G', 'B', ' ' ); | 204 static constexpr uint32_t kRGB_ColorSpace = SkSetFourByteTag('R', 'G', 'B', ' '); |
205 static constexpr uint32_t kDisplay_Profile = SkSetFourByteTag('m', 'n', 't', 'r' ); | 205 static constexpr uint32_t kDisplay_Profile = SkSetFourByteTag('m', 'n', 't', 'r'); |
206 static constexpr uint32_t kInput_Profile = SkSetFourByteTag('s', 'c', 'n', 'r' ); | 206 static constexpr uint32_t kInput_Profile = SkSetFourByteTag('s', 'c', 'n', 'r'); |
207 static constexpr uint32_t kOutput_Profile = SkSetFourByteTag('p', 'r', 't', 'r' ); | 207 static constexpr uint32_t kOutput_Profile = SkSetFourByteTag('p', 'r', 't', 'r'); |
208 static constexpr uint32_t kXYZ_PCSSpace = SkSetFourByteTag('X', 'Y', 'Z', ' ' ); | 208 static constexpr uint32_t kColorSpace_Profile = SkSetFourByteTag('s', 'p', 'a', 'c'); |
209 static constexpr uint32_t kACSP_Signature = SkSetFourByteTag('a', 'c', 's', 'p' ); | 209 static constexpr uint32_t kXYZ_PCSSpace = SkSetFourByteTag('X', 'Y', 'Z', ' '); |
210 static constexpr uint32_t kACSP_Signature = SkSetFourByteTag('a', 'c', 's', 'p'); | |
210 | 211 |
211 struct ICCProfileHeader { | 212 struct ICCProfileHeader { |
212 uint32_t fSize; | 213 uint32_t fSize; |
213 | 214 |
214 // No reason to care about the preferred color management module (ex: Adobe, Apple, etc.). | 215 // No reason to care about the preferred color management module (ex: Adobe, Apple, etc.). |
215 // We're always going to use this one. | 216 // We're always going to use this one. |
216 uint32_t fCMMType_ignored; | 217 uint32_t fCMMType_ignored; |
217 | 218 |
218 uint32_t fVersion; | 219 uint32_t fVersion; |
219 uint32_t fProfileClass; | 220 uint32_t fProfileClass; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 dst[i] = read_big_endian_uint(src); | 263 dst[i] = read_big_endian_uint(src); |
263 } | 264 } |
264 } | 265 } |
265 | 266 |
266 bool valid() const { | 267 bool valid() const { |
267 return_if_false(fSize >= kICCHeaderSize, "Size is too small"); | 268 return_if_false(fSize >= kICCHeaderSize, "Size is too small"); |
268 | 269 |
269 uint8_t majorVersion = fVersion >> 24; | 270 uint8_t majorVersion = fVersion >> 24; |
270 return_if_false(majorVersion <= 4, "Unsupported version"); | 271 return_if_false(majorVersion <= 4, "Unsupported version"); |
271 | 272 |
272 // These are the three basic classes of profiles that we might expect to see embedded | 273 // These are the four basic classes of profiles that we might expect to see embedded |
273 // in images. Four additional classes exist, but they generally are use d as a convenient | 274 // in images. Additional classes exist, but they generally are used as a convenient |
274 // way for CMMs to store calculated transforms. | 275 // way for CMMs to store calculated transforms. |
275 return_if_false(fProfileClass == kDisplay_Profile || | 276 return_if_false(fProfileClass == kDisplay_Profile || |
276 fProfileClass == kInput_Profile || | 277 fProfileClass == kInput_Profile || |
277 fProfileClass == kOutput_Profile, | 278 fProfileClass == kOutput_Profile || |
279 fProfileClass == kColorSpace_Profile, | |
278 "Unsupported profile"); | 280 "Unsupported profile"); |
279 | 281 |
280 // TODO (msarett): | 282 // TODO (msarett): |
281 // All the profiles we've tested so far use RGB as the input color space . | 283 // All the profiles we've tested so far use RGB as the input color space . |
282 return_if_false(fInputColorSpace == kRGB_ColorSpace, "Unsupported color space"); | 284 return_if_false(fInputColorSpace == kRGB_ColorSpace, "Unsupported color space"); |
283 | 285 |
284 // TODO (msarett): | 286 // TODO (msarett): |
285 // All the profiles we've tested so far use XYZ as the profile connectio n space. | 287 // All the profiles we've tested so far use XYZ as the profile connectio n space. |
286 return_if_false(fPCS == kXYZ_PCSSpace, "Unsupported PCS space"); | 288 return_if_false(fPCS == kXYZ_PCSSpace, "Unsupported PCS space"); |
287 | 289 |
288 return_if_false(fSignature == kACSP_Signature, "Bad signature"); | 290 return_if_false(fSignature == kACSP_Signature, "Bad signature"); |
289 | 291 |
290 // TODO (msarett): | 292 // TODO (msarett): |
291 // Should we treat different rendering intents differently? | 293 // Should we treat different rendering intents differently? |
292 // Valid rendering intents include kPerceptual (0), kRelative (1), | 294 // Valid rendering intents include kPerceptual (0), kRelative (1), |
293 // kSaturation (2), and kAbsolute (3). | 295 // kSaturation (2), and kAbsolute (3). |
294 return_if_false(fRenderingIntent <= 3, "Bad rendering intent"); | 296 if (fRenderingIntent <= 3) { |
297 // I think it makes to warn rather than fail here. I've seen a | |
298 // few profiles that specify 0x01000000 as the rendering intent. | |
299 // It's likely that they're just confused about endianness. | |
reed1
2016/06/25 01:16:37
What do other parsers do on these? Can you tell wh
msarett
2016/07/14 13:45:04
I'm fairly confident that this is the right decisi
| |
300 SkColorSpacePrintf("Warning, bad rendering intent.\n"); | |
301 } | |
295 | 302 |
296 return_if_false(color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[0 ]), 0.96420f) && | 303 return_if_false(color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[0 ]), 0.96420f) && |
297 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1 ]), 1.00000f) && | 304 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1 ]), 1.00000f) && |
298 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2 ]), 0.82491f), | 305 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2 ]), 0.82491f), |
299 "Illuminant must be D50"); | 306 "Illuminant must be D50"); |
300 | 307 |
301 return_if_false(fTagCount <= 100, "Too many tags"); | 308 return_if_false(fTagCount <= 100, "Too many tags"); |
302 | 309 |
303 return true; | 310 return true; |
304 } | 311 } |
(...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1350 | 1357 |
1351 uint32_t profileSize = *((uint32_t*) data); | 1358 uint32_t profileSize = *((uint32_t*) data); |
1352 data = SkTAddOffset<const void>(data, sizeof(uint32_t)); | 1359 data = SkTAddOffset<const void>(data, sizeof(uint32_t)); |
1353 length -= sizeof(uint32_t); | 1360 length -= sizeof(uint32_t); |
1354 if (length < profileSize) { | 1361 if (length < profileSize) { |
1355 return nullptr; | 1362 return nullptr; |
1356 } | 1363 } |
1357 | 1364 |
1358 return NewICC(data, profileSize); | 1365 return NewICC(data, profileSize); |
1359 } | 1366 } |
OLD | NEW |