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 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 if (arg1 >= 0 && arg2 <= std::numeric_limits<T>::max() - arg1) { | 312 if (arg1 >= 0 && arg2 <= std::numeric_limits<T>::max() - arg1) { |
313 T sum = arg1 + arg2; | 313 T sum = arg1 + arg2; |
314 if (sum <= std::numeric_limits<size_t>::max()) { | 314 if (sum <= std::numeric_limits<size_t>::max()) { |
315 *result = static_cast<size_t>(sum); | 315 *result = static_cast<size_t>(sum); |
316 return true; | 316 return true; |
317 } | 317 } |
318 } | 318 } |
319 return false; | 319 return false; |
320 } | 320 } |
321 | 321 |
| 322 static bool safe_mul(uint32_t arg1, uint32_t arg2, uint32_t* result) { |
| 323 uint64_t product64 = (uint64_t) arg1 * (uint64_t) arg2; |
| 324 uint32_t product32 = (uint32_t) product64; |
| 325 if (product32 != product64) { |
| 326 return false; |
| 327 } |
| 328 |
| 329 *result = product32; |
| 330 return true; |
| 331 } |
| 332 |
322 struct ICCTag { | 333 struct ICCTag { |
323 uint32_t fSignature; | 334 uint32_t fSignature; |
324 uint32_t fOffset; | 335 uint32_t fOffset; |
325 uint32_t fLength; | 336 uint32_t fLength; |
326 | 337 |
327 const uint8_t* init(const uint8_t* src) { | 338 const uint8_t* init(const uint8_t* src) { |
328 fSignature = read_big_endian_uint(src); | 339 fSignature = read_big_endian_uint(src); |
329 fOffset = read_big_endian_uint(src + 4); | 340 fOffset = read_big_endian_uint(src + 4); |
330 fLength = read_big_endian_uint(src + 8); | 341 fLength = read_big_endian_uint(src + 8); |
331 return src + 12; | 342 return src + 12; |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 } | 662 } |
652 } | 663 } |
653 | 664 |
654 return true; | 665 return true; |
655 } | 666 } |
656 | 667 |
657 static constexpr uint32_t kTAG_AtoBType = SkSetFourByteTag('m', 'A', 'B', ' '); | 668 static constexpr uint32_t kTAG_AtoBType = SkSetFourByteTag('m', 'A', 'B', ' '); |
658 | 669 |
659 bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, uint32
_t outputChannels, | 670 bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, uint32
_t outputChannels, |
660 const uint8_t* src, size_t len) { | 671 const uint8_t* src, size_t len) { |
661 if (len < 20) { | 672 // 16 bytes reserved for grid points, 2 for precision, 2 for padding. |
| 673 // The color LUT data follows after this header. |
| 674 static constexpr uint32_t kColorLUTHeaderSize = 20; |
| 675 if (len < kColorLUTHeaderSize) { |
662 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); | 676 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); |
663 return false; | 677 return false; |
664 } | 678 } |
| 679 size_t dataLen = len - kColorLUTHeaderSize; |
665 | 680 |
666 SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels && 3 == outputCha
nnels); | 681 SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels && 3 == outputCha
nnels); |
667 colorLUT->fInputChannels = inputChannels; | 682 colorLUT->fInputChannels = inputChannels; |
668 colorLUT->fOutputChannels = outputChannels; | 683 colorLUT->fOutputChannels = outputChannels; |
669 uint32_t numEntries = 1; | 684 uint32_t numEntries = 1; |
670 for (uint32_t i = 0; i < inputChannels; i++) { | 685 for (uint32_t i = 0; i < inputChannels; i++) { |
671 colorLUT->fGridPoints[i] = src[i]; | 686 colorLUT->fGridPoints[i] = src[i]; |
672 numEntries *= src[i]; | 687 if (0 == src[i]) { |
| 688 SkColorSpacePrintf("Each input channel must have at least one grid p
oint."); |
| 689 return false; |
| 690 } |
| 691 |
| 692 if (!safe_mul(numEntries, src[i], &numEntries)) { |
| 693 SkColorSpacePrintf("Too many entries in Color LUT."); |
| 694 return false; |
| 695 } |
673 } | 696 } |
674 numEntries *= outputChannels; | 697 |
| 698 if (!safe_mul(numEntries, outputChannels, &numEntries)) { |
| 699 SkColorSpacePrintf("Too many entries in Color LUT."); |
| 700 return false; |
| 701 } |
675 | 702 |
676 // Space is provided for a maximum of the 16 input channels. Now we determi
ne the precision | 703 // Space is provided for a maximum of the 16 input channels. Now we determi
ne the precision |
677 // of the table values. | 704 // of the table values. |
678 uint8_t precision = src[16]; | 705 uint8_t precision = src[16]; |
679 switch (precision) { | 706 switch (precision) { |
680 case 1: // 8-bit data | 707 case 1: // 8-bit data |
681 case 2: // 16-bit data | 708 case 2: // 16-bit data |
682 break; | 709 break; |
683 default: | 710 default: |
684 SkColorSpacePrintf("Color LUT precision must be 8-bit or 16-bit.\n",
len); | 711 SkColorSpacePrintf("Color LUT precision must be 8-bit or 16-bit.\n")
; |
685 return false; | 712 return false; |
686 } | 713 } |
687 | 714 |
688 if (len < 20 + numEntries * precision) { | 715 uint32_t clutBytes; |
| 716 if (!safe_mul(numEntries, precision, &clutBytes)) { |
| 717 SkColorSpacePrintf("Too many entries in Color LUT."); |
| 718 return false; |
| 719 } |
| 720 |
| 721 if (dataLen < clutBytes) { |
689 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); | 722 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); |
690 return false; | 723 return false; |
691 } | 724 } |
692 | 725 |
693 // Movable struct colorLUT has ownership of fTable. | 726 // Movable struct colorLUT has ownership of fTable. |
694 colorLUT->fTable = std::unique_ptr<float[]>(new float[numEntries]); | 727 colorLUT->fTable = std::unique_ptr<float[]>(new float[numEntries]); |
695 const uint8_t* ptr = src + 20; | 728 const uint8_t* ptr = src + kColorLUTHeaderSize; |
696 for (uint32_t i = 0; i < numEntries; i++, ptr += precision) { | 729 for (uint32_t i = 0; i < numEntries; i++, ptr += precision) { |
697 if (1 == precision) { | 730 if (1 == precision) { |
698 colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; | 731 colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; |
699 } else { | 732 } else { |
700 colorLUT->fTable[i] = ((float) read_big_endian_short(ptr)) / 65535.0
f; | 733 colorLUT->fTable[i] = ((float) read_big_endian_short(ptr)) / 65535.0
f; |
701 } | 734 } |
702 } | 735 } |
703 | 736 |
704 return true; | 737 return true; |
705 } | 738 } |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1201 ptr32[4] = SkEndian_SwapBE32(0x000116cc); |
1169 ptr += kTAG_XYZ_Bytes; | 1202 ptr += kTAG_XYZ_Bytes; |
1170 | 1203 |
1171 // Write copyright tag | 1204 // Write copyright tag |
1172 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1205 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); |
1173 | 1206 |
1174 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if | 1207 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if |
1175 // the client calls again? | 1208 // the client calls again? |
1176 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1209 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
1177 } | 1210 } |
OLD | NEW |