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 "SkAtomics.h" | 8 #include "SkAtomics.h" |
9 #include "SkColorSpace.h" | 9 #include "SkColorSpace.h" |
10 | 10 |
11 void SkFloat3::dump() const { | 11 void SkFloat3::dump() const { |
12 SkDebugf("[%7.4f %7.4f %7.4f]\n", fVec[0], fVec[1], fVec[2]); | 12 SkDebugf("[%7.4f %7.4f %7.4f]\n", fVec[0], fVec[1], fVec[2]); |
13 } | 13 } |
14 | 14 |
15 void SkFloat3x3::dump() const { | 15 void SkFloat3x3::dump() const { |
16 SkDebugf("[%7.4f %7.4f %7.4f] [%7.4f %7.4f %7.4f] [%7.4f %7.4f %7.4f]\n", | 16 SkDebugf("[%7.4f %7.4f %7.4f] [%7.4f %7.4f %7.4f] [%7.4f %7.4f %7.4f]\n", |
17 fMat[0], fMat[1], fMat[2], | 17 fMat[0], fMat[1], fMat[2], |
18 fMat[3], fMat[4], fMat[5], | 18 fMat[3], fMat[4], fMat[5], |
19 fMat[6], fMat[7], fMat[8]); | 19 fMat[6], fMat[7], fMat[8]); |
20 } | 20 } |
21 | 21 |
22 ////////////////////////////////////////////////////////////////////////////////
////////////////// | 22 ////////////////////////////////////////////////////////////////////////////////
////////////////// |
23 | 23 |
24 static int32_t gUniqueColorSpaceID; | 24 static int32_t gUniqueColorSpaceID; |
25 | 25 |
26 SkColorSpace::SkColorSpace(SkGammas gammas, const SkFloat3x3& toXYZD50, Named na
med) | 26 SkColorSpace::SkColorSpace(const SkFloat3& gamma, const SkFloat3x3& toXYZD50, Na
med named) |
27 : fGammas(std::move(gammas)) | 27 : fGamma(gamma) |
28 , fToXYZD50(toXYZD50) | 28 , fToXYZD50(toXYZD50) |
29 , fToXYZOffset({{ 0.0f, 0.0f, 0.0f }}) | 29 , fToXYZOffset({{ 0.0f, 0.0f, 0.0f }}) |
30 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID)) | 30 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID)) |
31 , fNamed(named) | 31 , fNamed(named) |
32 {} | 32 {} |
33 | 33 |
34 SkColorSpace::SkColorSpace(SkColorLookUpTable colorLUT, SkGammas gammas, | 34 SkColorSpace::SkColorSpace(SkColorLookUpTable colorLUT, const SkFloat3& gamma, |
35 const SkFloat3x3& toXYZD50, const SkFloat3& toXYZOffs
et) | 35 const SkFloat3x3& toXYZD50, const SkFloat3& toXYZOffs
et) |
36 : fColorLUT(std::move(colorLUT)) | 36 : fColorLUT(std::move(colorLUT)) |
37 , fGammas(std::move(gammas)) | 37 , fGamma(gamma) |
38 , fToXYZD50(toXYZD50) | 38 , fToXYZD50(toXYZD50) |
39 , fToXYZOffset(toXYZOffset) | 39 , fToXYZOffset(toXYZOffset) |
40 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID)) | 40 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID)) |
41 , fNamed(kUnknown_Named) | 41 , fNamed(kUnknown_Named) |
42 {} | 42 {} |
43 | 43 |
44 sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkFloat3x3& toXYZD50, SkGammas ga
mmas) { | 44 sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkFloat3x3& toXYZD50, const SkFlo
at3& gamma) { |
45 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(gammas), toXYZD50, kUn
known_Named)); | 45 return sk_sp<SkColorSpace>(new SkColorSpace(gamma, toXYZD50, kUnknown_Named)
); |
46 } | 46 } |
47 | 47 |
48 SkColorSpace::SkGammas gSRGB_gamma(2.2f, 2.2f, 2.2f); | 48 const SkFloat3 gSRGB_gamma {{ 2.2f, 2.2f, 2.2f }}; |
49 const SkFloat3x3 gSRGB_toXYZD50 {{ | 49 const SkFloat3x3 gSRGB_toXYZD50 {{ |
50 0.4358f, 0.2224f, 0.0139f, // * R | 50 0.4358f, 0.2224f, 0.0139f, // * R |
51 0.3853f, 0.7170f, 0.0971f, // * G | 51 0.3853f, 0.7170f, 0.0971f, // * G |
52 0.1430f, 0.0606f, 0.7139f, // * B | 52 0.1430f, 0.0606f, 0.7139f, // * B |
53 }}; | 53 }}; |
54 | 54 |
55 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { | 55 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { |
56 switch (named) { | 56 switch (named) { |
57 case kSRGB_Named: | 57 case kSRGB_Named: |
58 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(gSRGB_gamma),
gSRGB_toXYZD50, | 58 return sk_sp<SkColorSpace>(new SkColorSpace(gSRGB_gamma, gSRGB_toXYZ
D50, kSRGB_Named)); |
59 kSRGB_Named)); | |
60 default: | 59 default: |
61 break; | 60 break; |
62 } | 61 } |
63 return nullptr; | 62 return nullptr; |
64 } | 63 } |
65 | 64 |
66 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 65 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
67 | 66 |
68 #include "SkFixed.h" | 67 #include "SkFixed.h" |
69 #include "SkTemplates.h" | 68 #include "SkTemplates.h" |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); | 257 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); |
259 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); | 258 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); |
260 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); | 259 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); |
261 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); | 260 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); |
262 return true; | 261 return true; |
263 } | 262 } |
264 | 263 |
265 static const uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', 'v'); | 264 static const uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', 'v'); |
266 static const uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', 'a'); | 265 static const uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', 'a'); |
267 | 266 |
268 bool SkColorSpace::LoadGammas(SkGammaCurve* gammas, uint32_t numGammas, const ui
nt8_t* src, | 267 // FIXME (msarett): |
269 size_t len) { | 268 // We need to handle the possibility that the gamma curve does not correspond to
2.2f. |
| 269 static bool load_gammas(float* gammas, uint32_t numGammas, const uint8_t* src, s
ize_t len) { |
270 for (uint32_t i = 0; i < numGammas; i++) { | 270 for (uint32_t i = 0; i < numGammas; i++) { |
271 if (len < 12) { | 271 if (len < 12) { |
272 // FIXME (msarett): | 272 // FIXME (msarett): |
273 // We could potentially return false here after correctly parsing *s
ome* of the | 273 // We could potentially return false here after correctly parsing *s
ome* of the |
274 // gammas correctly. Should we somehow try to indicate a partial su
ccess? | 274 // gammas correctly. Should we somehow try to indicate a partial su
ccess? |
275 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); | 275 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
276 return false; | 276 return false; |
277 } | 277 } |
278 | 278 |
279 // We need to count the number of bytes in the tag, so we are able to mo
ve to the | 279 // We need to count the number of bytes in the tag, so we are able to mo
ve to the |
280 // next tag on the next loop iteration. | 280 // next tag on the next loop iteration. |
281 size_t tagBytes; | 281 size_t tagBytes; |
282 | 282 |
283 uint32_t type = read_big_endian_uint(src); | 283 uint32_t type = read_big_endian_uint(src); |
284 switch (type) { | 284 switch (type) { |
285 case kTAG_CurveType: { | 285 case kTAG_CurveType: { |
286 uint32_t count = read_big_endian_uint(src + 8); | 286 uint32_t count = read_big_endian_uint(src + 8); |
287 tagBytes = 12 + count * 2; | 287 tagBytes = 12 + count * 2; |
288 if (0 == count) { | 288 if (0 == count) { |
289 // Some tags require a gamma curve, but the author doesn't a
ctually want | 289 // Some tags require a gamma curve, but the author doesn't a
ctually want |
290 // to transform the data. In this case, it is common to see
a curve with | 290 // to transform the data. In this case, it is common to see
a curve with |
291 // a count of 0. | 291 // a count of 0. |
292 gammas[i].fValue = 1.0f; | 292 gammas[i] = 1.0f; |
293 break; | 293 break; |
294 } else if (len < 12 + 2 * count) { | 294 } else if (len < 12 + 2 * count) { |
295 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
; | 295 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
; |
296 return false; | 296 return false; |
297 } | 297 } |
298 | 298 |
299 const uint16_t* table = (const uint16_t*) (src + 12); | 299 const uint16_t* table = (const uint16_t*) (src + 12); |
300 if (1 == count) { | 300 if (1 == count) { |
301 // The table entry is the gamma (with a bias of 256). | 301 // Table entry is the exponent (bias 256). |
302 uint16_t value = read_big_endian_short((const uint8_t*) tabl
e); | 302 uint16_t value = read_big_endian_short((const uint8_t*) tabl
e); |
303 gammas[i].fValue = value / 256.0f; | 303 gammas[i] = value / 256.0f; |
304 SkColorSpacePrintf("gamma %d %g\n", value, *gamma); | 304 SkColorSpacePrintf("gamma %d %g\n", value, *gamma); |
305 break; | 305 break; |
306 } | 306 } |
307 | 307 |
308 // Fill in the interpolation table. | 308 // Print the interpolation table. For now, we ignore this and g
uess 2.2f. |
309 // FIXME (msarett): | |
310 // We should recognize commonly occurring tables and just set ga
mma to 2.2f. | |
311 gammas[i].fTableSize = count; | |
312 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); | |
313 for (uint32_t j = 0; j < count; j++) { | 309 for (uint32_t j = 0; j < count; j++) { |
314 gammas[i].fTable[j] = | 310 SkColorSpacePrintf("curve[%d] %d\n", j, |
315 (read_big_endian_short((const uint8_t*) &table[j]))
/ 65535.0f; | 311 read_big_endian_short((const uint8_t*) &table[j])); |
316 } | 312 } |
| 313 |
| 314 gammas[i] = 2.2f; |
317 break; | 315 break; |
318 } | 316 } |
319 case kTAG_ParaCurveType: | 317 case kTAG_ParaCurveType: |
320 // Guess 2.2f. | 318 // Guess 2.2f. |
321 // FIXME (msarett): Handle parametric curves. | |
322 SkColorSpacePrintf("parametric curve\n"); | 319 SkColorSpacePrintf("parametric curve\n"); |
323 gammas[i].fValue = 2.2f; | 320 gammas[i] = 2.2f; |
324 | 321 |
325 // Determine the size of the parametric curve tag. | |
326 switch(read_big_endian_short(src + 8)) { | 322 switch(read_big_endian_short(src + 8)) { |
327 case 0: | 323 case 0: |
328 tagBytes = 12 + 4; | 324 tagBytes = 12 + 4; |
329 break; | 325 break; |
330 case 1: | 326 case 1: |
331 tagBytes = 12 + 12; | 327 tagBytes = 12 + 12; |
332 break; | 328 break; |
333 case 2: | 329 case 2: |
334 tagBytes = 12 + 16; | 330 tagBytes = 12 + 16; |
335 break; | 331 break; |
(...skipping 19 matching lines...) Expand all Loading... |
355 tagBytes = SkAlign4(tagBytes); | 351 tagBytes = SkAlign4(tagBytes); |
356 if (len < tagBytes) { | 352 if (len < tagBytes) { |
357 return false; | 353 return false; |
358 } | 354 } |
359 | 355 |
360 src += tagBytes; | 356 src += tagBytes; |
361 len -= tagBytes; | 357 len -= tagBytes; |
362 } | 358 } |
363 } | 359 } |
364 | 360 |
365 return true; | 361 // If all of the gammas we encounter are 1.0f, indicate that we failed to lo
ad gammas. |
| 362 // There is no need to apply a gamma of 1.0f. |
| 363 for (uint32_t i = 0; i < numGammas; i++) { |
| 364 if (1.0f != gammas[i]) { |
| 365 return true; |
| 366 } |
| 367 } |
| 368 |
| 369 return false; |
366 } | 370 } |
367 | 371 |
368 static const uint32_t kTAG_AtoBType = SkSetFourByteTag('m', 'A', 'B', ' '); | 372 static const uint32_t kTAG_AtoBType = SkSetFourByteTag('m', 'A', 'B', ' '); |
369 | 373 |
370 bool SkColorSpace::LoadColorLUT(SkColorLookUpTable* colorLUT, uint32_t inputChan
nels, | 374 bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, uint32
_t outputChannels, |
371 uint32_t outputChannels, const uint8_t* src, siz
e_t len) { | 375 const uint8_t* src, size_t len) { |
372 if (len < 20) { | 376 if (len < 20) { |
373 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); | 377 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); |
374 return false; | 378 return false; |
375 } | 379 } |
376 | 380 |
377 SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels && 3 == outputCha
nnels); | 381 SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels && |
| 382 outputChannels <= SkColorLookUpTable::kMaxChannels); |
378 colorLUT->fInputChannels = inputChannels; | 383 colorLUT->fInputChannels = inputChannels; |
379 colorLUT->fOutputChannels = outputChannels; | 384 colorLUT->fOutputChannels = outputChannels; |
380 uint32_t numEntries = 1; | 385 uint32_t numEntries = 1; |
381 for (uint32_t i = 0; i < inputChannels; i++) { | 386 for (uint32_t i = 0; i < inputChannels; i++) { |
382 colorLUT->fGridPoints[i] = src[i]; | 387 colorLUT->fGridPoints[i] = src[i]; |
383 numEntries *= src[i]; | 388 numEntries *= src[i]; |
384 } | 389 } |
385 numEntries *= outputChannels; | 390 numEntries *= outputChannels; |
386 | 391 |
387 // Space is provided for a maximum of the 16 input channels. Now we determi
ne the precision | 392 // Space is provided for a maximum of the 16 input channels. Now we determi
ne the precision |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 toXYZ->fMat[7] = SkFixedToFloat(read_big_endian_int(src + 20)); | 434 toXYZ->fMat[7] = SkFixedToFloat(read_big_endian_int(src + 20)); |
430 toXYZ->fMat[2] = SkFixedToFloat(read_big_endian_int(src + 24)); | 435 toXYZ->fMat[2] = SkFixedToFloat(read_big_endian_int(src + 24)); |
431 toXYZ->fMat[5] = SkFixedToFloat(read_big_endian_int(src + 28)); | 436 toXYZ->fMat[5] = SkFixedToFloat(read_big_endian_int(src + 28)); |
432 toXYZ->fMat[8] = SkFixedToFloat(read_big_endian_int(src + 32)); | 437 toXYZ->fMat[8] = SkFixedToFloat(read_big_endian_int(src + 32)); |
433 toXYZOffset->fVec[0] = SkFixedToFloat(read_big_endian_int(src + 36)); | 438 toXYZOffset->fVec[0] = SkFixedToFloat(read_big_endian_int(src + 36)); |
434 toXYZOffset->fVec[1] = SkFixedToFloat(read_big_endian_int(src + 40)); | 439 toXYZOffset->fVec[1] = SkFixedToFloat(read_big_endian_int(src + 40)); |
435 toXYZOffset->fVec[2] = SkFixedToFloat(read_big_endian_int(src + 44)); | 440 toXYZOffset->fVec[2] = SkFixedToFloat(read_big_endian_int(src + 44)); |
436 return true; | 441 return true; |
437 } | 442 } |
438 | 443 |
439 bool SkColorSpace::LoadA2B0(SkColorLookUpTable* colorLUT, SkGammas* gammas, SkFl
oat3x3* toXYZ, | 444 bool load_a2b0(SkColorLookUpTable* colorLUT, SkFloat3* gamma, SkFloat3x3* toXYZ, |
440 SkFloat3* toXYZOffset, const uint8_t* src, size_t le
n) { | 445 SkFloat3* toXYZOffset, const uint8_t* src, size_t len) { |
441 if (len < 32) { | 446 if (len < 32) { |
442 SkColorSpacePrintf("A to B tag is too small (%d bytes).", len); | 447 SkColorSpacePrintf("A to B tag is too small (%d bytes).", len); |
443 return false; | 448 return false; |
444 } | 449 } |
445 | 450 |
446 uint32_t type = read_big_endian_uint(src); | 451 uint32_t type = read_big_endian_uint(src); |
447 if (kTAG_AtoBType != type) { | 452 if (kTAG_AtoBType != type) { |
448 // FIXME (msarett): Need to support lut8Type and lut16Type. | 453 // FIXME (msarett): Need to support lut8Type and lut16Type. |
449 SkColorSpacePrintf("Unsupported A to B tag type.\n"); | 454 SkColorSpacePrintf("Unsupported A to B tag type.\n"); |
450 return false; | 455 return false; |
451 } | 456 } |
452 | 457 |
453 // Read the number of channels. The four bytes that we skipped are reserved
and | 458 // Read the number of channels. The four bytes that we skipped are reserved
and |
454 // must be zero. | 459 // must be zero. |
455 uint8_t inputChannels = src[8]; | 460 uint8_t inputChannels = src[8]; |
456 uint8_t outputChannels = src[9]; | 461 uint8_t outputChannels = src[9]; |
457 if (0 == inputChannels || inputChannels > SkColorLookUpTable::kMaxChannels |
| | 462 if (0 == inputChannels || inputChannels > SkColorLookUpTable::kMaxChannels |
| |
458 3 != outputChannels) { | 463 0 < outputChannels || outputChannels > SkColorLookUpTable::kMaxChann
els) { |
459 // The color LUT assumes that there are at most 16 input channels. For
RGB | 464 // The color LUT assumes that there are at most 16 input channels. For
RGB |
460 // profiles, output channels should be 3. | 465 // profiles, output channels should be 3. |
461 SkColorSpacePrintf("Too many input or output channels in A to B tag.\n")
; | 466 SkColorSpacePrintf("Too many input or output channels in A to B tag.\n")
; |
462 return false; | 467 return false; |
463 } | 468 } |
464 | 469 |
465 // Read the offsets of each element in the A to B tag. With the exception o
f A curves and | 470 // Read the offsets of each element in the A to B tag. With the exception o
f A curves and |
466 // B curves (which we do not yet support), we will handle these elements in
the order in | 471 // B curves (which we do not yet support), we will handle these elements in
the order in |
467 // which they should be applied (rather than the order in which they occur i
n the tag). | 472 // which they should be applied (rather than the order in which they occur i
n the tag). |
468 // If the offset is non-zero it indicates that the element is present. | 473 // If the offset is non-zero it indicates that the element is present. |
469 uint32_t offsetToACurves = read_big_endian_int(src + 28); | 474 uint32_t offsetToACurves = read_big_endian_int(src + 28); |
470 uint32_t offsetToBCurves = read_big_endian_int(src + 12); | 475 uint32_t offsetToBCurves = read_big_endian_int(src + 12); |
471 if ((0 != offsetToACurves) || (0 != offsetToBCurves)) { | 476 if ((0 != offsetToACurves) || (0 != offsetToBCurves)) { |
472 // FIXME (msarett): Handle A and B curves. | 477 // FIXME (msarett): Handle A and B curves. |
473 // Note that the A curve is technically required in order to have a colo
r LUT. | 478 // Note that the A curve is technically required in order to have a colo
r LUT. |
474 // However, all the A curves I have seen so far have are just placeholde
rs that | 479 // However, all the A curves I have seen so far have are just placeholde
rs that |
475 // don't actually transform the data. | 480 // don't actually transform the data. |
476 SkColorSpacePrintf("Ignoring A and/or B curve. Output may be wrong.\n")
; | 481 SkColorSpacePrintf("Ignoring A and/or B curve. Output may be wrong.\n")
; |
477 } | 482 } |
478 | 483 |
479 uint32_t offsetToColorLUT = read_big_endian_int(src + 24); | 484 uint32_t offsetToColorLUT = read_big_endian_int(src + 24); |
480 if (0 != offsetToColorLUT && offsetToColorLUT < len) { | 485 if (0 != offsetToColorLUT && offsetToColorLUT < len) { |
481 if (!SkColorSpace::LoadColorLUT(colorLUT, inputChannels, outputChannels, | 486 if (!load_color_lut(colorLUT, inputChannels, outputChannels, src + offse
tToColorLUT, |
482 src + offsetToColorLUT, len - offsetToCo
lorLUT)) { | 487 len - offsetToColorLUT)) { |
483 SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n"); | 488 SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n"); |
484 } | 489 } |
485 } | 490 } |
486 | 491 |
487 uint32_t offsetToMCurves = read_big_endian_int(src + 20); | 492 uint32_t offsetToMCurves = read_big_endian_int(src + 20); |
488 if (0 != offsetToMCurves && offsetToMCurves < len) { | 493 if (0 != offsetToMCurves && offsetToMCurves < len) { |
489 if (!SkColorSpace::LoadGammas(&gammas->fRed, outputChannels, src + offse
tToMCurves, | 494 if (!load_gammas(gamma->fVec, outputChannels, src + offsetToMCurves, len
- offsetToMCurves)) |
490 len - offsetToMCurves)) { | 495 { |
491 SkColorSpacePrintf("Failed to read M curves from A to B tag.\n"); | 496 SkColorSpacePrintf("Failed to read M curves from A to B tag.\n"); |
492 } | 497 } |
493 } | 498 } |
494 | 499 |
495 uint32_t offsetToMatrix = read_big_endian_int(src + 16); | 500 uint32_t offsetToMatrix = read_big_endian_int(src + 16); |
496 if (0 != offsetToMatrix && offsetToMatrix < len) { | 501 if (0 != offsetToMatrix && offsetToMatrix < len) { |
497 if (!load_matrix(toXYZ, toXYZOffset, src + offsetToMatrix, len - offsetT
oMatrix)) { | 502 if (!load_matrix(toXYZ, toXYZOffset, src + offsetToMatrix, len - offsetT
oMatrix)) { |
498 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); | 503 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); |
499 } | 504 } |
500 } | 505 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 SkFloat3x3 toXYZ; | 560 SkFloat3x3 toXYZ; |
556 if (!load_xyz(&toXYZ.fMat[0], r->addr((const uint8_t*) base), r-
>fLength) || | 561 if (!load_xyz(&toXYZ.fMat[0], r->addr((const uint8_t*) base), r-
>fLength) || |
557 !load_xyz(&toXYZ.fMat[3], g->addr((const uint8_t*) base), g-
>fLength) || | 562 !load_xyz(&toXYZ.fMat[3], g->addr((const uint8_t*) base), g-
>fLength) || |
558 !load_xyz(&toXYZ.fMat[6], b->addr((const uint8_t*) base), b-
>fLength)) | 563 !load_xyz(&toXYZ.fMat[6], b->addr((const uint8_t*) base), b-
>fLength)) |
559 { | 564 { |
560 return_null("Need valid rgb tags for XYZ space"); | 565 return_null("Need valid rgb tags for XYZ space"); |
561 } | 566 } |
562 | 567 |
563 // It is not uncommon to see missing or empty gamma tags. This
indicates | 568 // It is not uncommon to see missing or empty gamma tags. This
indicates |
564 // that we should use unit gamma. | 569 // that we should use unit gamma. |
565 SkGammas gammas; | 570 SkFloat3 gamma {{ 1.0f, 1.0f, 1.0f }}; |
566 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); | 571 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); |
567 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); | 572 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); |
568 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); | 573 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); |
569 if (!r || !SkColorSpace::LoadGammas(&gammas.fRed, 1, | 574 if (!r || |
570 r->addr((const uint8_t*) bas
e), r->fLength)) { | 575 !load_gammas(&gamma.fVec[0], 1, r->addr((const uint8_t*) bas
e), r->fLength)) |
| 576 { |
571 SkColorSpacePrintf("Failed to read R gamma tag.\n"); | 577 SkColorSpacePrintf("Failed to read R gamma tag.\n"); |
572 } | 578 } |
573 if (!g || !SkColorSpace::LoadGammas(&gammas.fGreen, 1, | 579 if (!g || |
574 g->addr((const uint8_t*) bas
e), g->fLength)) { | 580 !load_gammas(&gamma.fVec[1], 1, g->addr((const uint8_t*) bas
e), g->fLength)) |
| 581 { |
575 SkColorSpacePrintf("Failed to read G gamma tag.\n"); | 582 SkColorSpacePrintf("Failed to read G gamma tag.\n"); |
576 } | 583 } |
577 if (!b || !SkColorSpace::LoadGammas(&gammas.fBlue, 1, | 584 if (!b || |
578 b->addr((const uint8_t*) bas
e), b->fLength)) { | 585 !load_gammas(&gamma.fVec[2], 1, b->addr((const uint8_t*) bas
e), b->fLength)) |
| 586 { |
579 SkColorSpacePrintf("Failed to read B gamma tag.\n"); | 587 SkColorSpacePrintf("Failed to read B gamma tag.\n"); |
580 } | 588 } |
581 return SkColorSpace::NewRGB(toXYZ, std::move(gammas)); | 589 return SkColorSpace::NewRGB(toXYZ, gamma); |
582 } | 590 } |
583 | 591 |
584 // Recognize color profile specified by A2B0 tag. | 592 // Recognize color profile specified by A2B0 tag. |
585 const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); | 593 const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); |
586 if (a2b0) { | 594 if (a2b0) { |
587 SkColorLookUpTable colorLUT; | 595 SkColorLookUpTable colorLUT; |
588 SkGammas gammas; | 596 SkFloat3 gamma; |
589 SkFloat3x3 toXYZ; | 597 SkFloat3x3 toXYZ; |
590 SkFloat3 toXYZOffset; | 598 SkFloat3 toXYZOffset; |
591 if (!SkColorSpace::LoadA2B0(&colorLUT, &gammas, &toXYZ, &toXYZOf
fset, | 599 if (!load_a2b0(&colorLUT, &gamma, &toXYZ, &toXYZOffset, |
592 a2b0->addr((const uint8_t*) base), a
2b0->fLength)) { | 600 a2b0->addr((const uint8_t*) base), a2b0->fLength)) { |
593 return_null("Failed to parse A2B0 tag"); | 601 return_null("Failed to parse A2B0 tag"); |
594 } | 602 } |
595 | 603 |
596 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT),
std::move(gammas), | 604 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT),
gamma, toXYZ, |
597 toXYZ, toXYZOffset))
; | 605 toXYZOffset)); |
598 } | 606 } |
599 | 607 |
600 } | 608 } |
601 default: | 609 default: |
602 break; | 610 break; |
603 } | 611 } |
604 | 612 |
605 return_null("ICC profile contains unsupported colorspace"); | 613 return_null("ICC profile contains unsupported colorspace"); |
606 } | 614 } |
OLD | NEW |