Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Functions
SkHeifCodec.cpp File Reference
#include "src/codec/SkHeifCodec.h"
#include "include/codec/SkCodec.h"
#include "include/codec/SkEncodedImageFormat.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypes.h"
#include "include/private/SkColorData.h"
#include "include/private/base/SkTemplates.h"
#include "src/base/SkEndian.h"
#include "src/codec/SkCodecPriv.h"

Go to the source code of this file.

Classes

struct  SkHeifStreamWrapper
 

Namespaces

namespace  SkHeifDecoder
 

Macros

#define FOURCC(c1, c2, c3, c4)    ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4))
 

Functions

static SkEncodedOrigin get_orientation (const HeifFrameInfo &frameInfo)
 
static void releaseProc (const void *ptr, void *context)
 
SK_API bool SkHeifDecoder::IsHeif (const void *, size_t)
 
SK_API std::unique_ptr< SkCodecSkHeifDecoder::Decode (std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
 
SK_API std::unique_ptr< SkCodecSkHeifDecoder::Decode (sk_sp< SkData >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
 

Macro Definition Documentation

◆ FOURCC

#define FOURCC (   c1,
  c2,
  c3,
  c4 
)     ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4))

Definition at line 18 of file SkHeifCodec.cpp.

21 {
22 // Parse the ftyp box up to bytesRead to determine if this is HEIF or AVIF.
23 // Any valid ftyp box should have at least 8 bytes.
24 if (bytesRead < 8) {
25 return false;
26 }
27
28 const uint32_t* ptr = (const uint32_t*)buffer;
29 uint64_t chunkSize = SkEndian_SwapBE32(ptr[0]);
30 uint32_t chunkType = SkEndian_SwapBE32(ptr[1]);
31
32 if (chunkType != FOURCC('f', 't', 'y', 'p')) {
33 return false;
34 }
35
36 int64_t offset = 8;
37 if (chunkSize == 1) {
38 // This indicates that the next 8 bytes represent the chunk size,
39 // and chunk data comes after that.
40 if (bytesRead < 16) {
41 return false;
42 }
43 auto* chunkSizePtr = SkTAddOffset<const uint64_t>(buffer, offset);
44 chunkSize = SkEndian_SwapBE64(*chunkSizePtr);
45 if (chunkSize < 16) {
46 // The smallest valid chunk is 16 bytes long in this case.
47 return false;
48 }
49 offset += 8;
50 } else if (chunkSize < 8) {
51 // The smallest valid chunk is 8 bytes long.
52 return false;
53 }
54
55 if (chunkSize > bytesRead) {
56 chunkSize = bytesRead;
57 }
58 int64_t chunkDataSize = chunkSize - offset;
59 // It should at least have major brand (4-byte) and minor version (4-bytes).
60 // The rest of the chunk (if any) is a list of (4-byte) compatible brands.
61 if (chunkDataSize < 8) {
62 return false;
63 }
64
65 uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
66 bool isHeif = false;
67 for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
68 if (i == 1) {
69 // Skip this index, it refers to the minorVersion,
70 // not a brand.
71 continue;
72 }
73 auto* brandPtr = SkTAddOffset<const uint32_t>(buffer, offset + 4 * i);
74 uint32_t brand = SkEndian_SwapBE32(*brandPtr);
75 if (brand == FOURCC('m', 'i', 'f', '1') || brand == FOURCC('h', 'e', 'i', 'c')
76 || brand == FOURCC('m', 's', 'f', '1') || brand == FOURCC('h', 'e', 'v', 'c')
77 || brand == FOURCC('a', 'v', 'i', 'f') || brand == FOURCC('a', 'v', 'i', 's')) {
78 // AVIF files could have "mif1" as the major brand. So we cannot
79 // distinguish whether the image is AVIF or HEIC just based on the
80 // "mif1" brand. So wait until we see a specific avif brand to
81 // determine whether it is AVIF or HEIC.
82 isHeif = true;
83 if (brand == FOURCC('a', 'v', 'i', 'f')
84 || brand == FOURCC('a', 'v', 'i', 's')) {
85 if (format != nullptr) {
87 }
88 return true;
89 }
90 }
91 }
92 if (isHeif) {
93 if (format != nullptr) {
95 }
96 return true;
97 }
98 return false;
99}
100
101static SkEncodedOrigin get_orientation(const HeifFrameInfo& frameInfo) {
102 switch (frameInfo.mRotationAngle) {
103 case 0: return kTopLeft_SkEncodedOrigin;
104 case 90: return kRightTop_SkEncodedOrigin;
105 case 180: return kBottomRight_SkEncodedOrigin;
106 case 270: return kLeftBottom_SkEncodedOrigin;
107 }
109}
110
111struct SkHeifStreamWrapper : public HeifStream {
112 SkHeifStreamWrapper(SkStream* stream) : fStream(stream) {}
113
114 ~SkHeifStreamWrapper() override {}
115
116 size_t read(void* buffer, size_t size) override {
117 return fStream->read(buffer, size);
118 }
119
120 bool rewind() override {
121 return fStream->rewind();
122 }
123
124 bool seek(size_t position) override {
125 return fStream->seek(position);
126 }
127
128 bool hasLength() const override {
129 return fStream->hasLength();
130 }
131
132 size_t getLength() const override {
133 return fStream->getLength();
134 }
135
136private:
137 std::unique_ptr<SkStream> fStream;
138};
139
140static void releaseProc(const void* ptr, void* context) {
141 delete reinterpret_cast<std::vector<uint8_t>*>(context);
142}
143
144std::unique_ptr<SkCodec> SkHeifCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
145 SkCodec::SelectionPolicy selectionPolicy, Result* result) {
147 if (!stream) {
149 return nullptr;
150 }
151 std::unique_ptr<HeifDecoder> heifDecoder(createHeifDecoder());
152 if (heifDecoder == nullptr) {
154 return nullptr;
155 }
156
157 constexpr size_t bytesToRead = MinBufferedBytesNeeded();
158 char buffer[bytesToRead];
159 size_t bytesRead = stream->peek(buffer, bytesToRead);
160 if (0 == bytesRead) {
161 // It is possible the stream does not support peeking, but does support rewinding.
162 // Attempt to read() and pass the actual amount read to the decoder.
163 bytesRead = stream->read(buffer, bytesToRead);
164 if (!stream->rewind()) {
165 SkCodecPrintf("Encoded image data could not peek or rewind to determine format!\n");
167 return nullptr;
168 }
169 }
170
172 if (!SkHeifCodec::IsSupported(buffer, bytesRead, &format)) {
173 SkCodecPrintf("Failed to get format despite earlier detecting it");
175 return nullptr;
176 }
177
178 HeifFrameInfo heifInfo;
179 if (!heifDecoder->init(new SkHeifStreamWrapper(stream.release()), &heifInfo)) {
181 return nullptr;
182 }
183
184 size_t frameCount = 1;
185 if (selectionPolicy == SkCodec::SelectionPolicy::kPreferAnimation) {
186 HeifFrameInfo sequenceInfo;
187 if (heifDecoder->getSequenceInfo(&sequenceInfo, &frameCount) &&
188 frameCount > 1) {
189 heifInfo = std::move(sequenceInfo);
190 }
191 }
192
193 std::unique_ptr<SkEncodedInfo::ICCProfile> profile = nullptr;
194 if (heifInfo.mIccData.size() > 0) {
195 auto iccData = new std::vector<uint8_t>(std::move(heifInfo.mIccData));
196 auto icc = SkData::MakeWithProc(iccData->data(), iccData->size(), releaseProc, iccData);
198 }
199 if (profile && profile->profile()->data_color_space != skcms_Signature_RGB) {
200 // This will result in sRGB.
201 profile = nullptr;
202 }
203
204 uint8_t colorDepth = heifDecoder->getColorDepth();
205
208 /*bitsPerComponent*/ 8, std::move(profile), colorDepth);
209 SkEncodedOrigin orientation = get_orientation(heifInfo);
210
212 return std::unique_ptr<SkCodec>(new SkHeifCodec(
213 std::move(info), heifDecoder.release(), orientation, frameCount > 1, format));
214}
215
216SkHeifCodec::SkHeifCodec(
218 HeifDecoder* heifDecoder,
219 SkEncodedOrigin origin,
220 bool useAnimation,
222 : INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, nullptr, origin)
223 , fHeifDecoder(heifDecoder)
224 , fSwizzleSrcRow(nullptr)
225 , fColorXformSrcRow(nullptr)
226 , fUseAnimation(useAnimation)
227 , fFormat(format)
228{}
229
230bool SkHeifCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,
231 bool needsColorXform) {
232 SkASSERT(srcIsOpaque);
233
235 return false;
236 }
237
239 SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
240 "- it is being decoded as non-opaque, which will draw slower\n");
241 }
242
243 uint8_t colorDepth = fHeifDecoder->getColorDepth();
244 switch (dstInfo.colorType()) {
247 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
248
251 return fHeifDecoder->setOutputColor(kHeifColorFormat_BGRA_8888);
252
255 if (needsColorXform) {
256 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
257 } else {
258 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGB565);
259 }
260
263 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_1010102);
264
266 SkASSERT(needsColorXform);
267 if (srcIsOpaque && colorDepth == 10) {
269 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_1010102);
270 } else {
272 return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
273 }
274
275 default:
276 return false;
277 }
278}
279
280int SkHeifCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count,
281 const Options& opts) {
282 // When fSwizzleSrcRow is non-null, it means that we need to swizzle. In this case,
283 // we will always decode into fSwizzlerSrcRow before swizzling into the next buffer.
284 // We can never swizzle "in place" because the swizzler may perform sampling and/or
285 // subsetting.
286 // When fColorXformSrcRow is non-null, it means that we need to color xform and that
287 // we cannot color xform "in place" (many times we can, but not when the dst is F16).
288 // In this case, we will color xform from fColorXformSrcRow into the dst.
289 uint8_t* decodeDst = (uint8_t*) dst;
290 uint32_t* swizzleDst = (uint32_t*) dst;
291 size_t decodeDstRowBytes = rowBytes;
292 size_t swizzleDstRowBytes = rowBytes;
293 int dstWidth = opts.fSubset ? opts.fSubset->width() : dstInfo.width();
294 if (fSwizzleSrcRow && fColorXformSrcRow) {
295 decodeDst = fSwizzleSrcRow;
296 swizzleDst = fColorXformSrcRow;
297 decodeDstRowBytes = 0;
298 swizzleDstRowBytes = 0;
299 dstWidth = fSwizzler->swizzleWidth();
300 } else if (fColorXformSrcRow) {
301 decodeDst = (uint8_t*) fColorXformSrcRow;
302 swizzleDst = fColorXformSrcRow;
303 decodeDstRowBytes = 0;
304 swizzleDstRowBytes = 0;
305 } else if (fSwizzleSrcRow) {
306 decodeDst = fSwizzleSrcRow;
307 decodeDstRowBytes = 0;
308 dstWidth = fSwizzler->swizzleWidth();
309 }
310
311 for (int y = 0; y < count; y++) {
312 if (!fHeifDecoder->getScanline(decodeDst)) {
313 return y;
314 }
315
316 if (fSwizzler) {
317 fSwizzler->swizzle(swizzleDst, decodeDst);
318 }
319
320 if (this->colorXform()) {
321 this->applyColorXform(dst, swizzleDst, dstWidth);
322 dst = SkTAddOffset<void>(dst, rowBytes);
323 }
324
325 decodeDst = SkTAddOffset<uint8_t>(decodeDst, decodeDstRowBytes);
326 swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes);
327 }
328
329 return count;
330}
331
333 if (!fUseAnimation) {
334 return 1;
335 }
336
337 if (fFrameHolder.size() == 0) {
338 size_t frameCount;
339 HeifFrameInfo frameInfo;
340 if (!fHeifDecoder->getSequenceInfo(&frameInfo, &frameCount)
341 || frameCount <= 1) {
342 fUseAnimation = false;
343 return 1;
344 }
345 fFrameHolder.reserve(frameCount);
346 for (size_t i = 0; i < frameCount; i++) {
347 Frame* frame = fFrameHolder.appendNewFrame();
348 frame->setXYWH(0, 0, frameInfo.mWidth, frameInfo.mHeight);
350 // Currently we don't know the duration until the frame is actually
351 // decoded (onGetFrameInfo is also called before frame is decoded).
352 // For now, fill it base on the value reported for the sequence.
353 frame->setDuration(frameInfo.mDurationUs / 1000);
354 frame->setRequiredFrame(SkCodec::kNoFrame);
355 frame->setHasAlpha(false);
356 }
357 }
358
359 return fFrameHolder.size();
360}
361
362const SkFrame* SkHeifCodec::FrameHolder::onGetFrame(int i) const {
363 return static_cast<const SkFrame*>(this->frame(i));
364}
365
366SkHeifCodec::Frame* SkHeifCodec::FrameHolder::appendNewFrame() {
367 const int i = this->size();
368 fFrames.emplace_back(i); // TODO: need to handle frame duration here
369 return &fFrames[i];
370}
371
372const SkHeifCodec::Frame* SkHeifCodec::FrameHolder::frame(int i) const {
373 SkASSERT(i >= 0 && i < this->size());
374 return &fFrames[i];
375}
376
377SkHeifCodec::Frame* SkHeifCodec::FrameHolder::editFrameAt(int i) {
378 SkASSERT(i >= 0 && i < this->size());
379 return &fFrames[i];
380}
381
382bool SkHeifCodec::onGetFrameInfo(int i, FrameInfo* frameInfo) const {
383 if (i >= fFrameHolder.size()) {
384 return false;
385 }
386
387 const Frame* frame = fFrameHolder.frame(i);
388 if (!frame) {
389 return false;
390 }
391
392 if (frameInfo) {
393 frame->fillIn(frameInfo, true);
394 }
395
396 return true;
397}
398
401}
402
403/*
404 * Performs the heif decode
405 */
407 void* dst, size_t dstRowBytes,
408 const Options& options,
409 int* rowsDecoded) {
410 if (options.fSubset) {
411 // Not supporting subsets on this path for now.
412 // TODO: if the heif has tiles, we can support subset here, but
413 // need to retrieve tile config from metadata retriever first.
414 return kUnimplemented;
415 }
416
417 bool success;
418 if (fUseAnimation) {
419 success = fHeifDecoder->decodeSequence(options.fFrameIndex, &fFrameInfo);
420 fFrameHolder.editFrameAt(options.fFrameIndex)->setDuration(
421 fFrameInfo.mDurationUs / 1000);
422 } else {
423 success = fHeifDecoder->decode(&fFrameInfo);
424 }
425
426 if (!success) {
427 return kInvalidInput;
428 }
429
430 fSwizzler.reset(nullptr);
431 this->allocateStorage(dstInfo);
432
433 int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height(), options);
434 if (rows < dstInfo.height()) {
435 *rowsDecoded = rows;
436 return kIncompleteInput;
437 }
438
439 return kSuccess;
440}
441
442void SkHeifCodec::allocateStorage(const SkImageInfo& dstInfo) {
443 int dstWidth = dstInfo.width();
444
445 size_t swizzleBytes = 0;
446 if (fSwizzler) {
447 swizzleBytes = fFrameInfo.mBytesPerPixel * fFrameInfo.mWidth;
448 dstWidth = fSwizzler->swizzleWidth();
449 SkASSERT(!this->colorXform() || SkIsAlign4(swizzleBytes));
450 }
451
452 size_t xformBytes = 0;
453 if (this->colorXform() && (kRGBA_F16_SkColorType == dstInfo.colorType() ||
455 xformBytes = dstWidth * sizeof(uint32_t);
456 }
457
458 size_t totalBytes = swizzleBytes + xformBytes;
459 fStorage.reset(totalBytes);
460 if (totalBytes > 0) {
461 fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr;
462 fColorXformSrcRow = (xformBytes > 0) ?
463 SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr;
464 }
465}
466
467void SkHeifCodec::initializeSwizzler(
468 const SkImageInfo& dstInfo, const Options& options) {
469 SkImageInfo swizzlerDstInfo = dstInfo;
470 switch (this->getSrcXformFormat()) {
472 swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_8888_SkColorType);
473 break;
475 swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_1010102_SkColorType);
476 break;
477 default:
478 SkASSERT(false);
479 }
480
481 int srcBPP = 4;
482 if (dstInfo.colorType() == kRGB_565_SkColorType && !this->colorXform()) {
483 srcBPP = 2;
484 }
485
486 fSwizzler = SkSwizzler::MakeSimple(srcBPP, swizzlerDstInfo, options);
487 SkASSERT(fSwizzler);
488}
489
490SkSampler* SkHeifCodec::getSampler(bool createIfNecessary) {
491 if (!createIfNecessary || fSwizzler) {
492 SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.get() == fSwizzleSrcRow));
493 return fSwizzler.get();
494 }
495
496 this->initializeSwizzler(this->dstInfo(), this->options());
497 this->allocateStorage(this->dstInfo());
498 return fSwizzler.get();
499}
500
502 fSwizzler.reset(nullptr);
503 fSwizzleSrcRow = nullptr;
504 fColorXformSrcRow = nullptr;
505 fStorage.reset();
506
507 return true;
508}
509
511 const SkImageInfo& dstInfo, const Options& options) {
512 // TODO: For now, just decode the whole thing even when there is a subset.
513 // If the heif image has tiles, we could potentially do this much faster,
514 // but the tile configuration needs to be retrieved from the metadata.
515 if (!fHeifDecoder->decode(&fFrameInfo)) {
516 return kInvalidInput;
517 }
518
519 if (options.fSubset) {
520 this->initializeSwizzler(dstInfo, options);
521 } else {
522 fSwizzler.reset(nullptr);
523 }
524
525 this->allocateStorage(dstInfo);
526
527 return kSuccess;
528}
529
530int SkHeifCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
531 return this->readRows(this->dstInfo(), dst, dstRowBytes, count, this->options());
532}
533
534bool SkHeifCodec::onSkipScanlines(int count) {
535 return count == (int) fHeifDecoder->skipScanlines(count);
536}
537
538namespace SkHeifDecoder {
539bool IsHeif(const void* data, size_t len) {
540 return SkHeifCodec::IsSupported(data, len, nullptr);
541}
542
543std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
544 SkCodec::Result* outResult,
545 SkCodecs::DecodeContext ctx) {
546 SkASSERT(ctx);
547 SkCodec::Result resultStorage;
548 if (!outResult) {
549 outResult = &resultStorage;
550 }
551 auto policy = static_cast<SkCodec::SelectionPolicy*>(ctx);
552 return SkHeifCodec::MakeFromStream(std::move(stream), *policy, outResult);
553}
554
555std::unique_ptr<SkCodec> Decode(sk_sp<SkData> data,
556 SkCodec::Result* outResult,
557 SkCodecs::DecodeContext ctx) {
558 if (!data) {
559 if (outResult) {
560 *outResult = SkCodec::kInvalidInput;
561 }
562 return nullptr;
563 }
564 return Decode(SkMemoryStream::Make(std::move(data)), outResult, ctx);
565}
566} // namespace SkHeifDecoder
567
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 policy
Definition switches.h:248
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
int width() const
SkAlphaType alphaType() const
SkColorType colorType() const
int height() const
SkImageInfo makeColorType(SkColorType newColorType) const

Function Documentation

◆ get_orientation()

static SkEncodedOrigin get_orientation ( const HeifFrameInfo frameInfo)
static

Definition at line 102 of file SkHeifCodec.cpp.

102 {
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}

◆ releaseProc()

static void releaseProc ( const void *  ptr,
void *  context 
)
static

Definition at line 141 of file SkHeifCodec.cpp.

141 {
142 delete reinterpret_cast<std::vector<uint8_t>*>(context);
143}