21 {
22
23
24 if (bytesRead < 8) {
25 return false;
26 }
27
28 const uint32_t* ptr = (
const uint32_t*)
buffer;
31
32 if (chunkType !=
FOURCC(
'f',
't',
'y',
'p')) {
33 return false;
34 }
35
37 if (chunkSize == 1) {
38
39
40 if (bytesRead < 16) {
41 return false;
42 }
43 auto* chunkSizePtr = SkTAddOffset<const uint64_t>(
buffer,
offset);
45 if (chunkSize < 16) {
46
47 return false;
48 }
50 } else if (chunkSize < 8) {
51
52 return false;
53 }
54
55 if (chunkSize > bytesRead) {
56 chunkSize = bytesRead;
57 }
58 int64_t chunkDataSize = chunkSize -
offset;
59
60
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
70
71 continue;
72 }
73 auto* brandPtr = SkTAddOffset<const uint32_t>(
buffer,
offset + 4 * i);
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
79
80
81
82 isHeif = true;
83 if (brand ==
FOURCC(
'a',
'v',
'i',
'f')
84 || brand ==
FOURCC(
'a',
'v',
'i',
's')) {
87 }
88 return true;
89 }
90 }
91 }
92 if (isHeif) {
95 }
96 return true;
97 }
98 return false;
99}
100
107 }
109}
110
113
115
116 size_t read(
void*
buffer,
size_t size)
override {
117 return fStream->read(
buffer, size);
118 }
119
121 return fStream->rewind();
122 }
123
124 bool seek(
size_t position)
override {
125 return fStream->seek(position);
126 }
127
129 return fStream->hasLength();
130 }
131
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
149 return nullptr;
150 }
152 if (heifDecoder == nullptr) {
154 return nullptr;
155 }
156
160 if (0 == bytesRead) {
161
162
165 SkCodecPrintf(
"Encoded image data could not peek or rewind to determine format!\n");
167 return nullptr;
168 }
169 }
170
173 SkCodecPrintf(
"Failed to get format despite earlier detecting it");
175 return nullptr;
176 }
177
181 return nullptr;
182 }
183
184 size_t frameCount = 1;
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;
195 auto iccData =
new std::vector<uint8_t>(std::move(heifInfo.
mIccData));
198 }
200
202 }
203
204 uint8_t colorDepth = heifDecoder->getColorDepth();
205
208 8, std::move(profile), colorDepth);
210
213 std::move(
info), heifDecoder.release(), orientation, frameCount > 1,
format));
214}
215
216SkHeifCodec::SkHeifCodec(
220 bool useAnimation,
223 , fHeifDecoder(heifDecoder)
224 , fSwizzleSrcRow(nullptr)
225 , fColorXformSrcRow(nullptr)
226 , fUseAnimation(useAnimation)
228{}
229
231 bool needsColorXform) {
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();
248
252
255 if (needsColorXform) {
257 } else {
259 }
260
264
267 if (srcIsOpaque && colorDepth == 10) {
270 } else {
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
283
284
285
286
287
288
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
312 if (!fHeifDecoder->getScanline(decodeDst)) {
314 }
315
316 if (fSwizzler) {
317 fSwizzler->swizzle(swizzleDst, decodeDst);
318 }
319
322 dst = SkTAddOffset<void>(dst, rowBytes);
323 }
324
325 decodeDst = SkTAddOffset<uint8_t>(decodeDst, decodeDstRowBytes);
326 swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes);
327 }
328
330}
331
333 if (!fUseAnimation) {
334 return 1;
335 }
336
337 if (fFrameHolder.size() == 0) {
338 size_t frameCount;
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();
350
351
352
355 frame->setHasAlpha(
false);
356 }
357 }
358
359 return fFrameHolder.size();
360}
361
362const SkFrame* SkHeifCodec::FrameHolder::onGetFrame(
int i)
const {
364}
365
366SkHeifCodec::Frame* SkHeifCodec::FrameHolder::appendNewFrame() {
367 const int i = this->size();
368 fFrames.emplace_back(i);
369 return &fFrames[i];
370}
371
372const SkHeifCodec::Frame* SkHeifCodec::FrameHolder::frame(int i) const {
374 return &fFrames[i];
375}
376
377SkHeifCodec::Frame* SkHeifCodec::FrameHolder::editFrameAt(int i) {
379 return &fFrames[i];
380}
381
383 if (i >= fFrameHolder.size()) {
384 return false;
385 }
386
387 const Frame*
frame = fFrameHolder.frame(i);
389 return false;
390 }
391
392 if (frameInfo) {
393 frame->fillIn(frameInfo,
true);
394 }
395
396 return true;
397}
398
401}
402
403
404
405
407 void* dst, size_t dstRowBytes,
409 int* rowsDecoded) {
411
412
413
415 }
416
417 bool success;
418 if (fUseAnimation) {
422 } else {
423 success = fHeifDecoder->decode(&fFrameInfo);
424 }
425
426 if (!success) {
428 }
429
430 fSwizzler.reset(nullptr);
431 this->allocateStorage(
dstInfo);
432
435 *rowsDecoded = rows;
437 }
438
440}
441
442void SkHeifCodec::allocateStorage(
const SkImageInfo& dstInfo) {
444
445 size_t swizzleBytes = 0;
446 if (fSwizzler) {
448 dstWidth = fSwizzler->swizzleWidth();
450 }
451
452 size_t xformBytes = 0;
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(
473 break;
476 break;
477 default:
479 }
480
481 int srcBPP = 4;
483 srcBPP = 2;
484 }
485
488}
489
491 if (!createIfNecessary || fSwizzler) {
492 SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.
get() == fSwizzleSrcRow));
493 return fSwizzler.get();
494 }
495
497 this->allocateStorage(this->
dstInfo());
498 return fSwizzler.get();
499}
500
502 fSwizzler.reset(nullptr);
503 fSwizzleSrcRow = nullptr;
504 fColorXformSrcRow = nullptr;
506
507 return true;
508}
509
512
513
514
515 if (!fHeifDecoder->decode(&fFrameInfo)) {
517 }
518
521 } else {
522 fSwizzler.reset(nullptr);
523 }
524
525 this->allocateStorage(
dstInfo);
526
528}
529
532}
533
536}
537
539bool IsHeif(
const void* data,
size_t len) {
541}
542
543std::unique_ptr<SkCodec>
Decode(std::unique_ptr<SkStream> stream,
545 SkCodecs::DecodeContext ctx) {
548 if (!outResult) {
549 outResult = &resultStorage;
550 }
553}
554
557 SkCodecs::DecodeContext ctx) {
558 if (!data) {
559 if (outResult) {
561 }
562 return nullptr;
563 }
565}
566}
567
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static constexpr bool SkIsAlign4(T x)
@ kUnknown_SkAlphaType
uninitialized
@ kOpaque_SkAlphaType
pixel is opaque
#define SkCodecPrintf(...)
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
@ kBottomRight_SkEncodedOrigin
@ kTopLeft_SkEncodedOrigin
@ kLeftBottom_SkEncodedOrigin
@ kDefault_SkEncodedOrigin
@ kRightTop_SkEncodedOrigin
#define SkEndian_SwapBE32(n)
#define SkEndian_SwapBE64(n)
#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
void applyColorXform(void *dst, const void *src, int count) const
static constexpr size_t MinBufferedBytesNeeded()
void setSrcXformFormat(XformFormat pixelFormat)
static constexpr int kRepetitionCountInfinite
static constexpr int kNoFrame
XformFormat getSrcXformFormat() const
const Options & options() const
static sk_sp< SkData > MakeWithProc(const void *ptr, size_t length, ReleaseProc proc, void *ctx)
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)
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)
virtual size_t peek(void *, size_t) const
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)
static const uint8_t buffer[]
uint32_t uint32_t * format
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
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
@ skcms_PixelFormat_RGBA_1010102
@ skcms_PixelFormat_RGBA_8888
std::vector< uint8_t > mIccData
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
SkAlphaType alphaType() const
SkColorType colorType() const
SkImageInfo makeColorType(SkColorType newColorType) const