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 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 if (len < 20) { |
662 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); | 673 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); |
663 return false; | 674 return false; |
664 } | 675 } |
676 size_t dataLen = len - 20; | |
kjlubick
2016/06/20 14:27:23
Where's the magic number 20 coming from?
msarett
2016/06/20 14:44:11
20 is the number of bytes preceding the actual col
| |
665 | 677 |
666 SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels && 3 == outputCha nnels); | 678 SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels && 3 == outputCha nnels); |
667 colorLUT->fInputChannels = inputChannels; | 679 colorLUT->fInputChannels = inputChannels; |
668 colorLUT->fOutputChannels = outputChannels; | 680 colorLUT->fOutputChannels = outputChannels; |
669 uint32_t numEntries = 1; | 681 uint32_t numEntries = 1; |
670 for (uint32_t i = 0; i < inputChannels; i++) { | 682 for (uint32_t i = 0; i < inputChannels; i++) { |
671 colorLUT->fGridPoints[i] = src[i]; | 683 colorLUT->fGridPoints[i] = src[i]; |
672 numEntries *= src[i]; | 684 if (0 == src[i]) { |
685 SkColorSpacePrintf("Each input channel must have at least one grid p oint."); | |
686 return false; | |
687 } | |
688 | |
689 if (!safe_mul(numEntries, src[i], &numEntries)) { | |
690 SkColorSpacePrintf("Too many entries in Color LUT."); | |
691 return false; | |
692 } | |
673 } | 693 } |
674 numEntries *= outputChannels; | 694 |
695 if (!safe_mul(numEntries, outputChannels, &numEntries)) { | |
696 SkColorSpacePrintf("Too many entries in Color LUT."); | |
697 return false; | |
698 } | |
675 | 699 |
676 // Space is provided for a maximum of the 16 input channels. Now we determi ne the precision | 700 // Space is provided for a maximum of the 16 input channels. Now we determi ne the precision |
677 // of the table values. | 701 // of the table values. |
678 uint8_t precision = src[16]; | 702 uint8_t precision = src[16]; |
679 switch (precision) { | 703 switch (precision) { |
680 case 1: // 8-bit data | 704 case 1: // 8-bit data |
681 case 2: // 16-bit data | 705 case 2: // 16-bit data |
682 break; | 706 break; |
683 default: | 707 default: |
684 SkColorSpacePrintf("Color LUT precision must be 8-bit or 16-bit.\n", len); | 708 SkColorSpacePrintf("Color LUT precision must be 8-bit or 16-bit.\n") ; |
685 return false; | 709 return false; |
686 } | 710 } |
687 | 711 |
688 if (len < 20 + numEntries * precision) { | 712 uint32_t clutBytes; |
713 if (!safe_mul(numEntries, precision, &clutBytes)) { | |
714 SkColorSpacePrintf("Too many entries in Color LUT."); | |
715 return false; | |
716 } | |
717 | |
718 if (dataLen < clutBytes) { | |
689 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); | 719 SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len); |
690 return false; | 720 return false; |
691 } | 721 } |
692 | 722 |
693 // Movable struct colorLUT has ownership of fTable. | 723 // Movable struct colorLUT has ownership of fTable. |
694 colorLUT->fTable = std::unique_ptr<float[]>(new float[numEntries]); | 724 colorLUT->fTable = std::unique_ptr<float[]>(new float[numEntries]); |
695 const uint8_t* ptr = src + 20; | 725 const uint8_t* ptr = src + 20; |
696 for (uint32_t i = 0; i < numEntries; i++, ptr += precision) { | 726 for (uint32_t i = 0; i < numEntries; i++, ptr += precision) { |
697 if (1 == precision) { | 727 if (1 == precision) { |
698 colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; | 728 colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1168 ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1198 ptr32[4] = SkEndian_SwapBE32(0x000116cc); |
1169 ptr += kTAG_XYZ_Bytes; | 1199 ptr += kTAG_XYZ_Bytes; |
1170 | 1200 |
1171 // Write copyright tag | 1201 // Write copyright tag |
1172 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1202 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); |
1173 | 1203 |
1174 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if | 1204 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if |
1175 // the client calls again? | 1205 // the client calls again? |
1176 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1206 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
1177 } | 1207 } |
OLD | NEW |