Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Static Public Member Functions | Protected Member Functions | List of all members
SkWebpCodec Class Referencefinal

#include <SkWebpCodec.h>

Inheritance diagram for SkWebpCodec:
SkScalingCodec SkCodec SkNoncopyable

Static Public Member Functions

static std::unique_ptr< SkCodecMakeFromStream (std::unique_ptr< SkStream >, Result *)
 
static bool IsWebp (const void *, size_t)
 
- Static Public Member Functions inherited from SkCodec
static constexpr size_t MinBufferedBytesNeeded ()
 
static const char * ResultToString (Result)
 
static std::unique_ptr< SkCodecMakeFromStream (std::unique_ptr< SkStream >, SkSpan< const SkCodecs::Decoder > decoders, Result *=nullptr, SkPngChunkReader *=nullptr, SelectionPolicy selectionPolicy=SelectionPolicy::kPreferStillImage)
 
static std::unique_ptr< SkCodecMakeFromStream (std::unique_ptr< SkStream >, Result *=nullptr, SkPngChunkReader *=nullptr, SelectionPolicy selectionPolicy=SelectionPolicy::kPreferStillImage)
 
static std::unique_ptr< SkCodecMakeFromData (sk_sp< SkData >, SkSpan< const SkCodecs::Decoder > decoders, SkPngChunkReader *=nullptr)
 
static std::unique_ptr< SkCodecMakeFromData (sk_sp< SkData >, SkPngChunkReader *=nullptr)
 
static void Register (bool(*peek)(const void *, size_t), std::unique_ptr< SkCodec >(*make)(std::unique_ptr< SkStream >, SkCodec::Result *))
 

Protected Member Functions

Result onGetPixels (const SkImageInfo &, void *, size_t, const Options &, int *) override
 
SkEncodedImageFormat onGetEncodedFormat () const override
 
bool onGetValidSubset (SkIRect *) const override
 
int onGetFrameCount () override
 
bool onGetFrameInfo (int, FrameInfo *) const override
 
int onGetRepetitionCount () override
 
const SkFrameHoldergetFrameHolder () const override
 
- Protected Member Functions inherited from SkScalingCodec
 SkScalingCodec (SkEncodedInfo &&info, XformFormat srcFormat, std::unique_ptr< SkStream > stream, SkEncodedOrigin origin=kTopLeft_SkEncodedOrigin)
 
SkISize onGetScaledDimensions (float desiredScale) const override
 
bool onDimensionsSupported (const SkISize &requested) override
 
- Protected Member Functions inherited from SkCodec
const SkEncodedInfogetEncodedInfo () const
 
 SkCodec (SkEncodedInfo &&, XformFormat srcFormat, std::unique_ptr< SkStream >, SkEncodedOrigin=kTopLeft_SkEncodedOrigin)
 
void setSrcXformFormat (XformFormat pixelFormat)
 
XformFormat getSrcXformFormat () const
 
virtual bool onGetGainmapInfo (SkGainmapInfo *, std::unique_ptr< SkStream > *)
 
virtual bool onQueryYUVAInfo (const SkYUVAPixmapInfo::SupportedDataTypes &, SkYUVAPixmapInfo *) const
 
virtual Result onGetYUVAPlanes (const SkYUVAPixmaps &)
 
bool rewindIfNeeded ()
 
virtual bool onRewind ()
 
SkStreamstream ()
 
virtual SkScanlineOrder onGetScanlineOrder () const
 
const SkImageInfodstInfo () const
 
const Optionsoptions () const
 
int currScanline () const
 
virtual int onOutputScanline (int inputScanline) const
 
virtual bool conversionSupported (const SkImageInfo &dst, bool srcIsOpaque, bool needsColorXform)
 
virtual bool usesColorXform () const
 
void applyColorXform (void *dst, const void *src, int count) const
 
bool colorXform () const
 
bool xformOnDecode () const
 

Additional Inherited Members

- Public Types inherited from SkCodec
enum  Result {
  kSuccess , kIncompleteInput , kErrorInInput , kInvalidConversion ,
  kInvalidScale , kInvalidParameters , kInvalidInput , kCouldNotRewind ,
  kInternalError , kUnimplemented
}
 
