Coverage Report

Created: 2024-05-20 07:14

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