Home | History | Annotate | Download | only in codec
      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 "../private/SkTemplates.h"
     12 #include "SkColor.h"
     13 #include "SkEncodedImageFormat.h"
     14 #include "SkEncodedInfo.h"
     15 #include "SkImageInfo.h"
     16 #include "SkSize.h"
     17 #include "SkStream.h"
     18 #include "SkTypes.h"
     19 #include "SkYUVSizeInfo.h"
     20 
     21 #include <vector>
     22 
     23 class SkColorSpace;
     24 class SkColorSpaceXform;
     25 class SkData;
     26 class SkPngChunkReader;
     27 class SkSampler;
     28 
     29 namespace DM {
     30 class CodecSrc;
     31 class ColorCodecSrc;
     32 }
     33 class ColorCodecBench;
     34 
     35 /**
     36  *  Abstraction layer directly on top of an image codec.
     37  */
     38 class SK_API SkCodec : SkNoncopyable {
     39 public:
     40     /**
     41      *  Minimum number of bytes that must be buffered in SkStream input.
     42      *
     43      *  An SkStream passed to NewFromStream must be able to use this many
     44      *  bytes to determine the image type. Then the same SkStream must be
     45      *  passed to the correct decoder to read from the beginning.
     46      *
     47      *  This can be accomplished by implementing peek() to support peeking
     48      *  this many bytes, or by implementing rewind() to be able to rewind()
     49      *  after reading this many bytes.
     50      */
     51     static size_t MinBufferedBytesNeeded();
     52 
     53     /**
     54      *  If this stream represents an encoded image that we know how to decode,
     55      *  return an SkCodec that can decode it. Otherwise return NULL.
     56      *
     57      *  As stated above, this call must be able to peek or read
     58      *  MinBufferedBytesNeeded to determine the correct format, and then start
     59      *  reading from the beginning. First it will attempt to peek, and it
     60      *  assumes that if less than MinBufferedBytesNeeded bytes (but more than
     61      *  zero) are returned, this is because the stream is shorter than this,
     62      *  so falling back to reading would not provide more data. If peek()
     63      *  returns zero bytes, this call will instead attempt to read(). This
     64      *  will require that the stream can be rewind()ed.
     65      *
     66      *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
     67      *  the image is a png.
     68      *
     69      *  If the SkPngChunkReader is not NULL then:
     70      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
     71      *      If the image is a PNG, the SkPngChunkReader will be reffed.
     72      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
     73      *      to handle these chunks.  SkPngChunkReader will be called to read
     74      *      any unknown chunk at any point during the creation of the codec
     75      *      or the decode.  Note that if SkPngChunkReader fails to read a
     76      *      chunk, this could result in a failure to create the codec or a
     77      *      failure to decode the image.
     78      *      If the PNG does not contain unknown chunks, the SkPngChunkReader
     79      *      will not be used or modified.
     80      *
     81      *  If NULL is returned, the stream is deleted immediately. Otherwise, the
     82      *  SkCodec takes ownership of it, and will delete it when done with it.
     83      */
     84     static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
     85 
     86     /**
     87      *  If this data represents an encoded image that we know how to decode,
     88      *  return an SkCodec that can decode it. Otherwise return NULL.
     89      *
     90      *  If the SkPngChunkReader is not NULL then:
     91      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
     92      *      If the image is a PNG, the SkPngChunkReader will be reffed.
     93      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
     94      *      to handle these chunks.  SkPngChunkReader will be called to read
     95      *      any unknown chunk at any point during the creation of the codec
     96      *      or the decode.  Note that if SkPngChunkReader fails to read a
     97      *      chunk, this could result in a failure to create the codec or a
     98      *      failure to decode the image.
     99      *      If the PNG does not contain unknown chunks, the SkPngChunkReader
    100      *      will not be used or modified.
    101      */
    102     static SkCodec* NewFromData(sk_sp<SkData>, SkPngChunkReader* = NULL);
    103     static SkCodec* NewFromData(SkData* data, SkPngChunkReader* reader) {
    104         return NewFromData(sk_ref_sp(data), reader);
    105     }
    106 
    107     virtual ~SkCodec();
    108 
    109     /**
    110      *  Return the ImageInfo associated with this codec.
    111      */
    112     const SkImageInfo& getInfo() const { return fSrcInfo; }
    113 
    114     const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }
    115 
    116     enum Origin {
    117         kTopLeft_Origin     = 1, // Default
    118         kTopRight_Origin    = 2, // Reflected across y-axis
    119         kBottomRight_Origin = 3, // Rotated 180
    120         kBottomLeft_Origin  = 4, // Reflected across x-axis
    121         kLeftTop_Origin     = 5, // Reflected across x-axis, Rotated 90 CCW
    122         kRightTop_Origin    = 6, // Rotated 90 CW
    123         kRightBottom_Origin = 7, // Reflected across x-axis, Rotated 90 CW
    124         kLeftBottom_Origin  = 8, // Rotated 90 CCW
    125         kDefault_Origin     = kTopLeft_Origin,
    126         kLast_Origin        = kLeftBottom_Origin,
    127     };
    128 
    129     /**
    130      *  Returns the image orientation stored in the EXIF data.
    131      *  If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft.
    132      */
    133     Origin getOrigin() const { return fOrigin; }
    134 
    135     /**
    136      *  Return a size that approximately supports the desired scale factor.
    137      *  The codec may not be able to scale efficiently to the exact scale
    138      *  factor requested, so return a size that approximates that scale.
    139      *  The returned value is the codec's suggestion for the closest valid
    140      *  scale that it can natively support
    141      */
    142     SkISize getScaledDimensions(float desiredScale) const {
    143         // Negative and zero scales are errors.
    144         SkASSERT(desiredScale > 0.0f);
    145         if (desiredScale <= 0.0f) {
    146             return SkISize::Make(0, 0);
    147         }
    148 
    149         // Upscaling is not supported. Return the original size if the client
    150         // requests an upscale.
    151         if (desiredScale >= 1.0f) {
    152             return this->getInfo().dimensions();
    153         }
    154         return this->onGetScaledDimensions(desiredScale);
    155     }
    156 
    157     /**
    158      *  Return (via desiredSubset) a subset which can decoded from this codec,
    159      *  or false if this codec cannot decode subsets or anything similar to
    160      *  desiredSubset.
    161      *
    162      *  @param desiredSubset In/out parameter. As input, a desired subset of
    163      *      the original bounds (as specified by getInfo). If true is returned,
    164      *      desiredSubset may have been modified to a subset which is
    165      *      supported. Although a particular change may have been made to
    166      *      desiredSubset to create something supported, it is possible other
    167      *      changes could result in a valid subset.
    168      *      If false is returned, desiredSubset's value is undefined.
    169      *  @return true if this codec supports decoding desiredSubset (as
    170      *      returned, potentially modified)
    171      */
    172     bool getValidSubset(SkIRect* desiredSubset) const {
    173         return this->onGetValidSubset(desiredSubset);
    174     }
    175 
    176     /**
    177      *  Format of the encoded data.
    178      */
    179     SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
    180 
    181     /**
    182      *  Used to describe the result of a call to getPixels().
    183      *
    184      *  Result is the union of possible results from subclasses.
    185      */
    186     enum Result {
    187         /**
    188          *  General return value for success.
    189          */
    190         kSuccess,
    191         /**
    192          *  The input is incomplete. A partial image was generated.
    193          */
    194         kIncompleteInput,
    195         /**
    196          *  The generator cannot convert to match the request, ignoring
    197          *  dimensions.
    198          */
    199         kInvalidConversion,
    200         /**
    201          *  The generator cannot scale to requested size.
    202          */
    203         kInvalidScale,
    204         /**
    205          *  Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
    206          *  too small, etc.
    207          */
    208         kInvalidParameters,
    209         /**
    210          *  The input did not contain a valid image.
    211          */
    212         kInvalidInput,
    213         /**
    214          *  Fulfilling this request requires rewinding the input, which is not
    215          *  supported for this input.
    216          */
    217         kCouldNotRewind,
    218         /**
    219          *  This method is not implemented by this codec.
    220          *  FIXME: Perhaps this should be kUnsupported?
    221          */
    222         kUnimplemented,
    223     };
    224 
    225     /**
    226      *  Whether or not the memory passed to getPixels is zero initialized.
    227      */
    228     enum ZeroInitialized {
    229         /**
    230          *  The memory passed to getPixels is zero initialized. The SkCodec
    231          *  may take advantage of this by skipping writing zeroes.
    232          */
    233         kYes_ZeroInitialized,
    234         /**
    235          *  The memory passed to getPixels has not been initialized to zero,
    236          *  so the SkCodec must write all zeroes to memory.
    237          *
    238          *  This is the default. It will be used if no Options struct is used.
    239          */
    240         kNo_ZeroInitialized,
    241     };
    242 
    243     /**
    244      *  Additional options to pass to getPixels.
    245      */
    246     struct Options {
    247         Options()
    248             : fZeroInitialized(kNo_ZeroInitialized)
    249             , fSubset(nullptr)
    250             , fFrameIndex(0)
    251             , fHasPriorFrame(false)
    252             , fPremulBehavior(SkTransferFunctionBehavior::kRespect)
    253         {}
    254 
    255         ZeroInitialized            fZeroInitialized;
    256         /**
    257          *  If not NULL, represents a subset of the original image to decode.
    258          *  Must be within the bounds returned by getInfo().
    259          *  If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which
    260          *  currently supports subsets), the top and left values must be even.
    261          *
    262          *  In getPixels and incremental decode, we will attempt to decode the
    263          *  exact rectangular subset specified by fSubset.
    264          *
    265          *  In a scanline decode, it does not make sense to specify a subset
    266          *  top or subset height, since the client already controls which rows
    267          *  to get and which rows to skip.  During scanline decodes, we will
    268          *  require that the subset top be zero and the subset height be equal
    269          *  to the full height.  We will, however, use the values of
    270          *  subset left and subset width to decode partial scanlines on calls
    271          *  to getScanlines().
    272          */
    273         const SkIRect*             fSubset;
    274 
    275         /**
    276          *  The frame to decode.
    277          *
    278          *  Only meaningful for multi-frame images.
    279          */
    280         size_t                     fFrameIndex;
    281 
    282         /**
    283          *  If true, the dst already contains the prior frame.
    284          *
    285          *  Only meaningful for multi-frame images.
    286          *
    287          *  If fFrameIndex needs to be blended with a prior frame (as reported by
    288          *  getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to
    289          *  either true or false:
    290          *
    291          *  true means that the prior frame is already in the dst, and this
    292          *  codec only needs to decode fFrameIndex and blend it with the dst.
    293          *  Options.fZeroInitialized is ignored in this case.
    294          *
    295          *  false means that the dst does not contain the prior frame, so this
    296          *  codec needs to first decode the prior frame (which in turn may need
    297          *  to decode its prior frame).
    298          */
    299         bool                       fHasPriorFrame;
    300 
    301         /**
    302          *  Indicates whether we should do a linear premultiply or a legacy premultiply.
    303          *
    304          *  In the case where the dst SkColorSpace is nullptr, this flag is ignored and
    305          *  we will always do a legacy premultiply.
    306          */
    307         SkTransferFunctionBehavior fPremulBehavior;
    308     };
    309 
    310     /**
    311      *  Decode into the given pixels, a block of memory of size at
    312      *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
    313      *  bytesPerPixel)
    314      *
    315      *  Repeated calls to this function should give the same results,
    316      *  allowing the PixelRef to be immutable.
    317      *
    318      *  @param info A description of the format (config, size)
    319      *         expected by the caller.  This can simply be identical
    320      *         to the info returned by getInfo().
    321      *
    322      *         This contract also allows the caller to specify
    323      *         different output-configs, which the implementation can
    324      *         decide to support or not.
    325      *
    326      *         A size that does not match getInfo() implies a request
    327      *         to scale. If the generator cannot perform this scale,
    328      *         it will return kInvalidScale.
    329      *
    330      *         If the info contains a non-null SkColorSpace, the codec
    331      *         will perform the appropriate color space transformation.
    332      *         If the caller passes in the same color space that was
    333      *         reported by the codec, the color space transformation is
    334      *         a no-op.
    335      *
    336      *  If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
    337      *  SkPMColor values in ctable. On success the generator must copy N colors into that storage,
    338      *  (where N is the logical number of table entries) and set ctableCount to N.
    339      *
    340      *  If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount
    341      *  is not null, it will be set to 0.
    342      *
    343      *  If a scanline decode is in progress, scanline mode will end, requiring the client to call
    344      *  startScanlineDecode() in order to return to decoding scanlines.
    345      *
    346      *  @return Result kSuccess, or another value explaining the type of failure.
    347      */
    348     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*,
    349                      SkPMColor ctable[], int* ctableCount);
    350 
    351     /**
    352      *  Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
    353      *  uses the default Options.
    354      */
    355     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
    356 
    357     /**
    358      *  If decoding to YUV is supported, this returns true.  Otherwise, this
    359      *  returns false and does not modify any of the parameters.
    360      *
    361      *  @param sizeInfo   Output parameter indicating the sizes and required
    362      *                    allocation widths of the Y, U, and V planes.
    363      *  @param colorSpace Output parameter.  If non-NULL this is set to kJPEG,
    364      *                    otherwise this is ignored.
    365      */
    366     bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
    367         if (nullptr == sizeInfo) {
    368             return false;
    369         }
    370 
    371         return this->onQueryYUV8(sizeInfo, colorSpace);
    372     }
    373 
    374     /**
    375      *  Returns kSuccess, or another value explaining the type of failure.
    376      *  This always attempts to perform a full decode.  If the client only
    377      *  wants size, it should call queryYUV8().
    378      *
    379      *  @param sizeInfo   Needs to exactly match the values returned by the
    380      *                    query, except the WidthBytes may be larger than the
    381      *                    recommendation (but not smaller).
    382      *  @param planes     Memory for each of the Y, U, and V planes.
    383      */
    384     Result getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
    385         if (nullptr == planes || nullptr == planes[0] || nullptr == planes[1] ||
    386                 nullptr == planes[2]) {
    387             return kInvalidInput;
    388         }
    389 
    390         if (!this->rewindIfNeeded()) {
    391             return kCouldNotRewind;
    392         }
    393 
    394         return this->onGetYUV8Planes(sizeInfo, planes);
    395     }
    396 
    397     /**
    398      *  Prepare for an incremental decode with the specified options.
    399      *
    400      *  This may require a rewind.
    401      *
    402      *  @param dstInfo Info of the destination. If the dimensions do not match
    403      *      those of getInfo, this implies a scale.
    404      *  @param dst Memory to write to. Needs to be large enough to hold the subset,
    405      *      if present, or the full image as described in dstInfo.
    406      *  @param options Contains decoding options, including if memory is zero
    407      *      initialized and whether to decode a subset.
    408      *  @param ctable A pointer to a color table.  When dstInfo.colorType() is
    409      *      kIndex8, this should be non-NULL and have enough storage for 256
    410      *      colors.  The color table will be populated after decoding the palette.
    411      *  @param ctableCount A pointer to the size of the color table.  When
    412      *      dstInfo.colorType() is kIndex8, this should be non-NULL.  It will
    413      *      be modified to the true size of the color table (<= 256) after
    414      *      decoding the palette.
    415      *  @return Enum representing success or reason for failure.
    416      */
    417     Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
    418             const SkCodec::Options*, SkPMColor* ctable, int* ctableCount);
    419 
    420     Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
    421             const SkCodec::Options* options) {
    422         return this->startIncrementalDecode(dstInfo, dst, rowBytes, options, nullptr, nullptr);
    423     }
    424 
    425     Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
    426         return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr, nullptr, nullptr);
    427     }
    428 
    429     /**
    430      *  Start/continue the incremental decode.
    431      *
    432      *  Not valid to call before calling startIncrementalDecode().
    433      *
    434      *  After the first call, should only be called again if more data has been
    435      *  provided to the source SkStream.
    436      *
    437      *  Unlike getPixels and getScanlines, this does not do any filling. This is
    438      *  left up to the caller, since they may be skipping lines or continuing the
    439      *  decode later. In the latter case, they may choose to initialize all lines
    440      *  first, or only initialize the remaining lines after the first call.
    441      *
    442      *  @param rowsDecoded Optional output variable returning the total number of
    443      *      lines initialized. Only meaningful if this method returns kIncompleteInput.
    444      *      Otherwise the implementation may not set it.
    445      *      Note that some implementations may have initialized this many rows, but
    446      *      not necessarily finished those rows (e.g. interlaced PNG). This may be
    447      *      useful for determining what rows the client needs to initialize.
    448      *  @return kSuccess if all lines requested in startIncrementalDecode have
    449      *      been completely decoded. kIncompleteInput otherwise.
    450      */
    451     Result incrementalDecode(int* rowsDecoded = nullptr) {
    452         if (!fStartedIncrementalDecode) {
    453             return kInvalidParameters;
    454         }
    455         return this->onIncrementalDecode(rowsDecoded);
    456     }
    457 
    458     /**
    459      * The remaining functions revolve around decoding scanlines.
    460      */
    461 
    462     /**
    463      *  Prepare for a scanline decode with the specified options.
    464      *
    465      *  After this call, this class will be ready to decode the first scanline.
    466      *
    467      *  This must be called in order to call getScanlines or skipScanlines.
    468      *
    469      *  This may require rewinding the stream.
    470      *
    471      *  Not all SkCodecs support this.
    472      *
    473      *  @param dstInfo Info of the destination. If the dimensions do not match
    474      *      those of getInfo, this implies a scale.
    475      *  @param options Contains decoding options, including if memory is zero
    476      *      initialized.
    477      *  @param ctable A pointer to a color table.  When dstInfo.colorType() is
    478      *      kIndex8, this should be non-NULL and have enough storage for 256
    479      *      colors.  The color table will be populated after decoding the palette.
    480      *  @param ctableCount A pointer to the size of the color table.  When
    481      *      dstInfo.colorType() is kIndex8, this should be non-NULL.  It will
    482      *      be modified to the true size of the color table (<= 256) after
    483      *      decoding the palette.
    484      *  @return Enum representing success or reason for failure.
    485      */
    486     Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options* options,
    487             SkPMColor ctable[], int* ctableCount);
    488 
    489     /**
    490      *  Simplified version of startScanlineDecode() that asserts that info is NOT
    491      *  kIndex8_SkColorType and uses the default Options.
    492      */
    493     Result startScanlineDecode(const SkImageInfo& dstInfo);
    494 
    495     /**
    496      *  Write the next countLines scanlines into dst.
    497      *
    498      *  Not valid to call before calling startScanlineDecode().
    499      *
    500      *  @param dst Must be non-null, and large enough to hold countLines
    501      *      scanlines of size rowBytes.
    502      *  @param countLines Number of lines to write.
    503      *  @param rowBytes Number of bytes per row. Must be large enough to hold
    504      *      a scanline based on the SkImageInfo used to create this object.
    505      *  @return the number of lines successfully decoded.  If this value is
    506      *      less than countLines, this will fill the remaining lines with a
    507      *      default value.
    508      */
    509     int getScanlines(void* dst, int countLines, size_t rowBytes);
    510 
    511     /**
    512      *  Skip count scanlines.
    513      *
    514      *  Not valid to call before calling startScanlineDecode().
    515      *
    516      *  The default version just calls onGetScanlines and discards the dst.
    517      *  NOTE: If skipped lines are the only lines with alpha, this default
    518      *  will make reallyHasAlpha return true, when it could have returned
    519      *  false.
    520      *
    521      *  @return true if the scanlines were successfully skipped
    522      *          false on failure, possible reasons for failure include:
    523      *              An incomplete input image stream.
    524      *              Calling this function before calling startScanlineDecode().
    525      *              If countLines is less than zero or so large that it moves
    526      *                  the current scanline past the end of the image.
    527      */
    528     bool skipScanlines(int countLines);
    529 
    530     /**
    531      *  The order in which rows are output from the scanline decoder is not the
    532      *  same for all variations of all image types.  This explains the possible
    533      *  output row orderings.
    534      */
    535     enum SkScanlineOrder {
    536         /*
    537          * By far the most common, this indicates that the image can be decoded
    538          * reliably using the scanline decoder, and that rows will be output in
    539          * the logical order.
    540          */
    541         kTopDown_SkScanlineOrder,
    542 
    543         /*
    544          * This indicates that the scanline decoder reliably outputs rows, but
    545          * they will be returned in reverse order.  If the scanline format is
    546          * kBottomUp, the nextScanline() API can be used to determine the actual
    547          * y-coordinate of the next output row, but the client is not forced
    548          * to take advantage of this, given that it's not too tough to keep
    549          * track independently.
    550          *
    551          * For full image decodes, it is safe to get all of the scanlines at
    552          * once, since the decoder will handle inverting the rows as it
    553          * decodes.
    554          *
    555          * For subset decodes and sampling, it is simplest to get and skip
    556          * scanlines one at a time, using the nextScanline() API.  It is
    557          * possible to ask for larger chunks at a time, but this should be used
    558          * with caution.  As with full image decodes, the decoder will handle
    559          * inverting the requested rows, but rows will still be delivered
    560          * starting from the bottom of the image.
    561          *
    562          * Upside down bmps are an example.
    563          */
    564         kBottomUp_SkScanlineOrder,
    565     };
    566 
    567     /**
    568      *  An enum representing the order in which scanlines will be returned by
    569      *  the scanline decoder.
    570      *
    571      *  This is undefined before startScanlineDecode() is called.
    572      */
    573     SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
    574 
    575     /**
    576      *  Returns the y-coordinate of the next row to be returned by the scanline
    577      *  decoder.
    578      *
    579      *  This will equal fCurrScanline, except in the case of strangely
    580      *  encoded image types (bottom-up bmps).
    581      *
    582      *  Results are undefined when not in scanline decoding mode.
    583      */
    584     int nextScanline() const { return this->outputScanline(fCurrScanline); }
    585 
    586     /**
    587      *  Returns the output y-coordinate of the row that corresponds to an input
    588      *  y-coordinate.  The input y-coordinate represents where the scanline
    589      *  is located in the encoded data.
    590      *
    591      *  This will equal inputScanline, except in the case of strangely
    592      *  encoded image types (bottom-up bmps, interlaced gifs).
    593      */
    594     int outputScanline(int inputScanline) const;
    595 
    596     // The required frame for an independent frame is marked as
    597     // kNone.
    598     static constexpr size_t kNone = static_cast<size_t>(-1);
    599 
    600     /**
    601      *  Information about individual frames in a multi-framed image.
    602      */
    603     struct FrameInfo {
    604         /**
    605          *  The frame that this frame needs to be blended with, or
    606          *  kNone.
    607          */
    608         size_t fRequiredFrame;
    609 
    610         /**
    611          *  Number of milliseconds to show this frame.
    612          */
    613         size_t fDuration;
    614 
    615         /**
    616          *  Whether the end marker for this frame is contained in the stream.
    617          *
    618          *  Note: this does not guarantee that an attempt to decode will be complete.
    619          *  There could be an error in the stream.
    620          */
    621         bool fFullyReceived;
    622     };
    623 
    624     /**
    625      *  Return info about the frames in the image.
    626      *
    627      *  May require reading through the stream to determine info about the
    628      *  frames (including the count).
    629      *
    630      *  As such, future decoding calls may require a rewind.
    631      *
    632      *  For single-frame images, this will return an empty vector.
    633      */
    634     std::vector<FrameInfo> getFrameInfo() {
    635         return this->onGetFrameInfo();
    636     }
    637 
    638     static constexpr int kRepetitionCountInfinite = -1;
    639 
    640     /**
    641      *  Return the number of times to repeat, if this image is animated.
    642      *
    643      *  May require reading the stream to find the repetition count.
    644      *
    645      *  As such, future decoding calls may require a rewind.
    646      *
    647      *  For single-frame images, this will return 0.
    648      */
    649     int getRepetitionCount() {
    650         return this->onGetRepetitionCount();
    651     }
    652 
    653 protected:
    654     /**
    655      *  Takes ownership of SkStream*
    656      */
    657     SkCodec(int width,
    658             int height,
    659             const SkEncodedInfo&,
    660             SkStream*,
    661             sk_sp<SkColorSpace>,
    662             Origin = kTopLeft_Origin);
    663 
    664     /**
    665      *  Takes ownership of SkStream*
    666      *  Allows the subclass to set the recommended SkImageInfo
    667      */
    668     SkCodec(const SkEncodedInfo&,
    669             const SkImageInfo&,
    670             SkStream*,
    671             Origin = kTopLeft_Origin);
    672 
    673     virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
    674         // By default, scaling is not supported.
    675         return this->getInfo().dimensions();
    676     }
    677 
    678     // FIXME: What to do about subsets??
    679     /**
    680      *  Subclasses should override if they support dimensions other than the
    681      *  srcInfo's.
    682      */
    683     virtual bool onDimensionsSupported(const SkISize&) {
    684         return false;
    685     }
    686 
    687     virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;
    688 
    689     /**
    690      * @param rowsDecoded When the encoded image stream is incomplete, this function
    691      *                    will return kIncompleteInput and rowsDecoded will be set to
    692      *                    the number of scanlines that were successfully decoded.
    693      *                    This will allow getPixels() to fill the uninitialized memory.
    694      */
    695     virtual Result onGetPixels(const SkImageInfo& info,
    696                                void* pixels, size_t rowBytes, const Options&,
    697                                SkPMColor ctable[], int* ctableCount,
    698                                int* rowsDecoded) = 0;
    699 
    700     virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const {
    701         return false;
    702     }
    703 
    704     virtual Result onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) {
    705         return kUnimplemented;
    706     }
    707 
    708     virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
    709         // By default, subsets are not supported.
    710         return false;
    711     }
    712 
    713     /**
    714      *  If the stream was previously read, attempt to rewind.
    715      *
    716      *  If the stream needed to be rewound, call onRewind.
    717      *  @returns true if the codec is at the right position and can be used.
    718      *      false if there was a failure to rewind.
    719      *
    720      *  This is called by getPixels() and start(). Subclasses may call if they
    721      *  need to rewind at another time.
    722      */
    723     bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
    724 
    725     /**
    726      *  Called by rewindIfNeeded, if the stream needed to be rewound.
    727      *
    728      *  Subclasses should do any set up needed after a rewind.
    729      */
    730     virtual bool onRewind() {
    731         return true;
    732     }
    733 
    734     /**
    735      * On an incomplete input, getPixels() and getScanlines() will fill any uninitialized
    736      * scanlines.  This allows the subclass to indicate what value to fill with.
    737      *
    738      * @param dstInfo   Describes the destination.
    739      * @return          The value with which to fill uninitialized pixels.
    740      *
    741      * Note that we can interpret the return value as a 64-bit Float16 color, a SkPMColor,
    742      * a 16-bit 565 color, an 8-bit gray color, or an 8-bit index into a color table,
    743      * depending on the color type.
    744      */
    745     uint64_t getFillValue(const SkImageInfo& dstInfo) const {
    746         return this->onGetFillValue(dstInfo);
    747     }
    748 
    749     /**
    750      * Some subclasses will override this function, but this is a useful default for the color
    751      * types that we support.  Note that for color types that do not use the full 64-bits,
    752      * we will simply take the low bits of the fill value.
    753      *
    754      * The defaults are:
    755      * kRGBA_F16_SkColorType: Transparent or Black, depending on the src alpha type
    756      * kN32_SkColorType: Transparent or Black, depending on the src alpha type
    757      * kRGB_565_SkColorType: Black
    758      * kGray_8_SkColorType: Black
    759      * kIndex_8_SkColorType: First color in color table
    760      */
    761     virtual uint64_t onGetFillValue(const SkImageInfo& dstInfo) const;
    762 
    763     /**
    764      * Get method for the input stream
    765      */
    766     SkStream* stream() {
    767         return fStream.get();
    768     }
    769 
    770     /**
    771      *  The remaining functions revolve around decoding scanlines.
    772      */
    773 
    774     /**
    775      *  Most images types will be kTopDown and will not need to override this function.
    776      */
    777     virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
    778 
    779     const SkImageInfo& dstInfo() const { return fDstInfo; }
    780 
    781     const SkCodec::Options& options() const { return fOptions; }
    782 
    783     /**
    784      *  Returns the number of scanlines that have been decoded so far.
    785      *  This is unaffected by the SkScanlineOrder.
    786      *
    787      *  Returns -1 if we have not started a scanline decode.
    788      */
    789     int currScanline() const { return fCurrScanline; }
    790 
    791     virtual int onOutputScanline(int inputScanline) const;
    792 
    793     bool initializeColorXform(const SkImageInfo& dstInfo,
    794                               SkTransferFunctionBehavior premulBehavior);
    795     SkColorSpaceXform* colorXform() const { return fColorXform.get(); }
    796 
    797     virtual std::vector<FrameInfo> onGetFrameInfo() {
    798         // empty vector - this is not animated.
    799         return std::vector<FrameInfo>{};
    800     }
    801 
    802     virtual int onGetRepetitionCount() {
    803         return 0;
    804     }
    805 
    806     void setUnsupportedICC(bool SkDEBUGCODE(value)) { SkDEBUGCODE(fUnsupportedICC = value); }
    807 
    808 private:
    809     const SkEncodedInfo                fEncodedInfo;
    810     const SkImageInfo                  fSrcInfo;
    811     std::unique_ptr<SkStream>          fStream;
    812     bool                               fNeedsRewind;
    813     const Origin                       fOrigin;
    814 
    815     SkImageInfo                        fDstInfo;
    816     SkCodec::Options                   fOptions;
    817     std::unique_ptr<SkColorSpaceXform> fColorXform;
    818 
    819     // Only meaningful during scanline decodes.
    820     int                                fCurrScanline;
    821 
    822     bool                               fStartedIncrementalDecode;
    823 #ifdef SK_DEBUG
    824     bool                               fUnsupportedICC = false;
    825 #endif
    826 
    827     /**
    828      *  Return whether these dimensions are supported as a scale.
    829      *
    830      *  The codec may choose to cache the information about scale and subset.
    831      *  Either way, the same information will be passed to onGetPixels/onStart
    832      *  on success.
    833      *
    834      *  This must return true for a size returned from getScaledDimensions.
    835      */
    836     bool dimensionsSupported(const SkISize& dim) {
    837         return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim);
    838     }
    839 
    840     // Methods for scanline decoding.
    841     virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
    842             const SkCodec::Options& /*options*/, SkPMColor* /*ctable*/, int* /*ctableCount*/) {
    843         return kUnimplemented;
    844     }
    845 
    846     virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
    847             const SkCodec::Options&, SkPMColor*, int*) {
    848         return kUnimplemented;
    849     }
    850 
    851     virtual Result onIncrementalDecode(int*) {
    852         return kUnimplemented;
    853     }
    854 
    855 
    856     virtual bool onSkipScanlines(int /*countLines*/) { return false; }
    857 
    858     virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
    859 
    860     /**
    861      * On an incomplete decode, getPixels() and getScanlines() will call this function
    862      * to fill any uinitialized memory.
    863      *
    864      * @param dstInfo        Contains the destination color type
    865      *                       Contains the destination alpha type
    866      *                       Contains the destination width
    867      *                       The height stored in this info is unused
    868      * @param dst            Pointer to the start of destination pixel memory
    869      * @param rowBytes       Stride length in destination pixel memory
    870      * @param zeroInit       Indicates if memory is zero initialized
    871      * @param linesRequested Number of lines that the client requested
    872      * @param linesDecoded   Number of lines that were successfully decoded
    873      */
    874     void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
    875             ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
    876 
    877     /**
    878      *  Return an object which will allow forcing scanline decodes to sample in X.
    879      *
    880      *  May create a sampler, if one is not currently being used. Otherwise, does
    881      *  not affect ownership.
    882      *
    883      *  Only valid during scanline decoding or incremental decoding.
    884      */
    885     virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
    886 
    887     friend class DM::CodecSrc;  // for fillIncompleteImage
    888     friend class SkSampledCodec;
    889     friend class SkIcoCodec;
    890     friend struct Sniffer; // for fUnsupportedICC
    891     friend class AutoCleanPng; // for setUnsupportedICC()
    892 };
    893 #endif // SkCodec_DEFINED
    894