Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Functions
SkJpegGainmapEncoder.cpp File Reference
#include "include/private/SkJpegGainmapEncoder.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkStream.h"
#include "include/encode/SkEncoder.h"
#include "include/encode/SkJpegEncoder.h"
#include "include/private/SkGainmapInfo.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkJpegConstants.h"
#include "src/codec/SkJpegMultiPicture.h"
#include "src/codec/SkJpegPriv.h"
#include "src/codec/SkJpegSegmentScan.h"
#include <vector>

Go to the source code of this file.

Functions

static bool is_single_channel (SkColor4f c)
 
sk_sp< SkDataget_hdrgm_xmp_data (const SkGainmapInfo &gainmapInfo)
 
static sk_sp< SkDataget_gcontainer_xmp_data (size_t gainmapItemLength)
 
std::vector< sk_sp< SkData > > get_hdrgm_image_segments (sk_sp< SkData > image, size_t segmentMaxDataSize)
 
static sk_sp< SkDataencode_to_data (const SkPixmap &pm, const SkJpegEncoder::Options &options, SkData *xmpMetadata)
 
static sk_sp< SkDataget_mpf_segment (const SkJpegMultiPictureParameters &mpParams)
 

Function Documentation

◆ encode_to_data()

static sk_sp< SkData > encode_to_data ( const SkPixmap pm,
const SkJpegEncoder::Options options,
SkData xmpMetadata 
)
static

Definition at line 222 of file SkJpegGainmapEncoder.cpp.

224 {
225 SkJpegEncoder::Options optionsWithXmp = options;
226 optionsWithXmp.xmpMetadata = xmpMetadata;
227 SkDynamicMemoryWStream encodeStream;
228 auto encoder = SkJpegEncoder::Make(&encodeStream, pm, optionsWithXmp);
229 if (!encoder || !encoder->encodeRows(pm.height())) {
230 return nullptr;
231 }
232 return encodeStream.detachAsData();
233}
const char * options
sk_sp< SkData > detachAsData()
Definition SkStream.cpp:707
int height() const
Definition SkPixmap.h:166
SK_API std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap &src, const Options &options)
const SkData * xmpMetadata

◆ get_gcontainer_xmp_data()

static sk_sp< SkData > get_gcontainer_xmp_data ( size_t  gainmapItemLength)
static

Definition at line 125 of file SkJpegGainmapEncoder.cpp.

125 {
127 s.writeText(
128 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 5.1.2\">\n"
129 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
130 " <rdf:Description\n"
131 " xmlns:Container=\"http://ns.google.com/photos/1.0/container/\"\n"
132 " xmlns:Item=\"http://ns.google.com/photos/1.0/container/item/\"\n"
133 " xmlns:hdrgm=\"http://ns.adobe.com/hdr-gain-map/1.0/\"\n"
134 " hdrgm:Version=\"1.0\">\n"
135 " <Container:Directory>\n"
136 " <rdf:Seq>\n"
137 " <rdf:li rdf:parseType=\"Resource\">\n"
138 " <Container:Item\n"
139 " Item:Semantic=\"Primary\"\n"
140 " Item:Mime=\"image/jpeg\"/>\n"
141 " </rdf:li>\n"
142 " <rdf:li rdf:parseType=\"Resource\">\n"
143 " <Container:Item\n"
144 " Item:Semantic=\"GainMap\"\n"
145 " Item:Mime=\"image/jpeg\"\n"
146 " Item:Length=\"");
147 s.writeDecAsText(gainmapItemLength);
148 s.writeText(
149 "\"/>\n"
150 " </rdf:li>\n"
151 " </rdf:Seq>\n"
152 " </Container:Directory>\n"
153 " </rdf:Description>\n"
154 " </rdf:RDF>\n"
155 "</x:xmpmeta>\n");
156 return s.detachAsData();
157}
struct MyStruct s

◆ get_hdrgm_image_segments()

std::vector< sk_sp< SkData > > get_hdrgm_image_segments ( sk_sp< SkData image,
size_t  segmentMaxDataSize 
)

Definition at line 160 of file SkJpegGainmapEncoder.cpp.

161 {
162 // Compute the total size of the header to a gainmap image segment (not including the 2 bytes
163 // for the segment size, which the encoder is responsible for writing).
164 constexpr size_t kGainmapHeaderSize = sizeof(kGainmapSig) + 2 * kGainmapMarkerIndexSize;
165
166 // Compute the payload size for each segment.
167 const size_t kGainmapPayloadSize = segmentMaxDataSize - kGainmapHeaderSize;
168
169 // Compute the number of segments we'll need.
170 const size_t segmentCount = (image->size() + kGainmapPayloadSize - 1) / kGainmapPayloadSize;
171 std::vector<sk_sp<SkData>> result;
172 result.reserve(segmentCount);
173
174 // Move |imageData| through |image| until it hits |imageDataEnd|.
175 const uint8_t* imageData = image->bytes();
176 const uint8_t* imageDataEnd = image->bytes() + image->size();
177 while (imageData < imageDataEnd) {
178 SkDynamicMemoryWStream segmentStream;
179
180 // Write the signature.
181 segmentStream.write(kGainmapSig, sizeof(kGainmapSig));
182
183 // Write the segment index as big-endian.
184 size_t segmentIndex = result.size() + 1;
185 uint8_t segmentIndexBytes[2] = {
186 static_cast<uint8_t>(segmentIndex / 256u),
187 static_cast<uint8_t>(segmentIndex % 256u),
188 };
189 segmentStream.write(segmentIndexBytes, sizeof(segmentIndexBytes));
190
191 // Write the segment count as big-endian.
192 uint8_t segmentCountBytes[2] = {
193 static_cast<uint8_t>(segmentCount / 256u),
194 static_cast<uint8_t>(segmentCount % 256u),
195 };
196 segmentStream.write(segmentCountBytes, sizeof(segmentCountBytes));
197
198 // Verify that our header size math is correct.
199 SkASSERT(segmentStream.bytesWritten() == kGainmapHeaderSize);
200
201 // Write the rest of the segment.
202 size_t bytesToWrite =
203 std::min(imageDataEnd - imageData, static_cast<intptr_t>(kGainmapPayloadSize));
204 segmentStream.write(imageData, bytesToWrite);
205 imageData += bytesToWrite;
206
207 // Verify that our data size math is correct.
208 if (segmentIndex == segmentCount) {
209 SkASSERT(segmentStream.bytesWritten() <= segmentMaxDataSize);
210 } else {
211 SkASSERT(segmentStream.bytesWritten() == segmentMaxDataSize);
212 }
213 result.push_back(segmentStream.detachAsData());
214 }
215
216 // Verify that our segment count math was correct.
217 SkASSERT(imageData == imageDataEnd);
218 SkASSERT(result.size() == segmentCount);
219 return result;
220}
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr uint32_t kGainmapMarkerIndexSize
static constexpr uint8_t kGainmapSig[]
size_t bytesWritten() const override
Definition SkStream.cpp:526
bool write(const void *buffer, size_t size) override
Definition SkStream.cpp:535
sk_sp< SkImage > image
Definition examples.cpp:29
GAsyncResult * result

◆ get_hdrgm_xmp_data()

sk_sp< SkData > get_hdrgm_xmp_data ( const SkGainmapInfo gainmapInfo)

Definition at line 30 of file SkJpegGainmapEncoder.cpp.

