54 const std::string& childName) {
56 if (
dom.countChildren(node, childName.c_str()) != 1) {
59 const auto* child =
dom.getFirstChild(node, childName.c_str());
64 if (
dom.countChildren(child) != 1) {
67 const auto* grandChild =
dom.getFirstChild(child);
72 return dom.getName(grandChild);
88 const std::string& prefix,
89 const std::string&
type) {
90 const auto name = prefix + std::string(
":") +
type;
96 const SkDOM::Node* typeChild =
dom->getFirstChild(node,
"rdf:type");
100 const char* typeChildResource =
dom->findAttr(typeChild,
"rdf:resource");
101 if (!typeChildResource || typeChildResource !=
type) {
105 const SkDOM::Node* valueChild =
dom->getFirstChild(node,
"rdf:value");
109 const char* valueChildParseType =
dom->findAttr(valueChild,
"rdf:parseType");
110 if (!valueChildParseType || strcmp(valueChildParseType,
"Resource") != 0) {
127 const std::string& prefix,
128 const std::string&
key) {
129 const auto name = prefix +
":" +
key;
130 const char* attr =
dom->findAttr(node,
name.c_str());
140 const std::string& prefix,
141 const std::string&
key,
163 const std::string& prefix,
164 const std::string&
key,
179 const std::string& prefix,
180 const std::string&
key,
198 const std::string& prefix,
199 const std::string&
key,
201 const auto name = prefix +
":" +
key;
204 if (
dom->countChildren(node,
name.c_str()) != 1) {
208 const auto* child =
dom->getFirstChild(node,
name.c_str());
214 const auto* seq =
dom->getFirstChild(child,
"rdf:Seq");
220 SkScalar values[3] = {0.f, 0.f, 0.f};
221 for (
const auto* liNode =
dom->getFirstChild(seq,
"rdf:li"); liNode;
222 liNode =
dom->getNextSibling(liNode,
"rdf:li")) {
227 if (
dom->countChildren(liNode) != 1) {
231 const auto* liTextNode =
dom->getFirstChild(liNode);
236 const char* liText =
dom->getName(liTextNode);
251 *outValue = {values[0], values[1], values[2], 1.f};
257 const std::string& prefix,
258 const std::string&
key,
275 const char* outNamespaces[]) {
277 for (
const auto* attr =
dom.getFirstAttr(node); attr; attr =
dom.getNextAttr(node, attr)) {
278 const char* attrName =
dom.getAttrName(node, attr);
279 const char* attrValue =
dom.getAttrValue(node, attr);
280 if (!attrName || !attrValue) {
291 for (
size_t i = 0; i <
count; ++i) {
292 if (strcmp(attrValue, uris[i]) != 0) {
295 outNamespaces[i] = attrName;
305 const char* outNamespaces[]) {
312 const char* rootName =
dom.getName(root);
313 if (!rootName || strcmp(rootName,
"x:xmpmeta") != 0) {
318 const char* kRdf =
"rdf:RDF";
319 for (
const auto* rdf =
dom.getFirstChild(root, kRdf); rdf;
320 rdf =
dom.getNextSibling(rdf, kRdf)) {
321 std::vector<const char*> rdfNamespaces(
count,
nullptr);
325 const char* kDesc =
"rdf:Description";
326 for (
const auto* desc =
dom.getFirstChild(rdf, kDesc); desc;
327 desc =
dom.getNextSibling(desc, kDesc)) {
328 std::vector<const char*> descNamespaces = rdfNamespaces;
332 bool foundAllUris =
true;
333 for (
size_t i = 0; i <
count; ++i) {
334 if (!descNamespaces[i]) {
335 foundAllUris =
false;
340 for (
size_t i = 0; i <
count; ++i) {
341 outNamespaces[i] = descNamespaces[i];
366 bool findUriNamespaces(
size_t count,
368 const char* outNamespaces[],
369 const SkDOM** outDom,
377 const char* namespaces[1] = {
nullptr};
378 const char* uris[1] = {
"http://ns.adobe.com/xmp/note/"};
385 return get_attr(&fStandardDOM, extendedNode, xmpNotePrefix,
"HasExtendedXMP");
388bool SkXmpImpl::findUriNamespaces(
size_t count,
390 const char* outNamespaces[],
391 const SkDOM** outDom,
400 *outDom = &fStandardDOM;
405 *outDom = &fExtendedDOM;
414 const char* namespaces[2] = {
nullptr,
nullptr};
415 const char* uris[2] = {
"http://ns.google.com/photos/1.0/container/",
416 "http://ns.google.com/photos/1.0/container/item/"};
419 if (!findUriNamespaces(2, uris, namespaces, &
dom, &node)) {
433 const auto* seq =
dom->getFirstChild(directory,
"rdf:Seq");
441 bool isFirstItem =
true;
443 for (
const auto* li =
dom->getFirstChild(seq,
"rdf:li"); li;
444 li =
dom->getNextSibling(li,
"rdf:li")) {
452 const char* itemSemantic =
get_attr(
dom, item, itemPrefix,
"Semantic");
458 const char* itemMime =
get_attr(
dom, item, itemPrefix,
"Mime");
467 if (strcmp(itemSemantic,
"Primary") != 0) {
472 if (strcmp(itemMime,
"image/jpeg") != 0) {
473 SkCodecPrintf(
"Primary does not report that it is image/jpeg.\n");
499 if (strcmp(itemSemantic,
"GainMap") != 0) {
504 if (strcmp(itemMime,
"image/jpeg") != 0) {
505 SkCodecPrintf(
"GainMap does not report that it is image/jpeg.\n");
521 const char* namespaces[2] = {
nullptr,
nullptr};
522 const char* uris[2] = {
"http://ns.apple.com/pixeldatainfo/1.0/",
523 "http://ns.apple.com/HDRGainMap/1.0/"};
526 if (!findUriNamespaces(2, uris, namespaces, &
dom, &node)) {
532 const char* auxiliaryImageType =
get_attr(
dom, node, adpiPrefix,
"AuxiliaryImageType");
533 if (!auxiliaryImageType) {
537 if (strcmp(auxiliaryImageType,
"urn:com:apple:photo:2020:aux:hdrgainmap") != 0) {
543 if (!
get_attr_int32(
dom, node, hdrGainMapPrefix,
"HDRGainMapVersion", &version)) {
547 if (version != 65536) {
554 const float kRatioMax = std::exp(1.f);
555 info->fGainmapRatioMin = {1.f, 1.f, 1.f, 1.f};
556 info->fGainmapRatioMax = {kRatioMax, kRatioMax, kRatioMax, 1.f};
557 info->fGainmapGamma = {1.f, 1.f, 1.f, 1.f};
558 info->fEpsilonSdr = {0.f, 0.f, 0.f, 1.f};
559 info->fEpsilonHdr = {0.f, 0.f, 0.f, 1.f};
560 info->fDisplayRatioSdr = 1.f;
561 info->fDisplayRatioHdr = kRatioMax;
568 const char* namespaces[1] = {
nullptr};
569 const char* uris[1] = {
"http://ns.adobe.com/hdr-gain-map/1.0/"};
572 if (!findUriNamespaces(1, uris, namespaces, &
dom, &node)) {
578 const char* version =
get_attr(
dom, node, hdrgmPrefix,
"Version");
583 if (strcmp(version,
"1.0") != 0) {
589 bool baseRenditionIsHDR =
false;
590 SkColor4f gainMapMin = {0.f, 0.f, 0.f, 1.f};
591 SkColor4f gainMapMax = {1.f, 1.f, 1.f, 1.f};
593 SkColor4f offsetSdr = {1.f / 64.f, 1.f / 64.f, 1.f / 64.f, 0.f};
594 SkColor4f offsetHdr = {1.f / 64.f, 1.f / 64.f, 1.f / 64.f, 0.f};
599 get_attr_bool(
dom, node, hdrgmPrefix,
"BaseRenditionIsHDR", &baseRenditionIsHDR);
609 const float kLog2 = std::log(2.f);
611 std::exp(gainMapMin.fG * kLog2),
612 std::exp(gainMapMin.fB * kLog2),
615 std::exp(gainMapMax.fG * kLog2),
616 std::exp(gainMapMax.fB * kLog2),
618 outGainmapInfo->
fGainmapGamma = {1.f / gamma.fR, 1.f / gamma.fG, 1.f / gamma.fB, 1.f};
623 if (baseRenditionIsHDR) {
634 if (!
dom->build(*xmpdStream)) {
645 std::unique_ptr<SkXmpImpl> xmp(
new SkXmpImpl);
646 if (!xmp->parseDom(std::move(xmpData),
false)) {
653 std::unique_ptr<SkXmpImpl> xmp(
new SkXmpImpl);
654 if (!xmp->parseDom(std::move(xmpStandard),
false)) {
659 (void)xmp->parseDom(std::move(xmpExtended),
true);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
#define SkCodecPrintf(...)
static void find_uri_namespaces(const SkDOM &dom, const SkDOM::Node *node, size_t count, const char *uris[], const char *outNamespaces[])
static bool get_attr_float3_as_list(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, SkColor4f *outValue)
const size_t kXmlnsPrefixLength
static const char * get_unique_child_text(const SkDOM &dom, const SkDOM::Node *node, const std::string &childName)
static const char * get_attr(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key)
static bool get_attr_bool(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, bool *outValue)
static bool get_attr_float3(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, SkColor4f *outValue)
static const char * get_namespace_prefix(const char *name)
static bool get_attr_int32(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, int32_t *value)
const char * kXmlnsPrefix
static const SkDOM::Node * get_typed_child(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &type)
static bool get_attr_float(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, float *outValue)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
static const char * FindScalar(const char str[], SkScalar *value)
static const char * FindS32(const char str[], int32_t *value)
static int FindList(const char str[], const char list[])
const char * getExtendedXmpGuid() const override
bool parseDom(sk_sp< SkData > xmpData, bool extended)
bool getGainmapInfoHDRGM(SkGainmapInfo *info) const override
bool getGainmapInfoHDRGainMap(SkGainmapInfo *info) const override
bool getContainerGainmapLocation(size_t *offset, size_t *size) const override
static std::unique_ptr< SkXmp > Make(sk_sp< SkData > xmpData)
SkColor4f fGainmapRatioMax
SkColor4f fGainmapRatioMin
BaseImageType fBaseImageType