46#include "webp/decode.h"
47#include "webp/demux.h"
48#include "webp/mux_types.h"
54 const char* bytes =
static_cast<const char*
>(buf);
55 return bytesRead >= 14 && !memcmp(bytes,
"RIFF", 4) && !memcmp(&bytes[8],
"WEBPVP", 6);
82 WebPData webpData = {
data->bytes(),
data->size() };
86 case WEBP_DEMUX_PARSE_ERROR:
89 case WEBP_DEMUX_PARSING_HEADER:
92 case WEBP_DEMUX_PARSED_HEADER:
98 const int width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
99 const int height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
105 if (!SkTFitsIn<int32_t>(
size) || SkTo<int32_t>(
size) > (0x7FFFFFFF >> 2)) {
111 std::unique_ptr<SkEncodedInfo::ICCProfile>
profile =
nullptr;
113 WebPChunkIterator chunkIterator;
115 if (WebPDemuxGetChunk(demux,
"ICCP", 1, &chunkIterator)) {
127 WebPChunkIterator chunkIterator;
129 if (WebPDemuxGetChunk(demux,
"EXIF", 1, &chunkIterator)) {
137 if (!WebPDemuxGetFrame(demux, 1, &
frame)) {
142 WebPBitstreamFeatures features;
143 switch (WebPGetFeatures(
frame.fragment.bytes,
frame.fragment.size, &features)) {
146 case VP8_STATUS_SUSPENDED:
147 case VP8_STATUS_NOT_ENOUGH_DATA:
159 switch (features.format) {
197 demux.release(), std::move(
data), origin));
203 return premultiply ? MODE_bgrA : MODE_BGRA;
205 return premultiply ? MODE_rgbA : MODE_RGBA;
213SkWebpCodec::Frame* SkWebpCodec::FrameHolder::appendNewFrame(
bool hasAlpha) {
214 const int i = this->
size();
221 if (!desiredSubset) {
232 desiredSubset->
fLeft = (desiredSubset->
fLeft >> 1) << 1;
233 desiredSubset->
fTop = (desiredSubset->
fTop >> 1) << 1;
238 auto flags = WebPDemuxGetI(fDemux.get(), WEBP_FF_FORMAT_FLAGS);
239 if (!(
flags & ANIMATION_FLAG)) {
243 int loopCount = WebPDemuxGetI(fDemux.get(), WEBP_FF_LOOP_COUNT);
244 if (0 == loopCount) {
253 auto flags = WebPDemuxGetI(fDemux.get(), WEBP_FF_FORMAT_FLAGS);
254 if (!(
flags & ANIMATION_FLAG)) {
258 const uint32_t oldFrameCount = fFrameHolder.size();
260 return oldFrameCount;
263 const uint32_t frameCount = WebPDemuxGetI(fDemux, WEBP_FF_FRAME_COUNT);
264 if (oldFrameCount == frameCount) {
269 fFrameHolder.reserve(frameCount);
271 for (uint32_t
i = oldFrameCount;
i < frameCount;
i++) {
275 if (!WebPDemuxGetFrame(fDemux.get(),
i + 1, &iter)) {
283 Frame*
frame = fFrameHolder.appendNewFrame(iter.has_alpha);
284 frame->setXYWH(iter.x_offset, iter.y_offset, iter.width, iter.height);
285 frame->setDisposalMethod(iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ?
288 frame->setDuration(iter.duration);
289 if (WEBP_MUX_BLEND != iter.blend_method) {
292 fFrameHolder.setAlphaAndRequiredFrame(
frame);
295 return fFrameHolder.size();
299const SkFrame* SkWebpCodec::FrameHolder::onGetFrame(
int i)
const {
309 if (
i >= fFrameHolder.size()) {
313 const Frame*
frame = fFrameHolder.frame(
i);
321 frame->fillIn(frameInfo,
true);
344 src_ctx = {
const_cast<void*
>(
src), 0 };
348 p.appendLoadDst(dstCT, &dst_ctx);
350 p.append(SkRasterPipelineOp::premul_dst);
353 p.appendLoad(srcCT, &src_ctx);
358 p.append(SkRasterPipelineOp::srcover);
361 p.append(SkRasterPipelineOp::unpremul);
363 p.appendStore(dstCT, &dst_ctx);
371 SkASSERT(0 == index || index < fFrameHolder.size());
374 WebPDecoderConfig config;
375 if (0 == WebPInitDecoderConfig(&config)) {
390 (fFrameHolder.frame(index)->getRequiredFrame() ==
kNoFrame);
395 const bool frameIsSubset = frameRect != this->
bounds();
396 if (independent && frameIsSubset) {
400 int dstX = frameRect.x();
401 int dstY = frameRect.y();
402 int subsetWidth = frameRect.width();
403 int subsetHeight = frameRect.height();
414 int minXOffset =
std::min(dstX, subset.
x());
415 int minYOffset =
std::min(dstY, subset.
y());
418 frameRect.offset(-minXOffset, -minYOffset);
419 subset.
offset(-minXOffset, -minYOffset);
428 subsetWidth = intersection.
width();
429 subsetHeight = intersection.
height();
431 config.options.use_cropping = 1;
432 config.options.crop_left = subset.
x();
433 config.options.crop_top = subset.
y();
434 config.options.crop_width = subsetWidth;
435 config.options.crop_height = subsetHeight;
439 int scaledWidth = subsetWidth;
440 int scaledHeight = subsetHeight;
443 config.options.use_scaling = 1;
451 dstX = scaleX * dstX;
452 scaledWidth = scaleX * scaledWidth;
453 dstY = scaleY * dstY;
454 scaledHeight = scaleY * scaledHeight;
455 if (0 == scaledWidth || 0 == scaledHeight) {
463 config.options.scaled_width = scaledWidth;
464 config.options.scaled_height = scaledHeight;
467 const bool blendWithPrevFrame = !
independent &&
frame.blend_method == WEBP_MUX_BLEND
471 if (!
frame.has_alpha) {
473 }
else if (this->
colorXform() || blendWithPrevFrame) {
499 config.output.is_external_memory = 1;
501 config.output.u.RGBA.rgba =
reinterpret_cast<uint8_t*
>(webpDst.
getAddr(dstX, dstY));
502 config.output.u.RGBA.stride =
static_cast<int>(webpDst.
rowBytes());
512 switch (WebPIUpdate(idec,
frame.fragment.bytes,
frame.fragment.size)) {
514 rowsDecoded = scaledHeight;
517 case VP8_STATUS_SUSPENDED:
518 if (!WebPIDecGetRGB(idec, &rowsDecoded,
nullptr,
nullptr,
nullptr)
519 || rowsDecoded <= 0) {
522 *rowsDecodedPtr = rowsDecoded + dstY;
530 dst = SkTAddOffset<void>(
dst, dstBpp * dstX + rowBytes * dstY);
531 const size_t srcRowBytes = config.output.u.RGBA.stride;
535 uint32_t* xformSrc = (uint32_t*) config.output.u.RGBA.rgba;
539 if (blendWithPrevFrame) {
542 xformDst = tmp.getPixels();
547 for (
int y = 0;
y < rowsDecoded;
y++) {
549 if (blendWithPrevFrame) {
552 dst = SkTAddOffset<void>(
dst, rowBytes);
554 xformDst = SkTAddOffset<void>(xformDst, rowBytes);
556 xformSrc = SkTAddOffset<uint32_t>(xformSrc, srcRowBytes);
558 }
else if (blendWithPrevFrame) {
559 const uint8_t*
src = config.output.u.RGBA.rgba;
561 for (
int y = 0;
y < rowsDecoded;
y++) {
564 src = SkTAddOffset<const uint8_t>(
src, srcRowBytes);
565 dst = SkTAddOffset<void>(
dst, rowBytes);
581 fFrameHolder.setScreenSize(eInfo.width(), eInfo.height());
594 outResult = &resultStorage;
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static constexpr bool SkIsAlign2(T x)
@ kOpaque_SkAlphaType
pixel is opaque
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
static bool independent(const SkFrame &frame)
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
@ 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
@ kDefault_SkEncodedOrigin
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static int64_t sk_64_mul(int64_t a, int64_t b)
bool SkParseEncodedOrigin(const void *data, size_t data_length, SkEncodedOrigin *orientation)
#define INHERITED(method,...)
sk_sp< SkData > SkCopyStreamToData(SkStream *stream)
static constexpr bool SkToBool(const T &x)
static bool is_8888(SkColorType colorType)
static WEBP_CSP_MODE webp_decode_mode(SkColorType dstCT, bool premultiply)
static void blend_line(SkColorType dstCT, void *dst, SkColorType srcCT, const void *src, SkAlphaType dstAt, bool srcHasAlpha, int width)
static uint32_t premul(uint32_t color)
void allocPixels(const SkImageInfo &info, size_t rowBytes)
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
size_t computeByteSize() const
void * getAddr(int x, int y) const
SkColorType colorType() const
bool getValidSubset(SkIRect *desiredSubset) const
SkISize dimensions() const
const SkImageInfo & dstInfo() const
void applyColorXform(void *dst, const void *src, int count) const
const SkEncodedInfo & getEncodedInfo() const
static constexpr int kRepetitionCountInfinite
static constexpr int kNoFrame
const Options & options() const
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
static std::unique_ptr< ICCProfile > Make(sk_sp< SkData >)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
static void Fill(const SkImageInfo &info, void *dst, size_t rowBytes, SkCodec::ZeroInitialized zeroInit)
virtual size_t getLength() const
virtual const void * getMemoryBase()
bool onGetFrameInfo(int, FrameInfo *) const override
int onGetFrameCount() override
static bool IsWebp(const void *, size_t)
static std::unique_ptr< SkCodec > MakeFromStream(std::unique_ptr< SkStream >, Result *)
bool onGetValidSubset(SkIRect *) const override
int onGetRepetitionCount() override
Result onGetPixels(const SkImageInfo &, void *, size_t, const Options &, int *) override
FlutterSemanticsFlag flags
static float min(float r, float g, float b)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API bool IsWebp(const void *, size_t)
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
constexpr bool contains(std::string_view str, std::string_view needle)
@ skcms_PixelFormat_BGRA_8888
ZeroInitialized fZeroInitialized
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)
constexpr int32_t x() const
constexpr int32_t y() const
bool intersect(const SkIRect &r)
static bool Intersects(const SkIRect &a, const SkIRect &b)
constexpr SkISize size() const
constexpr int32_t height() const
int32_t fTop
smaller y-axis bounds
constexpr int32_t width() const
void offset(int32_t dx, int32_t dy)
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
int32_t fLeft
smaller x-axis bounds
constexpr int32_t width() const
constexpr int32_t height() const
SkImageInfo makeWH(int newWidth, int newHeight) const
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const
int bytesPerPixel() const
SkISize dimensions() const
SkAlphaType alphaType() const
SkColorType colorType() const
SkImageInfo makeColorType(SkColorType newColorType) const
std::shared_ptr< const fml::Mapping > data