49 auto write_scalar_attr = [&
s](
const char* attrib,
SkScalar value) {
53 s.writeScalarAsText(
value);
59 auto maybe_write_scalar_attr = [&write_scalar_attr](
const char* attrib,
SkColor4f value) {
63 write_scalar_attr(attrib,
value.fR);
68 auto maybe_write_float3_attr = [&
s](
const char* attrib,
SkColor4f value) {
75 s.writeText(
" <rdf:Seq>\n");
76 s.writeText(
" <rdf:li>");
77 s.writeScalarAsText(
value.fR);
78 s.writeText(
"</rdf:li>\n");
79 s.writeText(
" <rdf:li>");
80 s.writeScalarAsText(
value.fG);
81 s.writeText(
"</rdf:li>\n");
82 s.writeText(
" <rdf:li>");
83 s.writeScalarAsText(
value.fB);
84 s.writeText(
"</rdf:li>\n");
85 s.writeText(
" </rdf:Seq>\n");
92 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"XMP Core 5.5.0\">\n"
93 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
94 " <rdf:Description rdf:about=\"\"\n"
95 " xmlns:hdrgm=\"http://ns.adobe.com/hdr-gain-map/1.0/\"\n"
96 " hdrgm:Version=\"1.0\"\n");
97 maybe_write_scalar_attr(
"hdrgm:GainMapMin", gainMapMin);
98 maybe_write_scalar_attr(
"hdrgm:GainMapMax", gainMapMax);
99 maybe_write_scalar_attr(
"hdrgm:Gamma", gamma);
100 maybe_write_scalar_attr(
"hdrgm:OffsetSDR", gainmapInfo.
fEpsilonSdr);
101 maybe_write_scalar_attr(
"hdrgm:OffsetHDR", gainmapInfo.
fEpsilonHdr);
106 s.writeText(
" hdrgm:BaseRenditionIsHDR=\"False\">\n");
109 s.writeText(
" hdrgm:BaseRenditionIsHDR=\"True\">\n");
115 maybe_write_float3_attr(
"hdrgm:GainMapMin", gainMapMin);
116 maybe_write_float3_attr(
"hdrgm:GainMapMax", gainMapMax);
117 maybe_write_float3_attr(
"hdrgm:Gamma", gamma);
118 maybe_write_float3_attr(
"hdrgm:OffsetSDR", gainmapInfo.
fEpsilonSdr);
119 maybe_write_float3_attr(
"hdrgm:OffsetHDR", gainmapInfo.
fEpsilonHdr);
121 " </rdf:Description>\n"
124 return s.detachAsData();
131 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 5.1.2\">\n"
132 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
133 " <rdf:Description\n"
134 " xmlns:Container=\"http://ns.google.com/photos/1.0/container/\"\n"
135 " xmlns:Item=\"http://ns.google.com/photos/1.0/container/item/\"\n"
136 " xmlns:hdrgm=\"http://ns.adobe.com/hdr-gain-map/1.0/\"\n"
137 " hdrgm:Version=\"1.0\">\n"
138 " <Container:Directory>\n"
140 " <rdf:li rdf:parseType=\"Resource\">\n"
142 " Item:Semantic=\"Primary\"\n"
143 " Item:Mime=\"image/jpeg\"/>\n"
145 " <rdf:li rdf:parseType=\"Resource\">\n"
147 " Item:Semantic=\"GainMap\"\n"
148 " Item:Mime=\"image/jpeg\"\n"
150 s.writeDecAsText(gainmapItemLength);
155 " </Container:Directory>\n"
156 " </rdf:Description>\n"
159 return s.detachAsData();
184 constexpr uint16_t kIndexIfdNumberOfTags = 1;
188 constexpr uint32_t kSubIfdCount = 1;
189 constexpr uint32_t kSubIfdOffset = 26;
195 constexpr uint32_t kIndexIfdNextIfdOffset = 0;
201 constexpr uint16_t kSubIfdNumberOfTags = 1;
206 constexpr uint8_t kVersion[
kVersionCount] = {
'0',
'2',
'3',
'2'};
210 s.write(kVersion,
sizeof(kVersion));
212 constexpr uint32_t kSubIfdNextIfdOffset = 0;
216 return s.detachAsData();
220 size_t imageNumber) {
222 auto segmentParameters = mpParams.
serialize(
static_cast<uint32_t
>(imageNumber));
226 s.write8(mpParameterLength / 256);
227 s.write8(mpParameterLength % 256);
228 s.write(segmentParameters->data(), segmentParameters->size());
229 return s.detachAsData();
236 return s.detachAsData();
256 metadataSegments.emplace_back(
kExifMarker, exif_params);
261 if (includeUltraHDRv1) {
277 gainmapData =
encode_to_data(gainmap, gainmapOptions, metadataSegments);
290 metadataSegments.emplace_back(
kExifMarker, exif_params);
295 if (includeUltraHDRv1) {
309 metadataSegments.emplace_back(
344 for (
size_t segmentIndex = 0; segmentIndex < segments.size() - 1; ++segmentIndex) {
345 const auto& segment = segments[segmentIndex];
355 return segments[segmentIndex + 1].offset;
359 return segments.back().offset;
363 if (imageCount < 1) {
368 std::vector<size_t> mpSegmentOffsets(imageCount);
372 size_t cumulativeSize = 0;
373 for (
size_t i = 0;
i < imageCount; ++
i) {
376 if (!mpSegmentOffsets[
i]) {
385 cumulativeSize, mpSegmentOffsets[0]);
386 mpParams.
images[
i].size =
static_cast<uint32_t
>(imageSize);
387 cumulativeSize += imageSize;
391 for (
size_t i = 0;
i < imageCount; ++
i) {
393 if (!
dst->write(
images[
i]->bytes(), mpSegmentOffsets[
i])) {
400 if (!
dst->write(mpfSegment->data(), mpfSegment->size())) {
406 if (!
dst->write(
images[
i]->bytes() + mpSegmentOffsets[
i],
407 images[
i]->size() - mpSegmentOffsets[
i])) {
#define SkCodecPrintf(...)
static constexpr uint32_t kExifMarker
static constexpr uint32_t kMpfMarker
static constexpr uint8_t kJpegMarkerStartOfScan
static constexpr uint32_t kISOGainmapMarker
static constexpr size_t kJpegSegmentParameterLengthSize
static constexpr uint8_t kISOGainmapSig[]
constexpr uint8_t kExifSig[]
static sk_sp< SkData > get_base_image_xmp_metadata(size_t gainmapItemLength)
sk_sp< SkData > get_gainmap_image_xmp_metadata(const SkGainmapInfo &gainmapInfo)
static bool is_single_channel(SkColor4f c)
static sk_sp< SkData > get_exif_params()
static sk_sp< SkData > encode_to_data(const SkPixmap &pm, const SkJpegEncoder::Options &options, const SkJpegMetadataEncoder::SegmentList &metadataSegments)
static size_t mp_segment_offset(const SkData *image)
static sk_sp< SkData > get_iso_gainmap_segment_params(sk_sp< SkData > data)
static sk_sp< SkData > get_mpf_segment(const SkJpegMultiPictureParameters &mpParams, size_t imageNumber)
constexpr uint16_t kVersionTag
constexpr uint32_t kVersionCount
bool SkWStreamWriteU32BE(SkWStream *s, uint32_t value)
bool SkWStreamWriteU16BE(SkWStream *s, uint16_t value)
sk_sp< SkData > detachAsData()
static std::unique_ptr< SkEncoder > MakeRGB(SkWStream *dst, const SkPixmap &src, const SkJpegEncoder::Options &options, const SkJpegMetadataEncoder::SegmentList &metadata)
static bool EncodeHDRGM(SkWStream *dst, const SkPixmap &base, const SkJpegEncoder::Options &baseOptions, const SkPixmap &gainmap, const SkJpegEncoder::Options &gainmapOptions, const SkGainmapInfo &gainmapInfo)
static bool MakeMPF(SkWStream *dst, const SkData **images, size_t imageCount)
const std::vector< SkJpegSegment > & getSegments() const
static sk_sp< SkData > GetParameters(const SkData *scannedData, const SkJpegSegment &segment)
void onBytes(const void *data, size_t size)
const EmbeddedViewParams * params
std::array< MockImage, 3 > images
constexpr uint16_t kSubIFDOffsetTag
sk_sp< const SkImage > image
constexpr uint8_t kEndianBig[kEndianSize]
constexpr uint16_t kTypeUnsignedLong
constexpr uint16_t kTypeUndefined
const myers::Point & get(const myers::Segment &)
SkColor4f fGainmapRatioMax
bool isUltraHDRv1Compatible() const
sk_sp< SkData > serialize() const
sk_sp< SkColorSpace > fGainmapMathColorSpace
SkColor4f fGainmapRatioMin
BaseImageType fBaseImageType
static sk_sp< SkData > SerializeVersion()
static uint32_t GetImageDataOffset(size_t imageAbsoluteOffset, size_t mpSegmentOffset)
sk_sp< SkData > serialize(uint32_t individualImageNumber) const
std::vector< Image > images
std::shared_ptr< const fml::Mapping > data