enum class  SelectionPolicy { kPreferStillImage , kPreferAnimation }
 
enum  ZeroInitialized { kYes_ZeroInitialized , kNo_ZeroInitialized }
 
enum  SkScanlineOrder { kTopDown_SkScanlineOrder , kBottomUp_SkScanlineOrder }
 
- Public Member Functions inherited from SkCodec
virtual ~SkCodec ()
 
SkImageInfo getInfo () const
 
SkISize dimensions () const
 
SkIRect bounds () const
 
const skcms_ICCProfilegetICCProfile () const
 
SkEncodedOrigin getOrigin () const
 
SkISize getScaledDimensions (float desiredScale) const
 
bool getValidSubset (SkIRect *desiredSubset) const
 
SkEncodedImageFormat getEncodedFormat () const
 
virtual std::unique_ptr< SkStreamgetEncodedData () const
 
Result getPixels (const SkImageInfo &info, void *pixels, size_t rowBytes, const Options *)
 
Result getPixels (const SkImageInfo &info, void *pixels, size_t rowBytes)
 
Result getPixels (const SkPixmap &pm, const Options *opts=nullptr)
 
std::tuple< sk_sp< SkImage >, SkCodec::ResultgetImage (const SkImageInfo &info, const Options *opts=nullptr)
 
std::tuple< sk_sp< SkImage >, SkCodec::ResultgetImage ()
 
bool queryYUVAInfo (const SkYUVAPixmapInfo::SupportedDataTypes &supportedDataTypes, SkYUVAPixmapInfo *yuvaPixmapInfo) const
 
Result getYUVAPlanes (const SkYUVAPixmaps &yuvaPixmaps)
 
Result startIncrementalDecode (const SkImageInfo &dstInfo, void *dst, size_t rowBytes, const Options *)
 
Result startIncrementalDecode (const SkImageInfo &dstInfo, void *dst, size_t rowBytes)
 
Result incrementalDecode (int *rowsDecoded=nullptr)
 
Result startScanlineDecode (const SkImageInfo &dstInfo, const Options *options)
 
Result startScanlineDecode (const SkImageInfo &dstInfo)
 
int getScanlines (void *dst, int countLines, size_t rowBytes)
 
bool skipScanlines (int countLines)
 
SkScanlineOrder getScanlineOrder () const
 
int nextScanline () const
 
int outputScanline (int inputScanline) const
 
int getFrameCount ()
 
bool getFrameInfo (int index, FrameInfo *info) const
 
std::vector< FrameInfogetFrameInfo ()
 
int getRepetitionCount ()
 
- Static Public Attributes inherited from SkCodec
static constexpr int kNoFrame = -1
 
static constexpr int kRepetitionCountInfinite = -1
 
- Protected Types inherited from SkCodec
using XformFormat = skcms_PixelFormat
 

Detailed Description

Definition at line 35 of file SkWebpCodec.h.

Member Function Documentation

◆ getFrameHolder()

const SkFrameHolder * SkWebpCodec::getFrameHolder ( ) const
inlineoverrideprotectedvirtual

For multi-framed images, return the object with information about the frames.

Reimplemented from SkCodec.

Definition at line 50 of file SkWebpCodec.h.

50 {
51 return &fFrameHolder;
52 }

◆ IsWebp()

bool SkWebpCodec::IsWebp ( const void *  buf,
size_t  bytesRead 
)
static

Definition at line 50 of file SkWebpCodec.cpp.

50 {
51 // WEBP starts with the following:
52 // RIFFXXXXWEBPVP
53 // Where XXXX is unspecified.
54 const char* bytes = static_cast<const char*>(buf);
55 return bytesRead >= 14 && !memcmp(bytes, "RIFF", 4) && !memcmp(&bytes[8], "WEBPVP", 6);
56}

◆ MakeFromStream()

std::unique_ptr< SkCodec > SkWebpCodec::MakeFromStream ( std::unique_ptr< SkStream stream,
Result result 
)
static

Definition at line 60 of file SkWebpCodec.cpp.

