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