Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkHeifCodec.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
8
15#include "src/base/SkEndian.h"
17
18#define FOURCC(c1, c2, c3, c4) \
19 ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4))
20
21bool SkHeifCodec::IsSupported(const void* buffer, size_t bytesRead,
23 // Parse the ftyp box up to bytesRead to determine if this is HEIF or AVIF.
24 // Any valid ftyp box should have at least 8 bytes.
25 if (bytesRead < 8) {
26 return false;
27 }
28
29 const uint32_t* ptr = (const uint32_t*)buffer;
30 uint64_t chunkSize = SkEndian_SwapBE32(ptr[0]);
31 uint32_t chunkType = SkEndian_SwapBE32(ptr[1]);
32
33 if (chunkType != FOURCC('f', 't', 'y', 'p')) {
34 return false;
35 }
36
37 int64_t offset = 8;
38 if (chunkSize == 1) {
39 // This indicates that the next 8 bytes represent the chunk size,
40 // and chunk data comes after that.
41 if (bytesRead < 16) {
42 return false;
43 }
44 auto* chunkSizePtr = SkTAddOffset<const uint64_t>(buffer, offset);
45 chunkSize = SkEndian_SwapBE64(*chunkSizePtr);
46 if (chunkSize < 16) {
47 // The smallest valid chunk is 16 bytes long in this case.
48 return false;
49 }
50 offset += 8;
51 } else if (chunkSize < 8) {
52 // The smallest valid chunk is 8 bytes long.
53 return false;
54 }
55
56 if (chunkSize > bytesRead) {
57 chunkSize = bytesRead;
58 }
59 int64_t chunkDataSize = chunkSize - offset;
60 // It should at least have major brand (4-byte) and minor version (4-bytes).
61 // The rest of the chunk (if any) is a list of (4-byte) compatible brands.
62 if (chunkDataSize < 8) {
63 return false;
64 }
65
66 uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
67 bool isHeif = false;
68 for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
69 if (i == 1) {
70 // Skip this index, it refers to the minorVersion,
71 // not a brand.
72 continue;
73 }
74 auto* brandPtr = SkTAddOffset<const uint32_t>(buffer, offset + 4 * i);
75 uint32_t brand = SkEndian_SwapBE32(*brandPtr);
76 if (brand == FOURCC('m', 'i', 'f', '1') || brand == FOURCC('h', 'e', 'i', 'c')
77 || brand == FOURCC('m', 's', 'f', '1') || brand == FOURCC('h', 'e', 'v', 'c')
78 || brand == FOURCC('a', 'v', 'i', 'f') || brand == FOURCC('a', 'v', 'i', 's')) {
79 // AVIF files could have "mif1" as the major brand. So we cannot
80 // distinguish whether the image is AVIF or HEIC just based on the
81 // "mif1" brand. So wait until we see a specific avif brand to
82 // determine whether it is AVIF or HEIC.
83 isHeif = true;
84 if (brand == FOURCC('a', 'v', 'i', 'f')
85 || brand == FOURCC('a', 'v', 'i', 's')) {
86 if (format != nullptr) {
88 }
89 return true;
90 }
91 }
92 }
93 if (isHeif) {
94 if (format != nullptr) {
96 }
97 return true;
98 }
99 return false;
100}
101
103 switch (frameInfo.mRotationAngle) {
104 case 0: return kTopLeft_SkEncodedOrigin;
105 case 90: return kRightTop_SkEncodedOrigin;
106 case 180: return kBottomRight_SkEncodedOrigin;
107 case 270: return kLeftBottom_SkEncodedOrigin;
108 }
110}
111
113 SkHeifStreamWrapper(SkStream* stream) : fStream(stream) {}
114
116
117 size_t read(void* buffer, size_t size) override {
118 return fStream->read(buffer, size);
119 }
120
121 bool rewind() override {
122 return fStream->rewind();
123 }
124
125 bool seek(size_t position) override {
126 return fStream->seek(position);
127 }
128
129 bool hasLength() const override {
130 return fStream->hasLength();
131 }
132
133 size_t getLength() const override {
134 return fStream->getLength();
135 }
136
137private:
138 std::unique_ptr<SkStream> fStream;
139};
140
141static void releaseProc(const void* ptr, void* context) {
142 delete reinterpret_cast<std::vector<uint8_t>*>(context);
143}
144
145std::unique_ptr<SkCodec> SkHeifCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
146 SkCodec::SelectionPolicy selectionPolicy, Result* result) {
148 if (!stream) {
150 return nullptr;
151 }
152 std::unique_ptr<HeifDecoder> heifDecoder(createHeifDecoder());
153 if (heifDecoder == nullptr) {
155 return nullptr;
156 }
157
158 constexpr size_t bytesToRead = MinBufferedBytesNeeded();
159 char buffer[bytesToRead];
160 size_t bytesRead = stream->peek(buffer, bytesToRead);
161 if (0 == bytesRead) {
162 // It is possible the stream does not support peeking, but does support rewinding.
163 // Attempt to read() and pass the actual amount read to the decoder.
164 bytesRead = stream->read(buffer, bytesToRead);
165 if (!stream->rewind()) {
166 SkCodecPrintf("Encoded image data could not peek or rewind to determine format!\n");
168 return nullptr;
169 }
170 }
171
173 if (!SkHeifCodec::IsSupported(buffer, bytesRead, &format)) {
174 SkCodecPrintf("Failed to get format despite earlier detecting it");
176 return nullptr;
177 }
178
179 HeifFrameInfo heifInfo;
180 if (!heifDecoder->init(new SkHeifStreamWrapper(stream.release()), &heifInfo)) {
182 return nullptr;
183 }
184
185 size_t frameCount = 1;
186 if (selectionPolicy == SkCodec::SelectionPolicy::kPreferAnimation) {
187 HeifFrameInfo sequenceInfo;
188 if (heifDecoder->getSequenceInfo(&sequenceInfo, &frameCount) &&
189 frameCount > 1) {
190 heifInfo = std::move(sequenceInfo);
191 }
192 }
193
194 std::unique_ptr<SkEncodedInfo::ICCProfile> profile = nullptr;
195 if (heifInfo.mIccData.size() > 0) {
196 auto iccData = new std::vector<uint8_t>(std::move(heifInfo.mIccData));
197 auto icc = SkData::MakeWithProc(iccData->data(), iccData->size(), releaseProc, iccData);
198 profile = SkEncodedInfo::ICCProfile::Make(std::move(icc));
199 }
200 if (profile && profile->profile()->data_color_space != skcms_Signature_RGB) {
201 // This will result in sRGB.
202 profile = nullptr;
203 }
204
205 uint8_t colorDepth = heifDecoder->getColorDepth();
206
209 /*bitsPerComponent*/ 8, std::move(profile), colorDepth);
210 SkEncodedOrigin orientation = get_orientation(heifInfo);
211
213 return std::unique_ptr<SkCodec>(new SkHeifCodec(
214 std::move(info), heifDecoder.release(), orientation, frameCount > 1, format));
215}
216
217SkHeifCodec::SkHeifCodec(
219 HeifDecoder* heifDecoder,
220 SkEncodedOrigin origin,
221 bool useAnimation,
223 : INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, nullptr, origin)
224 , fHeifDecoder(heifDecoder)
225 , fSwizzleSrcRow(nullptr)
226 , fColorXformSrcRow(nullptr)
227 , fUseAnimation(useAnimation)
228 , fFormat(format)
229{}
230
231bool SkHeifCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,
232 bool needsColorXform) {
233 SkASSERT(srcIsOpaque);
234
236 return false;
237 }
238
240 SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
241 "- it is being decoded as non-opaque, which will draw slower\n");
242 }
243
244 uint8_t colorDepth = fHeifDecoder->getColorDepth();
245 switch (dstInfo.colorType()) {
248 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
249
252 return fHeifDecoder->setOutputColor(kHeifColorFormat_BGRA_8888);
253
256 if (needsColorXform) {
257 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
258 } else {
259 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGB565);
260 }
261
264 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_1010102);
265
267 SkASSERT(needsColorXform);
268 if (srcIsOpaque && colorDepth == 10) {
270 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_1010102);
271 } else {
273 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
274 }
275
276 default:
277 return false;
278 }
279}
280
281int SkHeifCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count,
282 const Options& opts) {
283 // When fSwizzleSrcRow is non-null, it means that we need to swizzle. In this case,
284 // we will always decode into fSwizzlerSrcRow before swizzling into the next buffer.
285 // We can never swizzle "in place" because the swizzler may perform sampling and/or
286 // subsetting.
287 // When fColorXformSrcRow is non-null, it means that we need to color xform and that
288 // we cannot color xform "in place" (many times we can, but not when the dst is F16).
289 // In this case, we will color xform from fColorXformSrcRow into the dst.
290 uint8_t* decodeDst = (uint8_t*) dst;
291 uint32_t* swizzleDst = (uint32_t*) dst;
292 size_t decodeDstRowBytes = rowBytes;
293 size_t swizzleDstRowBytes = rowBytes;
294 int dstWidth = opts.fSubset ? opts.fSubset->width() : dstInfo.width();
295 if (fSwizzleSrcRow && fColorXformSrcRow) {
296 decodeDst = fSwizzleSrcRow;
297 swizzleDst = fColorXformSrcRow;
298 decodeDstRowBytes = 0;
299 swizzleDstRowBytes = 0;
300 dstWidth = fSwizzler->swizzleWidth();
301 } else if (fColorXformSrcRow) {
302 decodeDst = (uint8_t*) fColorXformSrcRow;
303 swizzleDst = fColorXformSrcRow;
304 decodeDstRowBytes = 0;
305 swizzleDstRowBytes = 0;
306 } else if (fSwizzleSrcRow) {
307 decodeDst = fSwizzleSrcRow;
308 decodeDstRowBytes = 0;
309 dstWidth = fSwizzler->swizzleWidth();
310 }
311
312 for (int y = 0; y < count; y++) {
313 if (!fHeifDecoder->getScanline(decodeDst)) {
314 return y;
315 }
316
317 if (fSwizzler) {
318 fSwizzler->swizzle(swizzleDst, decodeDst);
319 }
320
321 if (this->colorXform()) {
322 this->applyColorXform(dst, swizzleDst, dstWidth);
323 dst = SkTAddOffset<void>(dst, rowBytes);
324 }
325
326 decodeDst = SkTAddOffset<uint8_t>(decodeDst, decodeDstRowBytes);
327 swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes);
328 }
329
330 return count;
331}
332
334 if (!fUseAnimation) {
335 return 1;
336 }
337
338 if (fFrameHolder.size() == 0) {
339 size_t frameCount;
340 HeifFrameInfo frameInfo;
341 if (!fHeifDecoder->getSequenceInfo(&frameInfo, &frameCount)
342 || frameCount <= 1) {
343 fUseAnimation = false;
344 return 1;
345 }
346 fFrameHolder.reserve(frameCount);
347 for (size_t i = 0; i < frameCount; i++) {
348 Frame* frame = fFrameHolder.appendNewFrame();
349 frame->setXYWH(0, 0, frameInfo.mWidth, frameInfo.mHeight);
351 // Currently we don't know the duration until the frame is actually
352 // decoded (onGetFrameInfo is also called before frame is decoded).
353 // For now, fill it base on the value reported for the sequence.
354 frame->setDuration(frameInfo.mDurationUs / 1000);
355 frame->setRequiredFrame(SkCodec::kNoFrame);
356 frame->setHasAlpha(false);
357 }
358 }
359
360 return fFrameHolder.size();
361}
362
363const SkFrame* SkHeifCodec::FrameHolder::onGetFrame(int i) const {
364 return static_cast<const SkFrame*>(this->frame(i));
365}
366
367SkHeifCodec::Frame* SkHeifCodec::FrameHolder::appendNewFrame() {
368 const int i = this->size();
369 fFrames.emplace_back(i); // TODO: need to handle frame duration here
370 return &fFrames[i];
371}
372
373const SkHeifCodec::Frame* SkHeifCodec::FrameHolder::frame(int i) const {
374 SkASSERT(i >= 0 && i < this->size());
375 return &fFrames[i];
376}
377
378SkHeifCodec::Frame* SkHeifCodec::FrameHolder::editFrameAt(int i) {
379 SkASSERT(i >= 0 && i < this->size());
380 return &fFrames[i];
381}
382
383bool SkHeifCodec::onGetFrameInfo(int i, FrameInfo* frameInfo) const {
384 if (i >= fFrameHolder.size()) {
385 return false;
386 }
387
388 const Frame* frame = fFrameHolder.frame(i);
389 if (!frame) {
390 return false;
391 }
392
393 if (frameInfo) {
394 frame->fillIn(frameInfo, true);
395 }
396
397 return true;
398}
399
403
404/*
405 * Performs the heif decode
406 */
408 void* dst, size_t dstRowBytes,
409 const Options& options,
410 int* rowsDecoded) {
411 if (options.fSubset) {
412 // Not supporting subsets on this path for now.
413 // TODO: if the heif has tiles, we can support subset here, but
414 // need to retrieve tile config from metadata retriever first.
415 return kUnimplemented;
416 }
417
418 bool success;
419 if (fUseAnimation) {
420 success = fHeifDecoder->decodeSequence(options.fFrameIndex, &fFrameInfo);
421 fFrameHolder.editFrameAt(options.fFrameIndex)->setDuration(
422 fFrameInfo.mDurationUs / 1000);
423 } else {
424 success = fHeifDecoder->decode(&fFrameInfo);
425 }
426
427 if (!success) {
428 return kInvalidInput;
429 }
430
431 fSwizzler.reset(nullptr);
432 this->allocateStorage(dstInfo);
433
434 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height(), options);
435 if (rows < dstInfo.height()) {
436 *rowsDecoded = rows;
437 return kIncompleteInput;
438 }
439
440 return kSuccess;
441}
442
443void SkHeifCodec::allocateStorage(const SkImageInfo& dstInfo) {
444 int dstWidth = dstInfo.width();
445
446 size_t swizzleBytes = 0;
447 if (fSwizzler) {
448 swizzleBytes = fFrameInfo.mBytesPerPixel * fFrameInfo.mWidth;
449 dstWidth = fSwizzler->swizzleWidth();
450 SkASSERT(!this->colorXform() || SkIsAlign4(swizzleBytes));
451 }
452
453 size_t xformBytes = 0;
454 if (this->colorXform() && (kRGBA_F16_SkColorType == dstInfo.colorType() ||
456 xformBytes = dstWidth * sizeof(uint32_t);
457 }
458
459 size_t totalBytes = swizzleBytes + xformBytes;
460 fStorage.reset(totalBytes);
461 if (totalBytes > 0) {
462 fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr;
463 fColorXformSrcRow = (xformBytes > 0) ?
464 SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr;
465 }
466}
467
468void SkHeifCodec::initializeSwizzler(
469 const SkImageInfo& dstInfo, const Options& options) {
470 SkImageInfo swizzlerDstInfo = dstInfo;
471 switch (this->getSrcXformFormat()) {
473 swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_8888_SkColorType);
474 break;
476 swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_1010102_SkColorType);
477 break;
478 default:
479 SkASSERT(false);
480 }
481
482 int srcBPP = 4;
483 if (dstInfo.colorType() == kRGB_565_SkColorType && !this->colorXform()) {
484 srcBPP = 2;
485 }
486
487 fSwizzler = SkSwizzler::MakeSimple(srcBPP, swizzlerDstInfo, options);
488 SkASSERT(fSwizzler);
489}
490
491SkSampler* SkHeifCodec::getSampler(bool createIfNecessary) {
492 if (!createIfNecessary || fSwizzler) {
493 SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.get() == fSwizzleSrcRow));
494 return fSwizzler.get();
495 }
496
497 this->initializeSwizzler(this->dstInfo(), this->options());
498 this->allocateStorage(this->dstInfo());
499 return fSwizzler.get();
500}
501
503 fSwizzler.reset(nullptr);
504 fSwizzleSrcRow = nullptr;
505 fColorXformSrcRow = nullptr;
506 fStorage.reset();
507
508 return true;
509}
510
512 const SkImageInfo& dstInfo, const Options& options) {
513 // TODO: For now, just decode the whole thing even when there is a subset.
514 // If the heif image has tiles, we could potentially do this much faster,
515 // but the tile configuration needs to be retrieved from the metadata.
516 if (!fHeifDecoder->decode(&fFrameInfo)) {
517 return kInvalidInput;
518 }
519
520 if (options.fSubset) {
521 this->initializeSwizzler(dstInfo, options);
522 } else {
523 fSwizzler.reset(nullptr);
524 }
525
526 this->allocateStorage(dstInfo);
527
528 return kSuccess;
529}
530
531int SkHeifCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
532 return this->readRows(this->dstInfo(), dst, dstRowBytes, count, this->options());
533}
534
536 return count == (int) fHeifDecoder->skipScanlines(count);
537}
538
539namespace SkHeifDecoder {
540bool IsHeif(const void* data, size_t len) {
541 return SkHeifCodec::IsSupported(data, len, nullptr);
542}
543
544std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
545 SkCodec::Result* outResult,
546 SkCodecs::DecodeContext ctx) {
547 SkASSERT(ctx);
548 SkCodec::Result resultStorage;
549 if (!outResult) {
550 outResult = &resultStorage;
551 }
552 auto policy = static_cast<SkCodec::SelectionPolicy*>(ctx);
553 return SkHeifCodec::MakeFromStream(std::move(stream), *policy, outResult);
554}
555
556std::unique_ptr<SkCodec> Decode(sk_sp<SkData> data,
557 SkCodec::Result* outResult,
558 SkCodecs::DecodeContext ctx) {
559 if (!data) {
560 if (outResult) {
561 *outResult = SkCodec::kInvalidInput;
562 }
563 return nullptr;
564 }
565 return Decode(SkMemoryStream::Make(std::move(data)), outResult, ctx);
566}
567} // namespace SkHeifDecoder
568
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
int count
static constexpr bool SkIsAlign4(T x)
Definition SkAlign.h:20
@ kUnknown_SkAlphaType
uninitialized
Definition SkAlphaType.h:27
@ kOpaque_SkAlphaType
pixel is opaque
Definition SkAlphaType.h:28
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkCodecPrintf(...)
Definition SkCodecPriv.h:23
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition SkColorType.h:26
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition SkColorType.h:38
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition SkColorType.h:22
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
Definition SkColorType.h:27
SkEncodedImageFormat
SkEncodedOrigin
@ kBottomRight_SkEncodedOrigin
@ kTopLeft_SkEncodedOrigin
@ kLeftBottom_SkEncodedOrigin
@ kDefault_SkEncodedOrigin
@ kRightTop_SkEncodedOrigin
#define SkEndian_SwapBE32(n)
Definition SkEndian.h:136
#define SkEndian_SwapBE64(n)
Definition SkEndian.h:137
#define FOURCC(c1, c2, c3, c4)
static SkEncodedOrigin get_orientation(const HeifFrameInfo &frameInfo)
static void releaseProc(const void *ptr, void *context)
#define INHERITED(method,...)
static HeifDecoder * createHeifDecoder()
@ kHeifColorFormat_RGBA_1010102
@ kHeifColorFormat_RGB565
@ kHeifColorFormat_BGRA_8888
@ kHeifColorFormat_RGBA_8888
Type::kYUV Type::kRGBA() int(0.7 *637)
const SkImageInfo & dstInfo() const
Definition SkCodec.h:878
SkStream * stream()
Definition SkCodec.h:865
void applyColorXform(void *dst, const void *src, int count) const
Definition SkCodec.cpp:853
static constexpr size_t MinBufferedBytesNeeded()
Definition SkCodec.h:71
void setSrcXformFormat(XformFormat pixelFormat)
Definition SkCodec.cpp:263
@ kIncompleteInput
Definition SkCodec.h:84
@ kInvalidInput
Definition SkCodec.h:109
@ kInternalError
Definition SkCodec.h:118
@ kCouldNotRewind
Definition SkCodec.h:114
@ kUnimplemented
Definition SkCodec.h:123
@ kSuccess
Definition SkCodec.h:80
SelectionPolicy
Definition SkCodec.h:136
static constexpr int kRepetitionCountInfinite
Definition SkCodec.h:759
bool colorXform() const
Definition SkCodec.h:906
static constexpr int kNoFrame
Definition SkCodec.h:650
XformFormat getSrcXformFormat() const
Definition SkCodec.h:799
const Options & options() const
Definition SkCodec.h:880
static sk_sp< SkData > MakeWithProc(const void *ptr, size_t length, ReleaseProc proc, void *ctx)
Definition SkData.cpp:128
static std::unique_ptr< ICCProfile > Make(sk_sp< SkData >)
int onGetFrameCount() override
Result onStartScanlineDecode(const SkImageInfo &dstInfo, const Options &options) override
SkSampler * getSampler(bool createIfNecessary) override
static bool IsSupported(const void *, size_t, SkEncodedImageFormat *format)
bool onRewind() override
int onGetScanlines(void *dst, int count, size_t rowBytes) override
int onGetRepetitionCount() override
bool conversionSupported(const SkImageInfo &, bool, bool) override
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, SkCodec::SelectionPolicy selectionPolicy, Result *)
bool onGetFrameInfo(int, FrameInfo *) const override
bool onSkipScanlines(int count) override
Result onGetPixels(const SkImageInfo &dstInfo, void *dst, size_t dstRowBytes, const Options &options, int *rowsDecoded) override
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
Definition SkStream.cpp:314
virtual bool rewind()
Definition SkStream.h:100
virtual size_t peek(void *, size_t) const
Definition SkStream.h:68
virtual size_t read(void *buffer, size_t size)=0
static std::unique_ptr< SkSwizzler > MakeSimple(int srcBPP, const SkImageInfo &dstInfo, const SkCodec::Options &)
T * reset(size_t count=0)
double frame
Definition examples.cpp:31
static const uint8_t buffer[]
GAsyncResult * result
uint32_t uint32_t * format
double y
SK_API bool IsHeif(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
dst
Definition cp.py:12
Definition ref_ptr.h:256
@ skcms_PixelFormat_RGBA_1010102
@ skcms_PixelFormat_RGBA_8888
@ skcms_Signature_RGB
Point offset
std::vector< uint8_t > mIccData
const SkIRect * fSubset
Definition SkCodec.h:347
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
size_t getLength() const override
~SkHeifStreamWrapper() override
size_t read(void *buffer, size_t size) override
bool seek(size_t position) override
bool hasLength() const override
bool rewind() override
SkHeifStreamWrapper(SkStream *stream)
int width() const
SkAlphaType alphaType() const
SkColorType colorType() const
int height() const
SkImageInfo makeColorType(SkColorType newColorType) const