61 {
63 if (!stream) {
65 return nullptr;
66 }
67 // Webp demux needs a contiguous data buffer.
68 sk_sp<SkData> data = nullptr;
69 if (stream->getMemoryBase()) {
70 // It is safe to make without copy because we'll hold onto the stream.
72 } else {
74
75 // If we are forced to copy the stream to a data, we can go ahead and delete the stream.
76 stream.reset(nullptr);
77 }
78
79 // It's a little strange that the |demux| will outlive |webpData|, though it needs the
80 // pointer in |webpData| to remain valid. This works because the pointer remains valid
81 // until the SkData is freed.
82 WebPData webpData = { data->bytes(), data->size() };
83 WebPDemuxState state;
84 SkAutoTCallVProc<WebPDemuxer, WebPDemuxDelete> demux(WebPDemuxPartial(&webpData, &state));
85 switch (state) {
86 case WEBP_DEMUX_PARSE_ERROR:
88 return nullptr;
89 case WEBP_DEMUX_PARSING_HEADER:
91 return nullptr;
92 case WEBP_DEMUX_PARSED_HEADER:
93 case WEBP_DEMUX_DONE:
94 SkASSERT(demux);
95 break;
96 }
97
98 const int width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH);
99 const int height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT);
100
101 // Validate the image size that's about to be decoded.
102 {
103 const int64_t size = sk_64_mul(width, height);
104 // now check that if we are 4-bytes per pixel, we also don't overflow
105 if (!SkTFitsIn<int32_t>(size) || SkTo<int32_t>(size) > (0x7FFFFFFF >> 2)) {
107 return nullptr;
108 }
109 }
110
111 std::unique_ptr<SkEncodedInfo::ICCProfile> profile = nullptr;
112 {
113 WebPChunkIterator chunkIterator;
115 if (WebPDemuxGetChunk(demux, "ICCP", 1, &chunkIterator)) {
116 // FIXME: I think this could be MakeWithoutCopy
117 auto chunk = SkData::MakeWithCopy(chunkIterator.chunk.bytes, chunkIterator.chunk.size);
118 profile = SkEncodedInfo::ICCProfile::Make(std::move(chunk));
119 }
120 if (profile && profile->profile()->data_color_space != skcms_Signature_RGB) {
121 profile = nullptr;
122 }
123 }
124
126 {
127 WebPChunkIterator chunkIterator;
129 if (WebPDemuxGetChunk(demux, "EXIF", 1, &chunkIterator)) {
130 SkParseEncodedOrigin(chunkIterator.chunk.bytes, chunkIterator.chunk.size, &origin);
131 }
132 }
133
134 // Get the first frame and its "features" to determine the color and alpha types.
135 WebPIterator frame;
137 if (!WebPDemuxGetFrame(demux, 1, &frame)) {
139 return nullptr;
140 }
141
142 WebPBitstreamFeatures features;
143 switch (WebPGetFeatures(frame.fragment.bytes, frame.fragment.size, &features)) {
144 case VP8_STATUS_OK:
145 break;
146 case VP8_STATUS_SUSPENDED:
147 case VP8_STATUS_NOT_ENOUGH_DATA:
149 return nullptr;
150 default:
152 return nullptr;
153 }
154
155 const bool hasAlpha = SkToBool(frame.has_alpha)
156 || frame.width != width || frame.height != height;
159 switch (features.format) {
160 case 0:
161 // This indicates a "mixed" format. We could see this for
162 // animated webps (multiple fragments).
163 // We could also guess kYUV here, but I think it makes more
164 // sense to guess kBGRA which is likely closer to the final
165 // output. Otherwise, we might end up converting
166 // BGRA->YUVA->BGRA.
167 [[fallthrough]];
168 case 2:
169 // This is the lossless format (BGRA).
170 if (hasAlpha) {
173 } else {
176 }
177 break;
178 case 1:
179 // This is the lossy format (YUV).
180 if (hasAlpha) {
183 } else {
186 }
187 break;
188 default:
190 return nullptr;
191 }
192
193
194 *result = kSuccess;
195 SkEncodedInfo info = SkEncodedInfo::Make(width, height, color, alpha, 8, std::move(profile));
196 return std::unique_ptr<SkCodec>(new SkWebpCodec(std::move(info), std::move(stream),
197 demux.release(), std::move(data), origin));
198}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
SkColor4f color
#define SkASSERT(cond)
Definition SkAssert.h:116
SkEncodedOrigin
@ kDefault_SkEncodedOrigin
static int64_t sk_64_mul(int64_t a, int64_t b)
Definition SkMath.h:33
bool SkParseEncodedOrigin(const void *data, size_t data_length, SkEncodedOrigin *orientation)
sk_sp< SkData > SkCopyStreamToData(SkStream *stream)
Definition SkStream.cpp:937
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
SkStream * stream()
Definition SkCodec.h:865
@ kIncompleteInput
Definition SkCodec.h:84
@ kInvalidInput
Definition SkCodec.h:109
@ kSuccess
Definition SkCodec.h:80
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
Definition SkData.h:116
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
Definition SkData.cpp:111
static std::unique_ptr< ICCProfile > Make(sk_sp< SkData >)
virtual size_t getLength() const
Definition SkStream.h:137
virtual const void * getMemoryBase()
Definition SkStream.h:141
double frame
Definition examples.cpp:31
AtkStateType state
GAsyncResult * result
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
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
int32_t height
int32_t width
@ skcms_Signature_RGB
static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha, int bitsPerComponent)

