30 for (
const auto&
params : decoderApp1Params) {
32 if (
params->size() <= kSigSize) {
57 const char* guidAscii) {
59 constexpr size_t kFullLengthSize = 4;
60 constexpr size_t kOffsetSize = 4;
71 if (guidAscii[
i] >=
'0' && guidAscii[
i] <=
'9') {
72 digit = guidAscii[
i] -
'0';
73 }
else if (guidAscii[
i] >=
'A' && guidAscii[
i] <=
'F') {
74 digit = guidAscii[
i] -
'A' + 10;
80 guidAsDigest.
data[
i / 2] = 16 * digit;
82 guidAsDigest.
data[
i / 2] += digit;
87 uint32_t fullLength = 0;
88 using Part = std::tuple<uint32_t, sk_sp<SkData>>;
89 std::vector<Part>
parts;
90 for (
const auto&
params : decoderApp1Params) {
100 const uint8_t* partGuidAscii =
params->bytes() + kSigSize;
107 uint32_t partFullLength = 0;
108 uint32_t partOffset = 0;
110 const uint8_t* partOffsetBytes =
112 for (
size_t i = 0;
i < 4; ++
i) {
113 partFullLength *= 256;
115 partFullLength += partFullLengthBytes[
i];
116 partOffset += partOffsetBytes[
i];
121 fullLength = partFullLength;
125 if (partFullLength != fullLength) {
126 SkCodecPrintf(
"Multiple parts had different total lengths.\n");
133 parts.push_back({partOffset, partData});
135 if (
parts.empty() || fullLength == 0) {
141 return std::get<0>(a) < std::get<0>(b);
146 uint8_t* xmpExtendedBase =
reinterpret_cast<uint8_t*
>(xmpExtendedData->writable_data());
147 uint8_t* xmpExtendedCurrent = xmpExtendedBase;
149 for (
const auto& part :
parts) {
150 uint32_t currentOffset =
static_cast<uint32_t
>(xmpExtendedCurrent - xmpExtendedBase);
154 if (partOffset != currentOffset) {
158 if (partData->
size() > fullLength - currentOffset) {
162 memcpy(xmpExtendedCurrent, partData->
data(), partData->
size());
163 xmpExtendedCurrent += partData->
size();
166 if (
static_cast<uint32_t
>(xmpExtendedCurrent - xmpExtendedBase) != fullLength) {
172 md5.write(xmpExtendedData->data(), xmpExtendedData->size());
173 if (
md5.finish() != guidAsDigest) {
178 return xmpExtendedData;
187 std::unique_ptr<SkXmp> xmp =
SkXmp::Make(xmpStandard);
193 const char* extendedGuid = xmp->getExtendedXmpGuid();
201 SkCodecPrintf(
"Extended XMP was indicated but failed to read or validate.\n");
static SkMD5::Digest md5(const SkBitmap &bm)
#define SkCodecPrintf(...)
static constexpr size_t kHeaderSize
static constexpr uint8_t kXMPStandardSig[]
static constexpr uint8_t kXMPExtendedSig[]
static sk_sp< SkData > read_xmp_standard(const std::vector< sk_sp< SkData > > &decoderApp1Params)
constexpr size_t kGuidAsciiSize
static sk_sp< SkData > read_xmp_extended(const std::vector< sk_sp< SkData > > &decoderApp1Params, const char *guidAscii)
std::unique_ptr< SkXmp > SkJpegMakeXmp(const std::vector< sk_sp< SkData > > &decoderApp1Params)
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
static sk_sp< SkData > MakeUninitialized(size_t length)
const void * data() const
static std::unique_ptr< SkXmp > Make(sk_sp< SkData > xmpData)
const EmbeddedViewParams * params
const myers::Point & get< 1 >(const myers::Segment &s)
const myers::Point & get< 0 >(const myers::Segment &s)