• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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  */
7 
8 #ifndef SkCodec_DEFINED
9 #define SkCodec_DEFINED
10 
11 #include "include/codec/SkCodecAnimation.h"
12 #include "include/codec/SkEncodedOrigin.h"
13 #include "include/core/SkColor.h"
14 #include "include/core/SkEncodedImageFormat.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkPixmap.h"
17 #include "include/core/SkSize.h"
18 #include "include/core/SkStream.h"
19 #include "include/core/SkTypes.h"
20 #include "include/core/SkYUVAPixmaps.h"
21 #include "include/private/SkEncodedInfo.h"
22 #include "include/private/SkNoncopyable.h"
23 #include "include/private/SkTemplates.h"
24 
25 #include <vector>
26 #ifdef SK_ENABLE_OHOS_CODEC
27 #include <functional>
28 #endif
29 
30 class SkAndroidCodec;
31 class SkColorSpace;
32 class SkData;
33 class SkFrameHolder;
34 class SkImage;
35 class SkPngChunkReader;
36 class SkSampler;
37 
38 namespace DM {
39 class CodecSrc;
40 class ColorCodecSrc;
41 } // namespace DM
42 
43 /**
44  *  Abstraction layer directly on top of an image codec.
45  */
46 class SK_API SkCodec : SkNoncopyable {
47 public:
48     /**
49      *  Minimum number of bytes that must be buffered in SkStream input.
50      *
51      *  An SkStream passed to NewFromStream must be able to use this many
52      *  bytes to determine the image type. Then the same SkStream must be
53      *  passed to the correct decoder to read from the beginning.
54      *
55      *  This can be accomplished by implementing peek() to support peeking
56      *  this many bytes, or by implementing rewind() to be able to rewind()
57      *  after reading this many bytes.
58      */
MinBufferedBytesNeeded()59     static constexpr size_t MinBufferedBytesNeeded() { return 32; }
60 
61     /**
62      *  Error codes for various SkCodec methods.
63      */
64     enum Result {
65         /**
66          *  General return value for success.
67          */
68         kSuccess,
69         /**
70          *  The input is incomplete. A partial image was generated.
71          */
72         kIncompleteInput,
73         /**
74          *  Like kIncompleteInput, except the input had an error.
75          *
76          *  If returned from an incremental decode, decoding cannot continue,
77          *  even with more data.
78          */
79         kErrorInInput,
80         /**
81          *  The generator cannot convert to match the request, ignoring
82          *  dimensions.
83          */
84         kInvalidConversion,
85         /**
86          *  The generator cannot scale to requested size.
87          */
88         kInvalidScale,
89         /**
90          *  Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
91          *  too small, etc.
92          */
93         kInvalidParameters,
94         /**
95          *  The input did not contain a valid image.
96          */
97         kInvalidInput,
98         /**
99          *  Fulfilling this request requires rewinding the input, which is not
100          *  supported for this input.
101          */
102         kCouldNotRewind,
103         /**
104          *  An internal error, such as OOM.
105          */
106         kInternalError,
107         /**
108          *  This method is not implemented by this codec.
109          *  FIXME: Perhaps this should be kUnsupported?
110          */
111         kUnimplemented,
112     };
113 
114     /**
115      *  Readable string representing the error code.
116      */
117     static const char* ResultToString(Result);
118 
119     /**
120      * For container formats that contain both still images and image sequences,
121      * instruct the decoder how the output should be selected. (Refer to comments
122      * for each value for more details.)
123      */
124     enum class SelectionPolicy {
125         /**
126          *  If the container format contains both still images and image sequences,
127          *  SkCodec should choose one of the still images. This is the default.
128          */
129         kPreferStillImage,
130         /**
131          *  If the container format contains both still images and image sequences,
132          *  SkCodec should choose one of the image sequences for animation.
133          */
134         kPreferAnimation,
135     };
136 
137     /**
138      *  If this stream represents an encoded image that we know how to decode,
139      *  return an SkCodec that can decode it. Otherwise return NULL.
140      *
141      *  As stated above, this call must be able to peek or read
142      *  MinBufferedBytesNeeded to determine the correct format, and then start
143      *  reading from the beginning. First it will attempt to peek, and it
144      *  assumes that if less than MinBufferedBytesNeeded bytes (but more than
145      *  zero) are returned, this is because the stream is shorter than this,
146      *  so falling back to reading would not provide more data. If peek()
147      *  returns zero bytes, this call will instead attempt to read(). This
148      *  will require that the stream can be rewind()ed.
149      *
150      *  If Result is not NULL, it will be set to either kSuccess if an SkCodec
151      *  is returned or a reason for the failure if NULL is returned.
152      *
153      *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
154      *  the image is a png.
155      *
156      *  If the SkPngChunkReader is not NULL then:
157      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
158      *      If the image is a PNG, the SkPngChunkReader will be reffed.
159      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
160      *      to handle these chunks.  SkPngChunkReader will be called to read
161      *      any unknown chunk at any point during the creation of the codec
162      *      or the decode.  Note that if SkPngChunkReader fails to read a
163      *      chunk, this could result in a failure to create the codec or a
164      *      failure to decode the image.
165      *      If the PNG does not contain unknown chunks, the SkPngChunkReader
166      *      will not be used or modified.
167      *
168      *  If NULL is returned, the stream is deleted immediately. Otherwise, the
169      *  SkCodec takes ownership of it, and will delete it when done with it.
170      */
171     static std::unique_ptr<SkCodec> MakeFromStream(
172             std::unique_ptr<SkStream>, Result* = nullptr,
173             SkPngChunkReader* = nullptr,
174             SelectionPolicy selectionPolicy = SelectionPolicy::kPreferStillImage);
175 
176     /**
177      *  If this data represents an encoded image that we know how to decode,
178      *  return an SkCodec that can decode it. Otherwise return NULL.
179      *
180      *  If the SkPngChunkReader is not NULL then:
181      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
182      *      If the image is a PNG, the SkPngChunkReader will be reffed.
183      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
184      *      to handle these chunks.  SkPngChunkReader will be called to read
185      *      any unknown chunk at any point during the creation of the codec
186      *      or the decode.  Note that if SkPngChunkReader fails to read a
187      *      chunk, this could result in a failure to create the codec or a
188      *      failure to decode the image.
189      *      If the PNG does not contain unknown chunks, the SkPngChunkReader
190      *      will not be used or modified.
191      */
192     static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
193 
194     virtual ~SkCodec();
195 
196     /**
197      *  Return a reasonable SkImageInfo to decode into.
198      *
199      *  If the image has an ICC profile that does not map to an SkColorSpace,
200      *  the returned SkImageInfo will use SRGB.
201      */
getInfo()202     SkImageInfo getInfo() const { return fEncodedInfo.makeImageInfo(); }
203 
dimensions()204     SkISize dimensions() const { return {fEncodedInfo.width(), fEncodedInfo.height()}; }
bounds()205     SkIRect bounds() const {
206         return SkIRect::MakeWH(fEncodedInfo.width(), fEncodedInfo.height());
207     }
208 
209     /**
210      * Return the ICC profile of the encoded data.
211      */
getICCProfile()212     const skcms_ICCProfile* getICCProfile() const {
213         return this->getEncodedInfo().profile();
214     }
215 
216     /**
217      *  Returns the image orientation stored in the EXIF data.
218      *  If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft.
219      */
getOrigin()220     SkEncodedOrigin getOrigin() const { return fOrigin; }
221 
222     /**
223      *  Return a size that approximately supports the desired scale factor.
224      *  The codec may not be able to scale efficiently to the exact scale
225      *  factor requested, so return a size that approximates that scale.
226      *  The returned value is the codec's suggestion for the closest valid
227      *  scale that it can natively support
228      */
getScaledDimensions(float desiredScale)229     SkISize getScaledDimensions(float desiredScale) const {
230         // Negative and zero scales are errors.
231         SkASSERT(desiredScale > 0.0f);
232         if (desiredScale <= 0.0f) {
233             return SkISize::Make(0, 0);
234         }
235 
236         // Upscaling is not supported. Return the original size if the client
237         // requests an upscale.
238         if (desiredScale >= 1.0f) {
239             return this->dimensions();
240         }
241         return this->onGetScaledDimensions(desiredScale);
242     }
243 
244     /**
245      *  Return (via desiredSubset) a subset which can decoded from this codec,
246      *  or false if this codec cannot decode subsets or anything similar to
247      *  desiredSubset.
248      *
249      *  @param desiredSubset In/out parameter. As input, a desired subset of
250      *      the original bounds (as specified by getInfo). If true is returned,
251      *      desiredSubset may have been modified to a subset which is
252      *      supported. Although a particular change may have been made to
253      *      desiredSubset to create something supported, it is possible other
254      *      changes could result in a valid subset.
255      *      If false is returned, desiredSubset's value is undefined.
256      *  @return true if this codec supports decoding desiredSubset (as
257      *      returned, potentially modified)
258      */
getValidSubset(SkIRect * desiredSubset)259     bool getValidSubset(SkIRect* desiredSubset) const {
260         return this->onGetValidSubset(desiredSubset);
261     }
262 
263     /**
264      *  Format of the encoded data.
265      */
getEncodedFormat()266     SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
267 
268     /**
269      *  Whether or not the memory passed to getPixels is zero initialized.
270      */
271     enum ZeroInitialized {
272         /**
273          *  The memory passed to getPixels is zero initialized. The SkCodec
274          *  may take advantage of this by skipping writing zeroes.
275          */
276         kYes_ZeroInitialized,
277         /**
278          *  The memory passed to getPixels has not been initialized to zero,
279          *  so the SkCodec must write all zeroes to memory.
280          *
281          *  This is the default. It will be used if no Options struct is used.
282          */
283         kNo_ZeroInitialized,
284     };
285 
286     /**
287      *  Additional options to pass to getPixels.
288      */
289     struct Options {
OptionsOptions290         Options()
291             : fZeroInitialized(kNo_ZeroInitialized)
292             , fSubset(nullptr)
293             , fFrameIndex(0)
294             , fPriorFrame(kNoFrame)
295         {}
296 
297         ZeroInitialized            fZeroInitialized;
298         /**
299          *  If not NULL, represents a subset of the original image to decode.
300          *  Must be within the bounds returned by getInfo().
301          *  If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which
302          *  currently supports subsets), the top and left values must be even.
303          *
304          *  In getPixels and incremental decode, we will attempt to decode the
305          *  exact rectangular subset specified by fSubset.
306          *
307          *  In a scanline decode, it does not make sense to specify a subset
308          *  top or subset height, since the client already controls which rows
309          *  to get and which rows to skip.  During scanline decodes, we will
310          *  require that the subset top be zero and the subset height be equal
311          *  to the full height.  We will, however, use the values of
312          *  subset left and subset width to decode partial scanlines on calls
313          *  to getScanlines().
314          */
315         const SkIRect*             fSubset;
316 
317         /**
318          *  The frame to decode.
319          *
320          *  Only meaningful for multi-frame images.
321          */
322         int                        fFrameIndex;
323 
324         /**
325          *  If not kNoFrame, the dst already contains the prior frame at this index.
326          *
327          *  Only meaningful for multi-frame images.
328          *
329          *  If fFrameIndex needs to be blended with a prior frame (as reported by
330          *  getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to
331          *  any non-kRestorePrevious frame in [fRequiredFrame, fFrameIndex) to
332          *  indicate that that frame is already in the dst. Options.fZeroInitialized
333          *  is ignored in this case.
334          *
335          *  If set to kNoFrame, the codec will decode any necessary required frame(s) first.
336          */
337         int                        fPriorFrame;
338     };
339 
340     /**
341      *  Decode into the given pixels, a block of memory of size at
342      *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
343      *  bytesPerPixel)
344      *
345      *  Repeated calls to this function should give the same results,
346      *  allowing the PixelRef to be immutable.
347      *
348      *  @param info A description of the format (config, size)
349      *         expected by the caller.  This can simply be identical
350      *         to the info returned by getInfo().
351      *
352      *         This contract also allows the caller to specify
353      *         different output-configs, which the implementation can
354      *         decide to support or not.
355      *
356      *         A size that does not match getInfo() implies a request
357      *         to scale. If the generator cannot perform this scale,
358      *         it will return kInvalidScale.
359      *
360      *         If the info contains a non-null SkColorSpace, the codec
361      *         will perform the appropriate color space transformation.
362      *
363      *         If the caller passes in the SkColorSpace that maps to the
364      *         ICC profile reported by getICCProfile(), the color space
365      *         transformation is a no-op.
366      *
367      *         If the caller passes a null SkColorSpace, no color space
368      *         transformation will be done.
369      *
370      *  If a scanline decode is in progress, scanline mode will end, requiring the client to call
371      *  startScanlineDecode() in order to return to decoding scanlines.
372      *
373      *  @return Result kSuccess, or another value explaining the type of failure.
374      */
375     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*);
376 
377     /**
378      *  Simplified version of getPixels() that uses the default Options.
379      */
getPixels(const SkImageInfo & info,void * pixels,size_t rowBytes)380     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
381         return this->getPixels(info, pixels, rowBytes, nullptr);
382     }
383 
384     Result getPixels(const SkPixmap& pm, const Options* opts = nullptr) {
385         return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts);
386     }
387 
388     /**
389      *  Return an image containing the pixels.
390      */
391     std::tuple<sk_sp<SkImage>, SkCodec::Result> getImage(const SkImageInfo& info,
392                                                          const Options* opts = nullptr);
393     std::tuple<sk_sp<SkImage>, SkCodec::Result> getImage();
394 
395     /**
396      *  If decoding to YUV is supported, this returns true. Otherwise, this
397      *  returns false and the caller will ignore output parameter yuvaPixmapInfo.
398      *
399      * @param  supportedDataTypes Indicates the data type/planar config combinations that are
400      *                            supported by the caller. If the generator supports decoding to
401      *                            YUV(A), but not as a type in supportedDataTypes, this method
402      *                            returns false.
403      *  @param yuvaPixmapInfo Output parameter that specifies the planar configuration, subsampling,
404      *                        orientation, chroma siting, plane color types, and row bytes.
405      */
406     bool queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
407                        SkYUVAPixmapInfo* yuvaPixmapInfo) const;
408 
409     /**
410      *  Returns kSuccess, or another value explaining the type of failure.
411      *  This always attempts to perform a full decode. To get the planar
412      *  configuration without decoding use queryYUVAInfo().
413      *
414      *  @param yuvaPixmaps  Contains preallocated pixmaps configured according to a successful call
415      *                      to queryYUVAInfo().
416      */
417     Result getYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps);
418 
419     /**
420      *  Prepare for an incremental decode with the specified options.
421      *
422      *  This may require a rewind.
423      *
424      *  If kIncompleteInput is returned, may be called again after more data has
425      *  been provided to the source SkStream.
426      *
427      *  @param dstInfo Info of the destination. If the dimensions do not match
428      *      those of getInfo, this implies a scale.
429      *  @param dst Memory to write to. Needs to be large enough to hold the subset,
430      *      if present, or the full image as described in dstInfo.
431      *  @param options Contains decoding options, including if memory is zero
432      *      initialized and whether to decode a subset.
433      *  @return Enum representing success or reason for failure.
434      */
435     Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
436             const Options*);
437 
startIncrementalDecode(const SkImageInfo & dstInfo,void * dst,size_t rowBytes)438     Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
439         return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr);
440     }
441 
442     /**
443      *  Start/continue the incremental decode.
444      *
445      *  Not valid to call before a call to startIncrementalDecode() returns
446      *  kSuccess.
447      *
448      *  If kIncompleteInput is returned, may be called again after more data has
449      *  been provided to the source SkStream.
450      *
451      *  Unlike getPixels and getScanlines, this does not do any filling. This is
452      *  left up to the caller, since they may be skipping lines or continuing the
453      *  decode later. In the latter case, they may choose to initialize all lines
454      *  first, or only initialize the remaining lines after the first call.
455      *
456      *  @param rowsDecoded Optional output variable returning the total number of
457      *      lines initialized. Only meaningful if this method returns kIncompleteInput.
458      *      Otherwise the implementation may not set it.
459      *      Note that some implementations may have initialized this many rows, but
460      *      not necessarily finished those rows (e.g. interlaced PNG). This may be
461      *      useful for determining what rows the client needs to initialize.
462      *  @return kSuccess if all lines requested in startIncrementalDecode have
463      *      been completely decoded. kIncompleteInput otherwise.
464      */
465     Result incrementalDecode(int* rowsDecoded = nullptr) {
466         if (!fStartedIncrementalDecode) {
467             return kInvalidParameters;
468         }
469         return this->onIncrementalDecode(rowsDecoded);
470     }
471 
472     /**
473      * The remaining functions revolve around decoding scanlines.
474      */
475 
476     /**
477      *  Prepare for a scanline decode with the specified options.
478      *
479      *  After this call, this class will be ready to decode the first scanline.
480      *
481      *  This must be called in order to call getScanlines or skipScanlines.
482      *
483      *  This may require rewinding the stream.
484      *
485      *  Not all SkCodecs support this.
486      *
487      *  @param dstInfo Info of the destination. If the dimensions do not match
488      *      those of getInfo, this implies a scale.
489      *  @param options Contains decoding options, including if memory is zero
490      *      initialized.
491      *  @return Enum representing success or reason for failure.
492      */
493     Result startScanlineDecode(const SkImageInfo& dstInfo, const Options* options);
494 
495     /**
496      *  Simplified version of startScanlineDecode() that uses the default Options.
497      */
startScanlineDecode(const SkImageInfo & dstInfo)498     Result startScanlineDecode(const SkImageInfo& dstInfo) {
499         return this->startScanlineDecode(dstInfo, nullptr);
500     }
501 
502     /**
503      *  Write the next countLines scanlines into dst.
504      *
505      *  Not valid to call before calling startScanlineDecode().
506      *
507      *  @param dst Must be non-null, and large enough to hold countLines
508      *      scanlines of size rowBytes.
509      *  @param countLines Number of lines to write.
510      *  @param rowBytes Number of bytes per row. Must be large enough to hold
511      *      a scanline based on the SkImageInfo used to create this object.
512      *  @return the number of lines successfully decoded.  If this value is
513      *      less than countLines, this will fill the remaining lines with a
514      *      default value.
515      */
516     int getScanlines(void* dst, int countLines, size_t rowBytes);
517 
518     /**
519      *  Skip count scanlines.
520      *
521      *  Not valid to call before calling startScanlineDecode().
522      *
523      *  The default version just calls onGetScanlines and discards the dst.
524      *  NOTE: If skipped lines are the only lines with alpha, this default
525      *  will make reallyHasAlpha return true, when it could have returned
526      *  false.
527      *
528      *  @return true if the scanlines were successfully skipped
529      *          false on failure, possible reasons for failure include:
530      *              An incomplete input image stream.
531      *              Calling this function before calling startScanlineDecode().
532      *              If countLines is less than zero or so large that it moves
533      *                  the current scanline past the end of the image.
534      */
535     bool skipScanlines(int countLines);
536 
537     /**
538      *  The order in which rows are output from the scanline decoder is not the
539      *  same for all variations of all image types.  This explains the possible
540      *  output row orderings.
541      */
542     enum SkScanlineOrder {
543         /*
544          * By far the most common, this indicates that the image can be decoded
545          * reliably using the scanline decoder, and that rows will be output in
546          * the logical order.
547          */
548         kTopDown_SkScanlineOrder,
549 
550         /*
551          * This indicates that the scanline decoder reliably outputs rows, but
552          * they will be returned in reverse order.  If the scanline format is
553          * kBottomUp, the nextScanline() API can be used to determine the actual
554          * y-coordinate of the next output row, but the client is not forced
555          * to take advantage of this, given that it's not too tough to keep
556          * track independently.
557          *
558          * For full image decodes, it is safe to get all of the scanlines at
559          * once, since the decoder will handle inverting the rows as it
560          * decodes.
561          *
562          * For subset decodes and sampling, it is simplest to get and skip
563          * scanlines one at a time, using the nextScanline() API.  It is
564          * possible to ask for larger chunks at a time, but this should be used
565          * with caution.  As with full image decodes, the decoder will handle
566          * inverting the requested rows, but rows will still be delivered
567          * starting from the bottom of the image.
568          *
569          * Upside down bmps are an example.
570          */
571         kBottomUp_SkScanlineOrder,
572     };
573 
574     /**
575      *  An enum representing the order in which scanlines will be returned by
576      *  the scanline decoder.
577      *
578      *  This is undefined before startScanlineDecode() is called.
579      */
getScanlineOrder()580     SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
581 
582     /**
583      *  Returns the y-coordinate of the next row to be returned by the scanline
584      *  decoder.
585      *
586      *  This will equal fCurrScanline, except in the case of strangely
587      *  encoded image types (bottom-up bmps).
588      *
589      *  Results are undefined when not in scanline decoding mode.
590      */
nextScanline()591     int nextScanline() const { return this->outputScanline(fCurrScanline); }
592 
593     /**
594      *  Returns the output y-coordinate of the row that corresponds to an input
595      *  y-coordinate.  The input y-coordinate represents where the scanline
596      *  is located in the encoded data.
597      *
598      *  This will equal inputScanline, except in the case of strangely
599      *  encoded image types (bottom-up bmps, interlaced gifs).
600      */
601     int outputScanline(int inputScanline) const;
602 
603     /**
604      *  Return the number of frames in the image.
605      *
606      *  May require reading through the stream.
607      */
getFrameCount()608     int getFrameCount() {
609         return this->onGetFrameCount();
610     }
611 
612     // Sentinel value used when a frame index implies "no frame":
613     // - FrameInfo::fRequiredFrame set to this value means the frame
614     //   is independent.
615     // - Options::fPriorFrame set to this value means no (relevant) prior frame
616     //   is residing in dst's memory.
617     static constexpr int kNoFrame = -1;
618 
619     // This transitional definition was added in August 2018, and will eventually be removed.
620 #ifdef SK_LEGACY_SKCODEC_NONE_ENUM
621     static constexpr int kNone = kNoFrame;
622 #endif
623 
624     /**
625      *  Information about individual frames in a multi-framed image.
626      */
627     struct FrameInfo {
628         /**
629          *  The frame that this frame needs to be blended with, or
630          *  kNoFrame if this frame is independent (so it can be
631          *  drawn over an uninitialized buffer).
632          *
633          *  Note that this is the *earliest* frame that can be used
634          *  for blending. Any frame from [fRequiredFrame, i) can be
635          *  used, unless its fDisposalMethod is kRestorePrevious.
636          */
637         int fRequiredFrame;
638 
639         /**
640          *  Number of milliseconds to show this frame.
641          */
642         int fDuration;
643 
644         /**
645          *  Whether the end marker for this frame is contained in the stream.
646          *
647          *  Note: this does not guarantee that an attempt to decode will be complete.
648          *  There could be an error in the stream.
649          */
650         bool fFullyReceived;
651 
652         /**
653          *  This is conservative; it will still return non-opaque if e.g. a
654          *  color index-based frame has a color with alpha but does not use it.
655          */
656         SkAlphaType fAlphaType;
657 
658         /**
659          *  Whether the updated rectangle contains alpha.
660          *
661          *  This is conservative; it will still be set to true if e.g. a color
662          *  index-based frame has a color with alpha but does not use it. In
663          *  addition, it may be set to true, even if the final frame, after
664          *  blending, is opaque.
665          */
666         bool fHasAlphaWithinBounds;
667 
668         /**
669          *  How this frame should be modified before decoding the next one.
670          */
671         SkCodecAnimation::DisposalMethod fDisposalMethod;
672 
673         /**
674          *  How this frame should blend with the prior frame.
675          */
676         SkCodecAnimation::Blend fBlend;
677 
678         /**
679          *  The rectangle updated by this frame.
680          *
681          *  It may be empty, if the frame does not change the image. It will
682          *  always be contained by SkCodec::dimensions().
683          */
684         SkIRect fFrameRect;
685     };
686 
687     /**
688      *  Return info about a single frame.
689      *
690      *  Only supported by multi-frame images. Does not read through the stream,
691      *  so it should be called after getFrameCount() to parse any frames that
692      *  have not already been parsed.
693      */
getFrameInfo(int index,FrameInfo * info)694     bool getFrameInfo(int index, FrameInfo* info) const {
695         if (index < 0) {
696             return false;
697         }
698         return this->onGetFrameInfo(index, info);
699     }
700 
701     /**
702      *  Return info about all the frames in the image.
703      *
704      *  May require reading through the stream to determine info about the
705      *  frames (including the count).
706      *
707      *  As such, future decoding calls may require a rewind.
708      *
709      *  For still (non-animated) image codecs, this will return an empty vector.
710      */
711     std::vector<FrameInfo> getFrameInfo();
712 
713     static constexpr int kRepetitionCountInfinite = -1;
714 
715     /**
716      *  Return the number of times to repeat, if this image is animated. This number does not
717      *  include the first play through of each frame. For example, a repetition count of 4 means
718      *  that each frame is played 5 times and then the animation stops.
719      *
720      *  It can return kRepetitionCountInfinite, a negative number, meaning that the animation
721      *  should loop forever.
722      *
723      *  May require reading the stream to find the repetition count.
724      *
725      *  As such, future decoding calls may require a rewind.
726      *
727      *  For still (non-animated) image codecs, this will return 0.
728      */
getRepetitionCount()729     int getRepetitionCount() {
730         return this->onGetRepetitionCount();
731     }
732 
getHeifContext()733     virtual void *getHeifContext() { return nullptr; }
734 
735     // Register a decoder at runtime by passing two function pointers:
736     //    - peek() to return true if the span of bytes appears to be your encoded format;
737     //    - make() to attempt to create an SkCodec from the given stream.
738     // Not thread safe.
739     static void Register(
740             bool                     (*peek)(const void*, size_t),
741             std::unique_ptr<SkCodec> (*make)(std::unique_ptr<SkStream>, SkCodec::Result*));
742 
743 #ifdef SK_ENABLE_OHOS_CODEC
callGetEncodedInfo()744     const SkEncodedInfo& callGetEncodedInfo() const { return this->getEncodedInfo(); }
745 
746     using GetPixelsCallback = std::function<Result(const SkImageInfo&, void* pixels,
747                                                    size_t rowBytes, const Options& opts,
748                                                    int frameIndex)>;
749 
750     /**
751      *  Check for a valid Options.fFrameIndex, and decode prior frames if necessary.
752      */
753     Result callHandleFrameIndex(const SkImageInfo& info, void* pixels, size_t rowBytes,
754                                 const Options& handleOptions, GetPixelsCallback = nullptr);
755 
756     /**
757      *  Return whether these dimensions are supported as a scale.
758      */
callDimensionsSupported(const SkISize & dim)759     bool callDimensionsSupported(const SkISize& dim) {
760         return this->dimensionsSupported(dim);
761     }
762 
763     /**
764      * This function is used to fill any uinitialized memory.
765      */
callFillIncompleteImage(const SkImageInfo & dstInfo,void * dst,size_t rowBytes,ZeroInitialized zeroInit,int linesRequested,int linesDecoded)766     void callFillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
767                                  ZeroInitialized zeroInit, int linesRequested, int linesDecoded) {
768         this->fillIncompleteImage(dstInfo, dst, rowBytes, zeroInit, linesRequested, linesDecoded);
769     }
770 
771     /**
772      *  Return an object which can used to force scanline decodes to sample in X.
773      */
callGetSampler(bool flag)774     SkSampler* callGetSampler(bool flag) { return this->getSampler(flag); }
775 #endif
776 
777 protected:
getEncodedInfo()778     const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }
779 
780     using XformFormat = skcms_PixelFormat;
781 
782     SkCodec(SkEncodedInfo&&,
783             XformFormat srcFormat,
784             std::unique_ptr<SkStream>,
785             SkEncodedOrigin = kTopLeft_SkEncodedOrigin);
786 
onGetScaledDimensions(float)787     virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
788         // By default, scaling is not supported.
789         return this->dimensions();
790     }
791 
792     // FIXME: What to do about subsets??
793     /**
794      *  Subclasses should override if they support dimensions other than the
795      *  srcInfo's.
796      */
onDimensionsSupported(const SkISize &)797     virtual bool onDimensionsSupported(const SkISize&) {
798         return false;
799     }
800 
801     virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;
802 
803     /**
804      * @param rowsDecoded When the encoded image stream is incomplete, this function
805      *                    will return kIncompleteInput and rowsDecoded will be set to
806      *                    the number of scanlines that were successfully decoded.
807      *                    This will allow getPixels() to fill the uninitialized memory.
808      */
809     virtual Result onGetPixels(const SkImageInfo& info,
810                                void* pixels, size_t rowBytes, const Options&,
811                                int* rowsDecoded) = 0;
812 
onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes &,SkYUVAPixmapInfo *)813     virtual bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
814                                  SkYUVAPixmapInfo*) const { return false; }
815 
onGetYUVAPlanes(const SkYUVAPixmaps &)816     virtual Result onGetYUVAPlanes(const SkYUVAPixmaps&) { return kUnimplemented; }
817 
onGetValidSubset(SkIRect *)818     virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
819         // By default, subsets are not supported.
820         return false;
821     }
822 
823     /**
824      *  If the stream was previously read, attempt to rewind.
825      *
826      *  If the stream needed to be rewound, call onRewind.
827      *  @returns true if the codec is at the right position and can be used.
828      *      false if there was a failure to rewind.
829      *
830      *  This is called by getPixels(), getYUV8Planes(), startIncrementalDecode() and
831      *  startScanlineDecode(). Subclasses may call if they need to rewind at another time.
832      */
833     bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
834 
835     /**
836      *  Called by rewindIfNeeded, if the stream needed to be rewound.
837      *
838      *  Subclasses should do any set up needed after a rewind.
839      */
onRewind()840     virtual bool onRewind() {
841         return true;
842     }
843 
844     /**
845      * Get method for the input stream
846      */
stream()847     SkStream* stream() {
848         return fStream.get();
849     }
850 
851     /**
852      *  The remaining functions revolve around decoding scanlines.
853      */
854 
855     /**
856      *  Most images types will be kTopDown and will not need to override this function.
857      */
onGetScanlineOrder()858     virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
859 
dstInfo()860     const SkImageInfo& dstInfo() const { return fDstInfo; }
861 
options()862     const Options& options() const { return fOptions; }
863 
864     /**
865      *  Returns the number of scanlines that have been decoded so far.
866      *  This is unaffected by the SkScanlineOrder.
867      *
868      *  Returns -1 if we have not started a scanline decode.
869      */
currScanline()870     int currScanline() const { return fCurrScanline; }
871 
872     virtual int onOutputScanline(int inputScanline) const;
873 
874     /**
875      *  Return whether we can convert to dst.
876      *
877      *  Will be called for the appropriate frame, prior to initializing the colorXform.
878      */
879     virtual bool conversionSupported(const SkImageInfo& dst, bool srcIsOpaque,
880                                      bool needsColorXform);
881 
882     // Some classes never need a colorXform e.g.
883     // - ICO uses its embedded codec's colorXform
884     // - WBMP is just Black/White
usesColorXform()885     virtual bool usesColorXform() const { return true; }
886     void applyColorXform(void* dst, const void* src, int count) const;
887 
colorXform()888     bool colorXform() const { return fXformTime != kNo_XformTime; }
xformOnDecode()889     bool xformOnDecode() const { return fXformTime == kDecodeRow_XformTime; }
890 
onGetFrameCount()891     virtual int onGetFrameCount() {
892         return 1;
893     }
894 
onGetFrameInfo(int,FrameInfo *)895     virtual bool onGetFrameInfo(int, FrameInfo*) const {
896         return false;
897     }
898 
onGetRepetitionCount()899     virtual int onGetRepetitionCount() {
900         return 0;
901     }
902 
903 private:
904     const SkEncodedInfo                fEncodedInfo;
905     const XformFormat                  fSrcXformFormat;
906     std::unique_ptr<SkStream>          fStream;
907     bool                               fNeedsRewind;
908     const SkEncodedOrigin              fOrigin;
909 
910     SkImageInfo                        fDstInfo;
911     Options                            fOptions;
912 
913     enum XformTime {
914         kNo_XformTime,
915         kPalette_XformTime,
916         kDecodeRow_XformTime,
917     };
918     XformTime                          fXformTime;
919     XformFormat                        fDstXformFormat; // Based on fDstInfo.
920     skcms_ICCProfile                   fDstProfile;
921     skcms_AlphaFormat                  fDstXformAlphaFormat;
922 
923     // Only meaningful during scanline decodes.
924     int                                fCurrScanline;
925 
926     bool                               fStartedIncrementalDecode;
927 
928     // Allows SkAndroidCodec to call handleFrameIndex (potentially decoding a prior frame and
929     // clearing to transparent) without SkCodec calling it, too.
930     bool                               fAndroidCodecHandlesFrameIndex;
931 
932     bool initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha, bool srcIsOpaque);
933 
934     /**
935      *  Return whether these dimensions are supported as a scale.
936      *
937      *  The codec may choose to cache the information about scale and subset.
938      *  Either way, the same information will be passed to onGetPixels/onStart
939      *  on success.
940      *
941      *  This must return true for a size returned from getScaledDimensions.
942      */
dimensionsSupported(const SkISize & dim)943     bool dimensionsSupported(const SkISize& dim) {
944         return dim == this->dimensions() || this->onDimensionsSupported(dim);
945     }
946 
947     /**
948      *  For multi-framed images, return the object with information about the frames.
949      */
getFrameHolder()950     virtual const SkFrameHolder* getFrameHolder() const {
951         return nullptr;
952     }
953 
954     /**
955      *  Check for a valid Options.fFrameIndex, and decode prior frames if necessary.
956      *
957      *  If androidCodec is not null, that means this SkCodec is owned by an SkAndroidCodec. In that
958      *  case, the Options will be treated as an AndroidOptions, and SkAndroidCodec will be used to
959      *  decode a prior frame, if a prior frame is needed. When such an owned SkCodec calls
960      *  handleFrameIndex, it will immediately return kSuccess, since SkAndroidCodec already handled
961      *  it.
962      */
963     Result handleFrameIndex(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&,
964             SkAndroidCodec* androidCodec = nullptr);
965 
966     // Methods for scanline decoding.
onStartScanlineDecode(const SkImageInfo &,const Options &)967     virtual Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
968             const Options& /*options*/) {
969         return kUnimplemented;
970     }
971 
onStartIncrementalDecode(const SkImageInfo &,void *,size_t,const Options &)972     virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
973             const Options&) {
974         return kUnimplemented;
975     }
976 
onIncrementalDecode(int *)977     virtual Result onIncrementalDecode(int*) {
978         return kUnimplemented;
979     }
980 
981 
onSkipScanlines(int)982     virtual bool onSkipScanlines(int /*countLines*/) { return false; }
983 
onGetScanlines(void *,int,size_t)984     virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
985 
986     /**
987      * On an incomplete decode, getPixels() and getScanlines() will call this function
988      * to fill any uinitialized memory.
989      *
990      * @param dstInfo        Contains the destination color type
991      *                       Contains the destination alpha type
992      *                       Contains the destination width
993      *                       The height stored in this info is unused
994      * @param dst            Pointer to the start of destination pixel memory
995      * @param rowBytes       Stride length in destination pixel memory
996      * @param zeroInit       Indicates if memory is zero initialized
997      * @param linesRequested Number of lines that the client requested
998      * @param linesDecoded   Number of lines that were successfully decoded
999      */
1000     void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
1001             ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
1002 
1003     /**
1004      *  Return an object which will allow forcing scanline decodes to sample in X.
1005      *
1006      *  May create a sampler, if one is not currently being used. Otherwise, does
1007      *  not affect ownership.
1008      *
1009      *  Only valid during scanline decoding or incremental decoding.
1010      */
getSampler(bool)1011     virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
1012 
1013     friend class DM::CodecSrc;  // for fillIncompleteImage
1014     friend class SkSampledCodec;
1015     friend class SkIcoCodec;
1016     friend class SkAndroidCodec; // for fEncodedInfo
1017 };
1018 #endif // SkCodec_DEFINED
1019