◆ onGetEncodedFormat()

SkEncodedImageFormat SkWebpCodec::onGetEncodedFormat ( ) const
inlineoverrideprotectedvirtual

Implements SkCodec.

Definition at line 42 of file SkWebpCodec.h.

◆ onGetFrameCount()

int SkWebpCodec::onGetFrameCount ( )
overrideprotectedvirtual

Reimplemented from SkCodec.

Definition at line 252 of file SkWebpCodec.cpp.

252 {
253 auto flags = WebPDemuxGetI(fDemux.get(), WEBP_FF_FORMAT_FLAGS);
254 if (!(flags & ANIMATION_FLAG)) {
255 return 1;
256 }
257
258 const uint32_t oldFrameCount = fFrameHolder.size();
259 if (fFailed) {
260 return oldFrameCount;
261 }
262
263 const uint32_t frameCount = WebPDemuxGetI(fDemux, WEBP_FF_FRAME_COUNT);
264 if (oldFrameCount == frameCount) {
265 // We have already parsed this.
266 return frameCount;
267 }
268
269 fFrameHolder.reserve(frameCount);
270
271 for (uint32_t i = oldFrameCount; i < frameCount; i++) {
272 WebPIterator iter;
274
275 if (!WebPDemuxGetFrame(fDemux.get(), i + 1, &iter)) {
276 fFailed = true;
277 break;
278 }
279
280 // libwebp only reports complete frames of an animated image.
281 SkASSERT(iter.complete);
282
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) {
291 }
292 fFrameHolder.setAlphaAndRequiredFrame(frame);
293 }
294
295 return fFrameHolder.size();
296
297}
FlutterSemanticsFlag flags

◆ onGetFrameInfo()

bool SkWebpCodec::onGetFrameInfo ( int  i,
FrameInfo frameInfo 
) const
overrideprotectedvirtual

Reimplemented from SkCodec.

Definition at line 308 of file SkWebpCodec.cpp.

308 {
309 if (i >= fFrameHolder.size()) {
310 return false;
311 }
312
313 const Frame* frame = fFrameHolder.frame(i);
314 if (!frame) {
315 return false;
316 }
317
318 if (frameInfo) {
319 // libwebp only reports fully received frames for an
320 // animated image.
321 frame->fillIn(frameInfo, true);
322 }
323
324 return true;
325}

◆ onGetPixels()

SkCodec::Result SkWebpCodec::onGetPixels ( const SkImageInfo info,
void *  pixels,
size_t  rowBytes,
const Options ,
int rowsDecoded 
)
overrideprotectedvirtual
Parameters
rowsDecodedWhen the encoded image stream is incomplete, this function will return kIncompleteInput and rowsDecoded will be set to the number of scanlines that were successfully decoded. This will allow getPixels() to fill the uninitialized memory.

Implements SkCodec.

Definition at line 368 of file SkWebpCodec.cpp.

