Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
SkXmpImpl Class Referencefinal
Inheritance diagram for SkXmpImpl:
SkXmp

Public Member Functions

 SkXmpImpl ()=default
 
bool getGainmapInfoAdobe (SkGainmapInfo *info) const override
 
bool getGainmapInfoApple (float exifHdrHeadroom, SkGainmapInfo *info) const override
 
bool getContainerGainmapLocation (size_t *offset, size_t *size) const override
 
const char * getExtendedXmpGuid () const override
 
bool parseDom (sk_sp< SkData > xmpData, bool extended)
 
- Public Member Functions inherited from SkXmp
 SkXmp ()=default
 
virtual ~SkXmp ()=default
 
 SkXmp (const SkXmp &)=delete
 
SkXmpoperator= (const SkXmp &)=delete
 
bool getGainmapInfoHDRGM (SkGainmapInfo *info) const
 
virtual bool getGainmapInfoAdobe (SkGainmapInfo *info) const =0
 
virtual bool getGainmapInfoApple (float exifHdrHeadroom, SkGainmapInfo *info) const =0
 
virtual bool getContainerGainmapLocation (size_t *offset, size_t *size) const =0
 
virtual const char * getExtendedXmpGuid () const =0
 

Additional Inherited Members

- Static Public Member Functions inherited from SkXmp
static std::unique_ptr< SkXmpMake (sk_sp< SkData > xmpData)
 
static std::unique_ptr< SkXmpMake (sk_sp< SkData > xmpStandard, sk_sp< SkData > xmpExtended)
 

Detailed Description

Definition at line 353 of file SkXmp.cpp.

Constructor & Destructor Documentation

◆ SkXmpImpl()

SkXmpImpl::SkXmpImpl ( )
default

Member Function Documentation

◆ getContainerGainmapLocation()

bool SkXmpImpl::getContainerGainmapLocation ( size_t *  offset,
size_t *  size 
) const
overridevirtual

Implements SkXmp.

Definition at line 412 of file SkXmp.cpp.

412 {
413 // Find a node that matches the requested namespaces and URIs.
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/"};
417 const SkDOM* dom = nullptr;
418 const SkDOM::Node* node = nullptr;
419 if (!findUriNamespaces(2, uris, namespaces, &dom, &node)) {
420 return false;
421 }
422 const char* containerPrefix = get_namespace_prefix(namespaces[0]);
423 const char* itemPrefix = get_namespace_prefix(namespaces[1]);
424
425 // The node must have a Container:Directory child.
426 const auto* directory = get_typed_child(dom, node, containerPrefix, "Directory");
427 if (!directory) {
428 SkCodecPrintf("Missing Container Directory");
429 return false;
430 }
431
432 // That Container:Directory must have a sequence of items.
433 const auto* seq = dom->getFirstChild(directory, "rdf:Seq");
434 if (!seq) {
435 SkCodecPrintf("Missing rdf:Seq");
436 return false;
437 }
438
439 // Iterate through the items in the Container:Directory's sequence. Keep a running sum of the
440 // Item:Length of all items that appear before the GainMap.
441 bool isFirstItem = true;
442 size_t offset = 0;
443 for (const auto* li = dom->getFirstChild(seq, "rdf:li"); li;
444 li = dom->getNextSibling(li, "rdf:li")) {
445 // Each list item must contain a Container:Item.
446 const auto* item = get_typed_child(dom, li, containerPrefix, "Item");
447 if (!item) {
448 SkCodecPrintf("List item does not have container Item.\n");
449 return false;
450 }
451 // A Semantic is required for every item.
452 const char* itemSemantic = get_attr(dom, item, itemPrefix, "Semantic");
453 if (!itemSemantic) {
454 SkCodecPrintf("Item is missing Semantic.\n");
455 return false;
456 }
457 // A Mime is required for every item.
458 const char* itemMime = get_attr(dom, item, itemPrefix, "Mime");
459 if (!itemMime) {
460 SkCodecPrintf("Item is missing Mime.\n");
461 return false;
462 }
463
464 if (isFirstItem) {
465 isFirstItem = false;
466 // The first item must be Primary.
467 if (strcmp(itemSemantic, "Primary") != 0) {
468 SkCodecPrintf("First item is not Primary.\n");
469 return false;
470 }
471 // The first item has mime type image/jpeg (we are decoding a jpeg).
472 if (strcmp(itemMime, "image/jpeg") != 0) {
473 SkCodecPrintf("Primary does not report that it is image/jpeg.\n");
474 return false;
475 }
476 // The first media item can contain a Padding attribute, which specifies additional
477 // padding between the end of the encoded primary image and the beginning of the next
478 // media item. Only the first media item can contain a Padding attribute.
479 int32_t padding = 0;
480 if (get_attr_int32(dom, item, itemPrefix, "Padding", &padding)) {
481 if (padding < 0) {
482 SkCodecPrintf("Item padding must be non-negative.");
483 return false;
484 }
485 offset += padding;
486 }
487 } else {
488 // A Length is required for all non-Primary items.
489 int32_t length = 0;
490 if (!get_attr_int32(dom, item, itemPrefix, "Length", &length)) {
491 SkCodecPrintf("Item length is absent.");
492 return false;
493 }
494 if (length < 0) {
495 SkCodecPrintf("Item length must be non-negative.");
496 return false;
497 }
498 // If this is not the recovery map, then read past it.
499 if (strcmp(itemSemantic, "GainMap") != 0) {
500 offset += length;
501 continue;
502 }
503 // The recovery map must have mime type image/jpeg in this implementation.
504 if (strcmp(itemMime, "image/jpeg") != 0) {
505 SkCodecPrintf("GainMap does not report that it is image/jpeg.\n");
506 return false;
507 }
508
509 // Populate the location in the file at which to find the gainmap image.
510 *outOffset = offset;
511 *outSize = length;
512 return true;
513 }
514 }
515 return false;
516}
#define SkCodecPrintf(...)
Definition: SkCodecPriv.h:23
static const char * get_attr(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key)
Definition: SkXmp.cpp:125
static const char * get_namespace_prefix(const char *name)
Definition: SkXmp.cpp:32
static bool get_attr_int32(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, int32_t *value)
Definition: SkXmp.cpp:161
static const SkDOM::Node * get_typed_child(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &type)
Definition: SkXmp.cpp:86
Definition: SkDOM.h:24
size_t length
Definition: dom.py:1
SeparatedVector2 offset

◆ getExtendedXmpGuid()

const char * SkXmpImpl::getExtendedXmpGuid ( ) const
overridevirtual

Implements SkXmp.

Definition at line 376 of file SkXmp.cpp.

376 {
377 const char* namespaces[1] = {nullptr};
378 const char* uris[1] = {"http://ns.adobe.com/xmp/note/"};
379 const auto* extendedNode = find_uri_namespaces(fStandardDOM, 1, uris, namespaces);
380 if (!extendedNode) {
381 return nullptr;
382 }
383 const auto xmpNotePrefix = get_namespace_prefix(namespaces[0]);
384 // Extract the GUID (the MD5 hash) of the extended metadata.
385 return get_attr(&fStandardDOM, extendedNode, xmpNotePrefix, "HasExtendedXMP");
386}
static void find_uri_namespaces(const SkDOM &dom, const SkDOM::Node *node, size_t count, const char *uris[], const char *outNamespaces[])
Definition: SkXmp.cpp:271

◆ getGainmapInfoAdobe()

bool SkXmpImpl::getGainmapInfoAdobe ( SkGainmapInfo info) const
overridevirtual

Implements SkXmp.

Definition at line 571 of file SkXmp.cpp.

571 {
572 // Find a node that matches the requested namespace and URI.
573 const char* namespaces[1] = {nullptr};
574 const char* uris[1] = {"http://ns.adobe.com/hdr-gain-map/1.0/"};
575 const SkDOM* dom = nullptr;
576 const SkDOM::Node* node = nullptr;
577 if (!findUriNamespaces(1, uris, namespaces, &dom, &node)) {
578 return false;
579 }
580 const char* hdrgmPrefix = get_namespace_prefix(namespaces[0]);
581
582 // Require that hdrgm:Version="1.0" be present.
583 const char* version = get_attr(dom, node, hdrgmPrefix, "Version");
584 if (!version) {
585 SkCodecPrintf("Version attribute is absent.\n");
586 return false;
587 }
588 if (strcmp(version, "1.0") != 0) {
589 SkCodecPrintf("Version is \"%s\", not \"1.0\".\n", version);
590 return false;
591 }
592
593 // Initialize the parameters to their defaults.
594 bool baseRenditionIsHDR = false;
595 SkColor4f gainMapMin = {0.f, 0.f, 0.f, 1.f}; // log2 value
596 SkColor4f gainMapMax = {1.f, 1.f, 1.f, 1.f}; // log2 value
597 SkColor4f gamma = {1.f, 1.f, 1.f, 1.f};
598 SkColor4f offsetSdr = {1.f / 64.f, 1.f / 64.f, 1.f / 64.f, 0.f};
599 SkColor4f offsetHdr = {1.f / 64.f, 1.f / 64.f, 1.f / 64.f, 0.f};
600 SkScalar hdrCapacityMin = 0.f; // log2 value
601 SkScalar hdrCapacityMax = 1.f; // log2 value
602
603 // Read all parameters that are present.
604 get_attr_bool(dom, node, hdrgmPrefix, "BaseRenditionIsHDR", &baseRenditionIsHDR);
605 get_attr_float3(dom, node, hdrgmPrefix, "GainMapMin", &gainMapMin);
606 get_attr_float3(dom, node, hdrgmPrefix, "GainMapMax", &gainMapMax);
607 get_attr_float3(dom, node, hdrgmPrefix, "Gamma", &gamma);
608 get_attr_float3(dom, node, hdrgmPrefix, "OffsetSDR", &offsetSdr);
609 get_attr_float3(dom, node, hdrgmPrefix, "OffsetHDR", &offsetHdr);
610 get_attr_float(dom, node, hdrgmPrefix, "HDRCapacityMin", &hdrCapacityMin);
611 get_attr_float(dom, node, hdrgmPrefix, "HDRCapacityMax", &hdrCapacityMax);
612
613 // Translate all parameters to SkGainmapInfo's expected format.
614 if (!outGainmapInfo) {
615 return true;
616 }
617 const float kLog2 = std::log(2.f);
618 outGainmapInfo->fGainmapRatioMin = {std::exp(gainMapMin.fR * kLog2),
619 std::exp(gainMapMin.fG * kLog2),
620 std::exp(gainMapMin.fB * kLog2),
621 1.f};
622 outGainmapInfo->fGainmapRatioMax = {std::exp(gainMapMax.fR * kLog2),
623 std::exp(gainMapMax.fG * kLog2),
624 std::exp(gainMapMax.fB * kLog2),
625 1.f};
626 outGainmapInfo->fGainmapGamma = {1.f / gamma.fR, 1.f / gamma.fG, 1.f / gamma.fB, 1.f};
627 outGainmapInfo->fEpsilonSdr = offsetSdr;
628 outGainmapInfo->fEpsilonHdr = offsetHdr;
629 outGainmapInfo->fDisplayRatioSdr = std::exp(hdrCapacityMin * kLog2);
630 outGainmapInfo->fDisplayRatioHdr = std::exp(hdrCapacityMax * kLog2);
631 if (baseRenditionIsHDR) {
632 outGainmapInfo->fBaseImageType = SkGainmapInfo::BaseImageType::kHDR;
633 } else {
634 outGainmapInfo->fBaseImageType = SkGainmapInfo::BaseImageType::kSDR;
635 }
636 return true;
637}
static bool get_attr_bool(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, bool *outValue)
Definition: SkXmp.cpp:138
static bool get_attr_float3(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, SkColor4f *outValue)
Definition: SkXmp.cpp:255
static bool get_attr_float(const SkDOM *dom, const SkDOM::Node *node, const std::string &prefix, const std::string &key, float *outValue)
Definition: SkXmp.cpp:177
float SkScalar
Definition: extension.cpp:12

◆ getGainmapInfoApple()

bool SkXmpImpl::getGainmapInfoApple ( float  exifHdrHeadroom,
SkGainmapInfo info 
) const
overridevirtual

Implements SkXmp.

Definition at line 519 of file SkXmp.cpp.

519 {
520 // Find a node that matches the requested namespaces and URIs.
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/"};
524 const SkDOM* dom = nullptr;
525 const SkDOM::Node* node = nullptr;
526 if (!findUriNamespaces(2, uris, namespaces, &dom, &node)) {
527 return false;
528 }
529 const char* adpiPrefix = get_namespace_prefix(namespaces[0]);
530 const char* hdrGainMapPrefix = get_namespace_prefix(namespaces[1]);
531
532 const char* auxiliaryImageType = get_attr(dom, node, adpiPrefix, "AuxiliaryImageType");
533 if (!auxiliaryImageType) {
534 SkCodecPrintf("Did not find AuxiliaryImageType.\n");
535 return false;
536 }
537 if (strcmp(auxiliaryImageType, "urn:com:apple:photo:2020:aux:hdrgainmap") != 0) {
538 SkCodecPrintf("AuxiliaryImageType was not HDR gain map.\n");
539 return false;
540 }
541
542 // Require that the gainmap version be present, but do not require a specific version.
543 int32_t version = 0;
544 if (!get_attr_int32(dom, node, hdrGainMapPrefix, "HDRGainMapVersion", &version)) {
545 SkCodecPrintf("Did not find HDRGainMapVersion.\n");
546 return false;
547 }
548
549 // If the XMP also specifies a HDRGainMapHeadroom parameter, then prefer that parameter to the
550 // parameter specified in the base image Exif.
551 float hdrHeadroom = exifHdrHeadroom;
552 float xmpHdrHeadroom = 0.f;
553 if (get_attr_float(dom, node, hdrGainMapPrefix, "HDRGainMapHeadroom", &xmpHdrHeadroom)) {
554 hdrHeadroom = xmpHdrHeadroom;
555 }
556
557 // This node will often have StoredFormat and NativeFormat children that have inner text that
558 // specifies the integer 'L008' (also known as kCVPixelFormatType_OneComponent8).
559 info->fGainmapRatioMin = {1.f, 1.f, 1.f, 1.f};
560 info->fGainmapRatioMax = {hdrHeadroom, hdrHeadroom, hdrHeadroom, 1.f};
561 info->fGainmapGamma = {1.f, 1.f, 1.f, 1.f};
562 info->fEpsilonSdr = {0.f, 0.f, 0.f, 1.f};
563 info->fEpsilonHdr = {0.f, 0.f, 0.f, 1.f};
564 info->fDisplayRatioSdr = 1.f;
565 info->fDisplayRatioHdr = hdrHeadroom;
568 return true;
569}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213

◆ parseDom()

bool SkXmpImpl::parseDom ( sk_sp< SkData xmpData,
bool  extended 
)

Definition at line 639 of file SkXmp.cpp.

639 {
640 SkDOM* dom = extended ? &fExtendedDOM : &fStandardDOM;
641 auto xmpdStream = SkMemoryStream::Make(std::move(xmpData));
642 if (!dom->build(*xmpdStream)) {
643 SkCodecPrintf("Failed to parse XMP %s metadata.\n", extended ? "extended" : "standard");
644 return false;
645 }
646 return true;
647}
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
Definition: SkStream.cpp:314

The documentation for this class was generated from the following file: