Flutter Engine
The Flutter Engine
SkGainmapInfo.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2024 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
11#include "include/core/SkData.h"
14#include "src/base/SkEndian.h"
17
18#include <cmath>
19#include <cstdint>
20#include <memory>
21
22namespace {
23constexpr uint8_t kIsMultiChannelMask = (1u << 7);
24constexpr uint8_t kUseBaseColourSpaceMask = (1u << 6);
25} // namespace
26
28 // TODO(b/338342146): Select denominator to get maximum precision and robustness.
29 uint32_t denominator = 0x10000000;
30 if (std::abs(x) > 1.f) {
31 denominator = 0x1000;
32 }
33 int32_t numerator = static_cast<int32_t>(std::llround(static_cast<double>(x) * denominator));
34 SkWStreamWriteS32BE(&s, numerator);
35 SkWStreamWriteU32BE(&s, denominator);
36}
37
39 // TODO(b/338342146): Select denominator to get maximum precision and robustness.
40 uint32_t denominator = 0x10000000;
41 if (x > 1.f) {
42 denominator = 0x1000;
43 }
44 uint32_t numerator = static_cast<uint32_t>(std::llround(static_cast<double>(x) * denominator));
45 SkWStreamWriteU32BE(&s, numerator);
46 SkWStreamWriteU32BE(&s, denominator);
47}
48
49static bool read_u16_be(SkStream* s, uint16_t* value) {
50 if (!s->readU16(value)) {
51 return false;
52 }
54 return true;
55}
56
57static bool read_u32_be(SkStream* s, uint32_t* value) {
58 if (!s->readU32(value)) {
59 return false;
60 }
62 return true;
63}
64
65static bool read_s32_be(SkStream* s, int32_t* value) {
66 if (!s->readS32(value)) {
67 return false;
68 }
70 return true;
71}
72
73static bool read_rational_be(SkStream* s, float* value) {
74 int32_t numerator = 0;
75 uint32_t denominator = 0;
76 if (!read_s32_be(s, &numerator)) {
77 return false;
78 }
79 if (!read_u32_be(s, &denominator)) {
80 return false;
81 }
82 *value = static_cast<float>(static_cast<double>(numerator) / static_cast<double>(denominator));
83 return true;
84}
85
87 uint32_t numerator = 0;
88 uint32_t denominator = 0;
89 if (!read_u32_be(s, &numerator)) {
90 return false;
91 }
92 if (!read_u32_be(s, &denominator)) {
93 return false;
94 }
95 *value = static_cast<float>(static_cast<double>(numerator) / static_cast<double>(denominator));
96 return true;
97}
98
100 // Ensure minimum version is 0.
101 uint16_t minimum_version = 0;
102 if (!read_u16_be(s, &minimum_version)) {
103 SkCodecPrintf("Failed to read ISO 21496-1 minimum version.\n");
104 return false;
105 }
106 if (minimum_version != 0) {
107 SkCodecPrintf("Unsupported ISO 21496-1 minimum version.\n");
108 return false;
109 }
110
111 // Ensure writer version is present. No value is invalid.
112 uint16_t writer_version = 0;
113 if (!read_u16_be(s, &writer_version)) {
114 SkCodecPrintf("Failed to read ISO 21496-1 version.\n");
115 return false;
116 }
117
118 return true;
119}
120
123 SkCodecPrintf("Failed to read ISO 21496-1 version.\n");
124 return false;
125 }
126
127 uint8_t flags = 0;
128 if (!s->readU8(&flags)) {
129 SkCodecPrintf("Failed to read ISO 21496-1 flags.\n");
130 return false;
131 }
132 bool isMultiChannel = (flags & kIsMultiChannelMask) != 0;
133 bool useBaseColourSpace = (flags & kUseBaseColourSpaceMask) != 0;
134
135 float baseHdrHeadroom = 0.f;
136 if (!read_positive_rational_be(s, &baseHdrHeadroom)) {
137 SkCodecPrintf("Failed to read ISO 21496-1 base HDR headroom.\n");
138 return false;
139 }
140 float altrHdrHeadroom = 0.f;
141 if (!read_positive_rational_be(s, &altrHdrHeadroom)) {
142 SkCodecPrintf("Failed to read ISO 21496-1 altr HDR headroom.\n");
143 return false;
144 }
145
146 float gainMapMin[3] = {0.f};
147 float gainMapMax[3] = {0.f};
148 float gamma[3] = {0.f};
149 float baseOffset[3] = {0.f};
150 float altrOffset[3] = {0.f};
151
152 int channelCount = isMultiChannel ? 3 : 1;
153 for (int i = 0; i < channelCount; ++i) {
154 if (!read_rational_be(s, gainMapMin + i)) {
155 SkCodecPrintf("Failed to read ISO 21496-1 gainmap minimum.\n");
156 return false;
157 }
158 if (!read_rational_be(s, gainMapMax + i)) {
159 SkCodecPrintf("Failed to read ISO 21496-1 gainmap maximum.\n");
160 return false;
161 }
162 if (!read_positive_rational_be(s, gamma + i)) {
163 SkCodecPrintf("Failed to read ISO 21496-1 gamma.\n");
164 return false;
165 }
166 if (!read_rational_be(s, baseOffset + i)) {
167 SkCodecPrintf("Failed to read ISO 21496-1 base offset.\n");
168 return false;
169 }
170 if (!read_rational_be(s, altrOffset + i)) {
171 SkCodecPrintf("Failed to read ISO 21496-1 altr offset.\n");
172 return false;
173 }
174 }
175
177 if (!useBaseColourSpace) {
178 info.fGainmapMathColorSpace = SkColorSpace::MakeSRGB();
179 }
180 if (baseHdrHeadroom < altrHdrHeadroom) {
182 info.fDisplayRatioSdr = std::exp2(baseHdrHeadroom);
183 info.fDisplayRatioHdr = std::exp2(altrHdrHeadroom);
184 } else {
186 info.fDisplayRatioHdr = std::exp2(baseHdrHeadroom);
187 info.fDisplayRatioSdr = std::exp2(altrHdrHeadroom);
188 }
189 for (int i = 0; i < 3; ++i) {
190 int j = i >= channelCount ? 0 : i;
191 info.fGainmapRatioMin[i] = std::exp2(gainMapMin[j]);
192 info.fGainmapRatioMax[i] = std::exp2(gainMapMax[j]);
193 info.fGainmapGamma[i] = 1.f / gamma[j];
194 switch (info.fBaseImageType) {
196 info.fEpsilonSdr[i] = baseOffset[j];
197 info.fEpsilonHdr[i] = altrOffset[j];
198 break;
200 info.fEpsilonHdr[i] = baseOffset[j];
201 info.fEpsilonSdr[i] = altrOffset[j];
202 break;
203 }
204 }
205 return true;
206}
207
209 // UltraHDR v1 supports having the base image be HDR in theory, but it is largely
210 // untested.
212 return false;
213 }
214 // UltraHDR v1 doesn't support a non-base gainmap math color space.
216 return false;
217 }
218 return true;
219}
220
222 if (!data) {
223 return false;
224 }
225 auto s = SkMemoryStream::MakeDirect(data->data(), data->size());
226 return read_iso_gainmap_version(s.get());
227}
228
230 if (!data) {
231 return false;
232 }
233 auto s = SkMemoryStream::MakeDirect(data->data(), data->size());
234 return read_iso_gainmap_info(s.get(), info);
235}
236
239 SkWStreamWriteU16BE(&s, 0); // Minimum reader version
240 SkWStreamWriteU16BE(&s, 0); // Writer version
241 return s.detachAsData();
242}
243
244static bool is_single_channel(SkColor4f c) { return c.fR == c.fG && c.fG == c.fB; };
245
248 // Version.
249 SkWStreamWriteU16BE(&s, 0); // Minimum reader version
250 SkWStreamWriteU16BE(&s, 0); // Writer version
251
252 // Flags.
253 bool all_single_channel = is_single_channel(fGainmapRatioMin) &&
257 uint8_t flags = 0;
259 flags |= kUseBaseColourSpaceMask;
260 }
261 if (!all_single_channel) {
262 flags |= kIsMultiChannelMask;
263 }
264 s.write8(flags);
265
266 // Base and altr headroom.
267 switch (fBaseImageType) {
271 break;
275 break;
276 }
277
278 // Per-channel information.
279 for (int i = 0; i < (all_single_channel ? 1 : 3); ++i) {
283 switch (fBaseImageType) {
287 break;
291 break;
292 }
293 }
294 return s.detachAsData();
295}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SkCodecPrintf(...)
Definition: SkCodecPriv.h:23
#define SkEndian_SwapBE32(n)
Definition: SkEndian.h:136
#define SkEndian_SwapBE16(n)
Definition: SkEndian.h:135
static bool read_u32_be(SkStream *s, uint32_t *value)
static bool read_rational_be(SkStream *s, float *value)
static bool is_single_channel(SkColor4f c)
static void write_positive_rational_be(SkDynamicMemoryWStream &s, float x)
static bool read_u16_be(SkStream *s, uint16_t *value)
static bool read_positive_rational_be(SkStream *s, float *value)
static bool read_iso_gainmap_info(SkStream *s, SkGainmapInfo &info)
static bool read_iso_gainmap_version(SkStream *s)
static bool read_s32_be(SkStream *s, int32_t *value)
static void write_rational_be(SkDynamicMemoryWStream &s, float x)
bool SkWStreamWriteU32BE(SkWStream *s, uint32_t value)
Definition: SkStreamPriv.h:54
bool SkWStreamWriteS32BE(SkWStream *s, int32_t value)
Definition: SkStreamPriv.h:59
bool SkWStreamWriteU16BE(SkWStream *s, uint16_t value)
Definition: SkStreamPriv.h:49
static sk_sp< SkColorSpace > MakeSRGB()
Definition: SkData.h:25
static std::unique_ptr< SkMemoryStream > MakeDirect(const void *data, size_t length)
Definition: SkStream.cpp:310
struct MyStruct s
FlutterSemanticsFlag flags
uint8_t value
double x
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707
SkColor4f fGainmapRatioMax
Definition: SkGainmapInfo.h:49
SkColor4f fEpsilonSdr
Definition: SkGainmapInfo.h:55
bool isUltraHDRv1Compatible() const
sk_sp< SkData > serialize() const
SkColor4f fGainmapGamma
Definition: SkGainmapInfo.h:50
static bool ParseVersion(const SkData *data)
sk_sp< SkColorSpace > fGainmapMathColorSpace
Definition: SkGainmapInfo.h:95
SkColor4f fGainmapRatioMin
Definition: SkGainmapInfo.h:48
BaseImageType fBaseImageType
Definition: SkGainmapInfo.h:75
float fDisplayRatioSdr
Definition: SkGainmapInfo.h:65
static bool Parse(const SkData *data, SkGainmapInfo &info)
SkColor4f fEpsilonHdr
Definition: SkGainmapInfo.h:56
float fDisplayRatioHdr
Definition: SkGainmapInfo.h:66
static sk_sp< SkData > SerializeVersion()
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63