369 {
370 const int index = options.fFrameIndex;
371 SkASSERT(0 == index || index < fFrameHolder.size());
372 SkASSERT(0 == index || !options.fSubset);
373
374 WebPDecoderConfig config;
375 if (0 == WebPInitDecoderConfig(&config)) {
376 // ABI mismatch.
377 // FIXME: New enum for this?
378 return kInvalidInput;
379 }
380
381 // Free any memory associated with the buffer. Must be called last, so we declare it first.
383
384 WebPIterator frame;
386 // If this succeeded in onGetFrameCount(), it should succeed again here.
387 SkAssertResult(WebPDemuxGetFrame(fDemux, index + 1, &frame));
388
389 const bool independent = index == 0 ? true :
390 (fFrameHolder.frame(index)->getRequiredFrame() == kNoFrame);
391 // Get the frameRect. libwebp will have already signaled an error if this is not fully
392 // contained by the canvas.
393 auto frameRect = SkIRect::MakeXYWH(frame.x_offset, frame.y_offset, frame.width, frame.height);
394 SkASSERT(this->bounds().contains(frameRect));
395 const bool frameIsSubset = frameRect != this->bounds();
396 if (independent && frameIsSubset) {
398 }
399
400 int dstX = frameRect.x();
401 int dstY = frameRect.y();
402 int subsetWidth = frameRect.width();
403 int subsetHeight = frameRect.height();
404 if (options.fSubset) {
405 SkIRect subset = *options.fSubset;
406 SkASSERT(this->bounds().contains(subset));
407 SkASSERT(SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTop));
408 SkASSERT(this->getValidSubset(&subset) && subset == *options.fSubset);
409
410 if (!SkIRect::Intersects(subset, frameRect)) {
411 return kSuccess;
412 }
413
414 int minXOffset = std::min(dstX, subset.x());
415 int minYOffset = std::min(dstY, subset.y());
416 dstX -= minXOffset;
417 dstY -= minYOffset;
418 frameRect.offset(-minXOffset, -minYOffset);
419 subset.offset(-minXOffset, -minYOffset);
420
421 // Just like we require that the requested subset x and y offset are even, libwebp
422 // guarantees that the frame x and y offset are even (it's actually impossible to specify
423 // an odd frame offset). So we can still guarantee that the adjusted offsets are even.
424 SkASSERT(SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTop));
425
426 SkIRect intersection;
427 SkAssertResult(intersection.intersect(frameRect, subset));
428 subsetWidth = intersection.width();
429 subsetHeight = intersection.height();
430
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;
436 }
437
438 // Ignore the frame size and offset when determining if scaling is necessary.
439 int scaledWidth = subsetWidth;
440 int scaledHeight = subsetHeight;
441 SkISize srcSize = options.fSubset ? options.fSubset->size() : this->dimensions();
442 if (srcSize != dstInfo.dimensions()) {
443 config.options.use_scaling = 1;
444
445 if (frameIsSubset) {
446 float scaleX = ((float) dstInfo.width()) / srcSize.width();
447 float scaleY = ((float) dstInfo.height()) / srcSize.height();
448
449 // We need to be conservative here and floor rather than round.
450 // Otherwise, we may find ourselves decoding off the end of memory.
451 dstX = scaleX * dstX;
452 scaledWidth = scaleX * scaledWidth;
453 dstY = scaleY * dstY;
454 scaledHeight = scaleY * scaledHeight;
455 if (0 == scaledWidth || 0 == scaledHeight) {
456 return kSuccess;
457 }
458 } else {
459 scaledWidth = dstInfo.width();
460 scaledHeight = dstInfo.height();
461 }
462
463 config.options.scaled_width = scaledWidth;
464 config.options.scaled_height = scaledHeight;
465 }
466
467 const bool blendWithPrevFrame = !independent && frame.blend_method == WEBP_MUX_BLEND
468 && frame.has_alpha;
469
470 auto webpInfo = dstInfo;
471 if (!frame.has_alpha) {
472 webpInfo = webpInfo.makeAlphaType(kOpaque_SkAlphaType);
473 } else if (this->colorXform() || blendWithPrevFrame) {
474 // the colorXform and blend_line expect unpremul.
475 webpInfo = webpInfo.makeAlphaType(kUnpremul_SkAlphaType);
476 }
477 if (this->colorXform()) {
478 // Swizzling between RGBA and BGRA is zero cost in a color transform. So when we have a
479 // color transform, we should decode to whatever is easiest for libwebp, and then let the
480 // color transform swizzle if necessary.
481 // Lossy webp is encoded as YUV (so RGBA and BGRA are the same cost). Lossless webp is
482 // encoded as BGRA. This means decoding to BGRA is either faster or the same cost as RGBA.
483 webpInfo = webpInfo.makeColorType(kBGRA_8888_SkColorType);
484 }
485
486 SkBitmap webpDst;
487 if ((this->colorXform() && !is_8888(dstInfo.colorType())) || blendWithPrevFrame) {
488 // We will decode the entire image and then perform the color transform. libwebp
489 // does not provide a row-by-row API. This is a shame particularly when we do not want
490 // 8888, since we will need to create another image sized buffer.
491 webpDst.allocPixels(webpInfo);
492 } else {
493 // libwebp can decode directly into the output memory.
494 webpDst.installPixels(webpInfo, dst, rowBytes);
495 }
496
497 config.output.colorspace = webp_decode_mode(webpInfo.colorType(),
498 webpInfo.alphaType() == kPremul_SkAlphaType);
499 config.output.is_external_memory = 1;
500
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());
503 config.output.u.RGBA.size = webpDst.computeByteSize();
504
505 SkAutoTCallVProc<WebPIDecoder, WebPIDelete> idec(WebPIDecode(nullptr, 0, &config));
506 if (!idec) {
507 return kInvalidInput;
508 }
509
510 int rowsDecoded = 0;
512 switch (WebPIUpdate(idec, frame.fragment.bytes, frame.fragment.size)) {
513 case VP8_STATUS_OK:
514 rowsDecoded = scaledHeight;
516 break;
517 case VP8_STATUS_SUSPENDED:
518 if (!WebPIDecGetRGB(idec, &rowsDecoded, nullptr, nullptr, nullptr)
519 || rowsDecoded <= 0) {
520 return kInvalidInput;
521 }
522 *rowsDecodedPtr = rowsDecoded + dstY;
524 break;
525 default:
526 return kInvalidInput;
527 }
528
529 const size_t dstBpp = dstInfo.bytesPerPixel();
530 dst = SkTAddOffset<void>(dst, dstBpp * dstX + rowBytes * dstY);
531 const size_t srcRowBytes = config.output.u.RGBA.stride;
532
533 const auto dstCT = dstInfo.colorType();
534 if (this->colorXform()) {
535 uint32_t* xformSrc = (uint32_t*) config.output.u.RGBA.rgba;
536 SkBitmap tmp;
537 void* xformDst;
538
539 if (blendWithPrevFrame) {
540 // Xform into temporary bitmap big enough for one row.
541 tmp.allocPixels(dstInfo.makeWH(scaledWidth, 1));
542 xformDst = tmp.getPixels();
543 } else {
544 xformDst = dst;
545 }
546
547 for (int y = 0; y < rowsDecoded; y++) {
548 this->applyColorXform(xformDst, xformSrc, scaledWidth);
549 if (blendWithPrevFrame) {
550 blend_line(dstCT, dst, dstCT, xformDst,
551 dstInfo.alphaType(), frame.has_alpha, scaledWidth);
552 dst = SkTAddOffset<void>(dst, rowBytes);
553 } else {
554 xformDst = SkTAddOffset<void>(xformDst, rowBytes);
555 }
556 xformSrc = SkTAddOffset<uint32_t>(xformSrc, srcRowBytes);
557 }
558 } else if (blendWithPrevFrame) {
559 const uint8_t* src = config.output.u.RGBA.rgba;
560
561 for (int y = 0; y < rowsDecoded; y++) {
562 blend_line(dstCT, dst, webpDst.colorType(), src,
563 dstInfo.alphaType(), frame.has_alpha, scaledWidth);
564 src = SkTAddOffset<const uint8_t>(src, srcRowBytes);
565 dst = SkTAddOffset<void>(dst, rowBytes);
566 }
567 }
568
569 return result;
570}
kUnpremul_SkAlphaType
static constexpr bool SkIsAlign2(T x)
Definition SkAlign.h:19
@ kOpaque_SkAlphaType
pixel is opaque
Definition SkAlphaType.h:28
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkAssertResult(cond)
Definition SkAssert.h:123
static bool independent(const SkFrame &frame)
Definition SkCodec.cpp:922
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition SkColorType.h:26
static bool contains(const SkRect &r, SkPoint p)
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)
void allocPixels(const SkImageInfo &info, size_t rowBytes)
Definition SkBitmap.cpp:258
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
Definition SkBitmap.cpp:323
size_t computeByteSize() const
Definition SkBitmap.h:293
void * getAddr(int x, int y) const
Definition SkBitmap.cpp:406
size_t rowBytes() const
Definition SkBitmap.h:238
SkColorType colorType() const
Definition SkBitmap.h:160
void * getPixels() const
Definition SkBitmap.h:283
bool getValidSubset(SkIRect *desiredSubset) const
Definition SkCodec.h:285
SkISize dimensions() const
Definition SkCodec.h:230
const SkImageInfo & dstInfo() const
Definition SkCodec.h:878
void applyColorXform(void *dst, const void *src, int count) const
Definition SkCodec.cpp:853
SkIRect bounds() const
Definition SkCodec.h:231
bool colorXform() const
Definition SkCodec.h:906
static constexpr int kNoFrame
Definition SkCodec.h:650
const Options & options() const
Definition SkCodec.h:880
static void Fill(const SkImageInfo &info, void *dst, size_t rowBytes, SkCodec::ZeroInitialized zeroInit)
Definition SkSampler.cpp:20
double y
dst
Definition cp.py:12
const SkIRect * fSubset
Definition SkCodec.h:347
ZeroInitialized fZeroInitialized
Definition SkCodec.h:329
constexpr int32_t x() const
Definition SkRect.h:141
constexpr int32_t y() const
Definition SkRect.h:148
bool intersect(const SkIRect &r)
Definition SkRect.h:513
static bool Intersects(const SkIRect &a, const SkIRect &b)
Definition SkRect.h:535
constexpr SkISize size() const
Definition SkRect.h:172
constexpr int32_t height() const
Definition SkRect.h:165
int32_t fTop
smaller y-axis bounds
Definition SkRect.h:34
constexpr int32_t width() const
Definition SkRect.h:158
void offset(int32_t dx, int32_t dy)
Definition SkRect.h:367
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition SkRect.h:104
int32_t fLeft
smaller x-axis bounds
Definition SkRect.h:33
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
SkImageInfo makeWH(int newWidth, int newHeight) const
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const
int bytesPerPixel() const
SkISize dimensions() const
int width() const
SkAlphaType alphaType() const
SkColorType colorType() const
int height() const
SkImageInfo makeColorType(SkColorType newColorType) const

