xref: /aosp_15_r20/external/skia/include/codec/SkCodec.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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