30 {
32 const float kLog2 = std::log(2.f);
33 const SkColor4f gainMapMin = {std::log(gainmapInfo.fGainmapRatioMin.fR) / kLog2,
34 std::log(gainmapInfo.fGainmapRatioMin.fG) / kLog2,
35 std::log(gainmapInfo.fGainmapRatioMin.fB) / kLog2,
36 1.f};
37 const SkColor4f gainMapMax = {std::log(gainmapInfo.fGainmapRatioMax.fR) / kLog2,
38 std::log(gainmapInfo.fGainmapRatioMax.fG) / kLog2,
39 std::log(gainmapInfo.fGainmapRatioMax.fB) / kLog2,
40 1.f};
41 const SkColor4f gamma = {1.f / gainmapInfo.fGainmapGamma.fR,
42 1.f / gainmapInfo.fGainmapGamma.fG,
43 1.f / gainmapInfo.fGainmapGamma.fB,
44 1.f};
45 // Write a scalar attribute.
46 auto write_scalar_attr = [&s](const char* attrib, SkScalar value) {
47 s.writeText(" ");
48 s.writeText(attrib);
49 s.writeText("=\"");
50 s.writeScalarAsText(value);
51 s.writeText("\"\n");
52 };
53
54 // Write a scalar attribute only if all channels of |value| are equal (otherwise, write
55 // nothing).
56 auto maybe_write_scalar_attr = [&write_scalar_attr](const char* attrib, SkColor4f value) {
57 if (!is_single_channel(value)) {
58 return;
59 }
60 write_scalar_attr(attrib, value.fR);
61 };
62
63 // Write a float3 attribute as a list ony if not all channels of |value| are equal (otherwise,
64 // write nothing).
65 auto maybe_write_float3_attr = [&s](const char* attrib, SkColor4f value) {
66 if (is_single_channel(value)) {
67 return;
68 }
69 s.writeText(" <");
70 s.writeText(attrib);
71 s.writeText(">\n");
72 s.writeText(" <rdf:Seq>\n");
73 s.writeText(" <rdf:li>");
74 s.writeScalarAsText(value.fR);
75 s.writeText("</rdf:li>\n");
76 s.writeText(" <rdf:li>");
77 s.writeScalarAsText(value.fG);
78 s.writeText("</rdf:li>\n");
79 s.writeText(" <rdf:li>");
80 s.writeScalarAsText(value.fB);
81 s.writeText("</rdf:li>\n");
82 s.writeText(" </rdf:Seq>\n");
83 s.writeText(" </");
84 s.writeText(attrib);
85 s.writeText(">\n");
86 };
87
88 s.writeText(
89 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"XMP Core 5.5.0\">\n"
90 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
91 " <rdf:Description rdf:about=\"\"\n"
92 " xmlns:hdrgm=\"http://ns.adobe.com/hdr-gain-map/1.0/\"\n"
93 " hdrgm:Version=\"1.0\"\n");
94 maybe_write_scalar_attr("hdrgm:GainMapMin", gainMapMin);
95 maybe_write_scalar_attr("hdrgm:GainMapMax", gainMapMax);
96 maybe_write_scalar_attr("hdrgm:Gamma", gamma);
97 maybe_write_scalar_attr("hdrgm:OffsetSDR", gainmapInfo.fEpsilonSdr);
98 maybe_write_scalar_attr("hdrgm:OffsetHDR", gainmapInfo.fEpsilonHdr);
99 write_scalar_attr("hdrgm:HDRCapacityMin", std::log(gainmapInfo.fDisplayRatioSdr) / kLog2);
100 write_scalar_attr("hdrgm:HDRCapacityMax", std::log(gainmapInfo.fDisplayRatioHdr) / kLog2);
101 switch (gainmapInfo.fBaseImageType) {
103 s.writeText(" hdrgm:BaseRenditionIsHDR=\"False\">\n");
104 break;
106 s.writeText(" hdrgm:BaseRenditionIsHDR=\"True\">\n");
107 break;
108 }
109
110 // Write any of the vector parameters that cannot be represented as scalars (and thus cannot
111 // be written inline as above).
112 maybe_write_float3_attr("hdrgm:GainMapMin", gainMapMin);
113 maybe_write_float3_attr("hdrgm:GainMapMax", gainMapMax);
114 maybe_write_float3_attr("hdrgm:Gamma", gamma);
115 maybe_write_float3_attr("hdrgm:OffsetSDR", gainmapInfo.fEpsilonSdr);
116 maybe_write_float3_attr("hdrgm:OffsetHDR", gainmapInfo.fEpsilonHdr);
117 s.writeText(
118 " </rdf:Description>\n"
119 " </rdf:RDF>\n"
120 "</x:xmpmeta>");
121 return s.detachAsData();
122}
static bool is_single_channel(SkColor4f c)
float SkScalar
Definition extension.cpp:12
uint8_t value
SkColor4f fGainmapRatioMax
SkColor4f fEpsilonSdr
SkColor4f fGainmapGamma
SkColor4f fGainmapRatioMin
BaseImageType fBaseImageType
float fDisplayRatioSdr
SkColor4f fEpsilonHdr
float fDisplayRatioHdr

◆ get_mpf_segment()

static sk_sp< SkData > get_mpf_segment ( const SkJpegMultiPictureParameters mpParams)
static

Definition at line 235 of file SkJpegGainmapEncoder.cpp.

235 {
237 auto segmentParameters = mpParams.serialize();
238 const size_t mpParameterLength = kJpegSegmentParameterLengthSize + segmentParameters->size();
239 s.write8(0xFF);
240 s.write8(kMpfMarker);
241 s.write8(mpParameterLength / 256);
242 s.write8(mpParameterLength % 256);
243 s.write(segmentParameters->data(), segmentParameters->size());
244 return s.detachAsData();
245}
static constexpr uint32_t kMpfMarker
static constexpr size_t kJpegSegmentParameterLengthSize
size_t size() const
Definition SkData.h:30
sk_sp< SkData > serialize() const

◆ is_single_channel()

static bool is_single_channel ( SkColor4f  c)
static

Definition at line 24 of file SkJpegGainmapEncoder.cpp.

24{ return c.fR == c.fG && c.fG == c.fB; };