◆ onGetRepetitionCount()

int SkWebpCodec::onGetRepetitionCount ( )
overrideprotectedvirtual

Reimplemented from SkCodec.

Definition at line 237 of file SkWebpCodec.cpp.

237 {
238 auto flags = WebPDemuxGetI(fDemux.get(), WEBP_FF_FORMAT_FLAGS);
239 if (!(flags & ANIMATION_FLAG)) {
240 return 0;
241 }
242
243 int loopCount = WebPDemuxGetI(fDemux.get(), WEBP_FF_LOOP_COUNT);
244 if (0 == loopCount) {
246 }
247
248 loopCount--;
249 return loopCount;
250}
static constexpr int kRepetitionCountInfinite
Definition SkCodec.h:759

◆ onGetValidSubset()

bool SkWebpCodec::onGetValidSubset ( SkIRect desiredSubset) const
overrideprotectedvirtual

Reimplemented from SkCodec.

Definition at line 220 of file SkWebpCodec.cpp.

220 {
221 if (!desiredSubset) {
222 return false;
223 }
224
225 if (!this->bounds().contains(*desiredSubset)) {
226 return false;
227 }
228
229 // As stated below, libwebp snaps to even left and top. Make sure top and left are even, so we
230 // decode this exact subset.
231 // Leave right and bottom unmodified, so we suggest a slightly larger subset than requested.
232 desiredSubset->fLeft = (desiredSubset->fLeft >> 1) << 1;
233 desiredSubset->fTop = (desiredSubset->fTop >> 1) << 1;
234 return true;
235}

The documentation for this class was generated from the following files: