Coverage Report

Created: 2024-09-14 07:19

/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
56.7k
    SkImageInfo getInfo() const { return fEncodedInfo.makeImageInfo(); }
229
230
244k
    SkISize dimensions() const { return {fEncodedInfo.width(), fEncodedInfo.height()}; }
231
14.6k
    SkIRect bounds() const {
232
14.6k
        return SkIRect::MakeWH(fEncodedInfo.width(), fEncodedInfo.height());
233
14.6k
    }
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
60.2k
    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
6.81k
    SkISize getScaledDimensions(float desiredScale) const {
256
        // Negative and zero scales are errors.
257
6.81k
        SkASSERT(desiredScale > 0.0f);
258
6.81k
        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
6.81k
        if (desiredScale >= 1.0f) {
265
0
            return this->dimensions();
266
0
        }
267
6.81k
        return this->onGetScaledDimensions(desiredScale);
268
6.81k
    }
SkCodec::getScaledDimensions(float) const
Line
Count
Source
255
6.81k
    SkISize getScaledDimensions(float desiredScale) const {
256
        // Negative and zero scales are errors.
257
6.81k
        SkASSERT(desiredScale > 0.0f);
258
6.81k
        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
6.81k
        if (desiredScale >= 1.0f) {
265
0
            return this->dimensions();
266
0
        }
267
6.81k
        return this->onGetScaledDimensions(desiredScale);
268
6.81k
    }
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
51.2k
    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
217k
        {}
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
18.7k
    Result getPixels(const SkPixmap& pm, const Options* opts = nullptr) {
417
18.7k
        return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts);
418
18.7k
    }
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
2.66k
    Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
472
2.66k
        return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr);
473
2.66k
    }
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
2.38k
    Result incrementalDecode(int* rowsDecoded = nullptr) {
499
2.38k
        if (!fStartedIncrementalDecode) {
500
0
            return kInvalidParameters;
501
0
        }
502
2.38k
        return this->onIncrementalDecode(rowsDecoded);
503
2.38k
    }
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
378
    Result startScanlineDecode(const SkImageInfo& dstInfo) {
532
378
        return this->startScanlineDecode(dstInfo, nullptr);
533
378
    }
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
2.12M
    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
17.3k
    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
5.75k
    int getFrameCount() {
642
5.75k
        return this->onGetFrameCount();
643
5.75k
    }
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
    /**
653
     *  Information about individual frames in a multi-framed image.
654
     */
655
    struct FrameInfo {
656
        /**
657
         *  The frame that this frame needs to be blended with, or
658
         *  kNoFrame if this frame is independent (so it can be
659
         *  drawn over an uninitialized buffer).
660
         *
661
         *  Note that this is the *earliest* frame that can be used
662
         *  for blending. Any frame from [fRequiredFrame, i) can be
663
         *  used, unless its fDisposalMethod is kRestorePrevious.
664
         */
665
        int fRequiredFrame;
666
667
        /**
668
         *  Number of milliseconds to show this frame.
669
         */
670
        int fDuration;
671
672
        /**
673
         *  Whether the end marker for this frame is contained in the stream.
674
         *
675
         *  Note: this does not guarantee that an attempt to decode will be complete.
676
         *  There could be an error in the stream.
677
         */
678
        bool fFullyReceived;
679
680
        /**
681
         *  This is conservative; it will still return non-opaque if e.g. a
682
         *  color index-based frame has a color with alpha but does not use it.
683
         */
684
        SkAlphaType fAlphaType;
685
686
        /**
687
         *  Whether the updated rectangle contains alpha.
688
         *
689
         *  This is conservative; it will still be set to true if e.g. a color
690
         *  index-based frame has a color with alpha but does not use it. In
691
         *  addition, it may be set to true, even if the final frame, after
692
         *  blending, is opaque.
693
         */
694
        bool fHasAlphaWithinBounds;
695
696
        /**
697
         *  How this frame should be modified before decoding the next one.
698
         */
699
        SkCodecAnimation::DisposalMethod fDisposalMethod;
700
701
        /**
702
         *  How this frame should blend with the prior frame.
703
         */
704
        SkCodecAnimation::Blend fBlend;
705
706
        /**
707
         *  The rectangle updated by this frame.
708
         *
709
         *  It may be empty, if the frame does not change the image. It will
710
         *  always be contained by SkCodec::dimensions().
711
         */
712
        SkIRect fFrameRect;
713
    };
714
715
    /**
716
     *  Return info about a single frame.
717
     *
718
     *  Does not read through the stream, so it should be called after
719
     *  getFrameCount() to parse any frames that have not already been parsed.
720
     *
721
     *  Only supported by animated (multi-frame) codecs. Note that this is a
722
     *  property of the codec (the SkCodec subclass), not the image.
723
     *
724
     *  To elaborate, some codecs support animation (e.g. GIF). Others do not
725
     *  (e.g. BMP). Animated codecs can still represent single frame images.
726
     *  Calling getFrameInfo(0, etc) will return true for a single frame GIF
727
     *  even if the overall image is not animated (in that the pixels on screen
728
     *  do not change over time). When incrementally decoding a GIF image, we
729
     *  might only know that there's a single frame *so far*.
730
     *
731
     *  For non-animated SkCodec subclasses, it's sufficient but not necessary
732
     *  for this method to always return false.
733
     */
734
46.5k
    bool getFrameInfo(int index, FrameInfo* info) const {
735
46.5k
        if (index < 0) {
736
0
            return false;
737
0
        }
738
46.5k
        return this->onGetFrameInfo(index, info);
739
46.5k
    }
740
741
    /**
742
     *  Return info about all the frames in the image.
743
     *
744
     *  May require reading through the stream to determine info about the
745
     *  frames (including the count).
746
     *
747
     *  As such, future decoding calls may require a rewind.
748
     *
749
     *  This may return an empty vector for non-animated codecs. See the
750
     *  getFrameInfo(int, FrameInfo*) comment.
751
     */
752
    std::vector<FrameInfo> getFrameInfo();
753
754
    static constexpr int kRepetitionCountInfinite = -1;
755
756
    /**
757
     *  Return the number of times to repeat, if this image is animated. This number does not
758
     *  include the first play through of each frame. For example, a repetition count of 4 means
759
     *  that each frame is played 5 times and then the animation stops.
760
     *
761
     *  It can return kRepetitionCountInfinite, a negative number, meaning that the animation
762
     *  should loop forever.
763
     *
764
     *  May require reading the stream to find the repetition count.
765
     *
766
     *  As such, future decoding calls may require a rewind.
767
     *
768
     *  For still (non-animated) image codecs, this will return 0.
769
     */
770
5.75k
    int getRepetitionCount() {
771
5.75k
        return this->onGetRepetitionCount();
772
5.75k
    }
773
774
    // Register a decoder at runtime by passing two function pointers:
775
    //    - peek() to return true if the span of bytes appears to be your encoded format;
776
    //    - make() to attempt to create an SkCodec from the given stream.
777
    // Not thread safe.
778
    static void Register(
779
            bool                     (*peek)(const void*, size_t),
780
            std::unique_ptr<SkCodec> (*make)(std::unique_ptr<SkStream>, SkCodec::Result*));
781
782
protected:
783
83.4k
    const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }
784
785
    using XformFormat = skcms_PixelFormat;
786
787
    SkCodec(SkEncodedInfo&&,
788
            XformFormat srcFormat,
789
            std::unique_ptr<SkStream>,
790
            SkEncodedOrigin = kTopLeft_SkEncodedOrigin);
791
792
    void setSrcXformFormat(XformFormat pixelFormat);
793
794
0
    XformFormat getSrcXformFormat() const {
795
0
        return fSrcXformFormat;
796
0
    }
797
798
0
    virtual bool onGetGainmapCodec(SkGainmapInfo*, std::unique_ptr<SkCodec>*) { return false; }
799
800
    // TODO(issues.skia.org/363544350): This API only works for JPEG images. Remove this API once
801
    // it is no longer used.
802
2.28k
    virtual bool onGetGainmapInfo(SkGainmapInfo*, std::unique_ptr<SkStream>*) { return false; }
803
804
0
    virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
805
        // By default, scaling is not supported.
806
0
        return this->dimensions();
807
0
    }
808
809
    // FIXME: What to do about subsets??
810
    /**
811
     *  Subclasses should override if they support dimensions other than the
812
     *  srcInfo's.
813
     */
814
729
    virtual bool onDimensionsSupported(const SkISize&) {
815
729
        return false;
816
729
    }
817
818
    virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;
819
820
    /**
821
     * @param rowsDecoded When the encoded image stream is incomplete, this function
822
     *                    will return kIncompleteInput and rowsDecoded will be set to
823
     *                    the number of scanlines that were successfully decoded.
824
     *                    This will allow getPixels() to fill the uninitialized memory.
825
     */
826
    virtual Result onGetPixels(const SkImageInfo& info,
827
                               void* pixels, size_t rowBytes, const Options&,
828
                               int* rowsDecoded) = 0;
829
830
    virtual bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
831
0
                                 SkYUVAPixmapInfo*) const { return false; }
832
833
0
    virtual Result onGetYUVAPlanes(const SkYUVAPixmaps&) { return kUnimplemented; }
834
835
0
    virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
836
        // By default, subsets are not supported.
837
0
        return false;
838
0
    }
839
840
    /**
841
     *  If the stream was previously read, attempt to rewind.
842
     *
843
     *  If the stream needed to be rewound, call onRewind.
844
     *  @returns true if the codec is at the right position and can be used.
845
     *      false if there was a failure to rewind.
846
     *
847
     *  This is called by getPixels(), getYUV8Planes(), startIncrementalDecode() and
848
     *  startScanlineDecode(). Subclasses may call if they need to rewind at another time.
849
     */
850
    [[nodiscard]] bool rewindIfNeeded();
851
852
    /**
853
     *  Called by rewindIfNeeded, if the stream needed to be rewound.
854
     *
855
     *  Subclasses should do any set up needed after a rewind.
856
     */
857
31.4k
    virtual bool onRewind() {
858
31.4k
        return true;
859
31.4k
    }
860
861
    /**
862
     * Get method for the input stream
863
     */
864
71.6k
    SkStream* stream() {
865
71.6k
        return fStream.get();
866
71.6k
    }
867
868
    /**
869
     *  The remaining functions revolve around decoding scanlines.
870
     */
871
872
    /**
873
     *  Most images types will be kTopDown and will not need to override this function.
874
     */
875
14.4k
    virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
876
877
315k
    const SkImageInfo& dstInfo() const { return fDstInfo; }
878
879
289k
    const Options& options() const { return fOptions; }
880
881
    /**
882
     *  Returns the number of scanlines that have been decoded so far.
883
     *  This is unaffected by the SkScanlineOrder.
884
     *
885
     *  Returns -1 if we have not started a scanline decode.
886
     */
887
746
    int currScanline() const { return fCurrScanline; }
888
889
    virtual int onOutputScanline(int inputScanline) const;
890
891
    /**
892
     *  Return whether we can convert to dst.
893
     *
894
     *  Will be called for the appropriate frame, prior to initializing the colorXform.
895
     */
896
    virtual bool conversionSupported(const SkImageInfo& dst, bool srcIsOpaque,
897
                                     bool needsColorXform);
898
899
    // Some classes never need a colorXform e.g.
900
    // - ICO uses its embedded codec's colorXform
901
    // - WBMP is just Black/White
902
64.6k
    virtual bool usesColorXform() const { return true; }
903
    void applyColorXform(void* dst, const void* src, int count) const;
904
905
4.24M
    bool colorXform() const { return fXformTime != kNo_XformTime; }
906
11.1k
    bool xformOnDecode() const { return fXformTime == kDecodeRow_XformTime; }
907
908
3.30k
    virtual int onGetFrameCount() {
909
3.30k
        return 1;
910
3.30k
    }
911
912
3.13k
    virtual bool onGetFrameInfo(int, FrameInfo*) const {
913
3.13k
        return false;
914
3.13k
    }
915
916
3.30k
    virtual int onGetRepetitionCount() {
917
3.30k
        return 0;
918
3.30k
    }
919
920
private:
921
    const SkEncodedInfo                fEncodedInfo;
922
    XformFormat                        fSrcXformFormat;
923
    std::unique_ptr<SkStream>          fStream;
924
    bool fNeedsRewind = false;
925
    const SkEncodedOrigin fOrigin;
926
927
    SkImageInfo                        fDstInfo;
928
    Options                            fOptions;
929
930
    enum XformTime {
931
        kNo_XformTime,
932
        kPalette_XformTime,
933
        kDecodeRow_XformTime,
934
    };
935
    XformTime                          fXformTime;
936
    XformFormat                        fDstXformFormat; // Based on fDstInfo.
937
    skcms_ICCProfile                   fDstProfile;
938
    skcms_AlphaFormat                  fDstXformAlphaFormat;
939
940
    // Only meaningful during scanline decodes.
941
    int fCurrScanline = -1;
942
943
    bool fStartedIncrementalDecode = false;
944
945
    // Allows SkAndroidCodec to call handleFrameIndex (potentially decoding a prior frame and
946
    // clearing to transparent) without SkCodec itself calling it, too.
947
    bool fUsingCallbackForHandleFrameIndex = false;
948
949
    bool initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha, bool srcIsOpaque);
950
951
    /**
952
     *  Return whether these dimensions are supported as a scale.
953
     *
954
     *  The codec may choose to cache the information about scale and subset.
955
     *  Either way, the same information will be passed to onGetPixels/onStart
956
     *  on success.
957
     *
958
     *  This must return true for a size returned from getScaledDimensions.
959
     */
960
84.0k
    bool dimensionsSupported(const SkISize& dim) {
961
84.0k
        return dim == this->dimensions() || this->onDimensionsSupported(dim);
962
84.0k
    }
963
964
    /**
965
     *  For multi-framed images, return the object with information about the frames.
966
     */
967
0
    virtual const SkFrameHolder* getFrameHolder() const {
968
0
        return nullptr;
969
0
    }
970
971
    // Callback for decoding a prior frame. The `Options::fFrameIndex` is ignored,
972
    // being replaced by frameIndex. This allows opts to actually be a subclass of
973
    // SkCodec::Options which SkCodec itself does not know how to copy or modify,
974
    // but just passes through to the caller (where it can be reinterpret_cast'd).
975
    using GetPixelsCallback = std::function<Result(const SkImageInfo&, void* pixels,
976
                                                   size_t rowBytes, const Options& opts,
977
                                                   int frameIndex)>;
978
979
    /**
980
     *  Check for a valid Options.fFrameIndex, and decode prior frames if necessary.
981
     *
982
     * If GetPixelsCallback is not null, it will be used to decode a prior frame instead
983
     * of using this SkCodec directly. It may also be used recursively, if that in turn
984
     * depends on a prior frame. This is used by SkAndroidCodec.
985
     */
986
    Result handleFrameIndex(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&,
987
                            GetPixelsCallback = nullptr);
988
989
    // Methods for scanline decoding.
990
    virtual Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
991
0
            const Options& /*options*/) {
992
0
        return kUnimplemented;
993
0
    }
994
995
    virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
996
4.85k
            const Options&) {
997
4.85k
        return kUnimplemented;
998
4.85k
    }
999
1000
0
    virtual Result onIncrementalDecode(int*) {
1001
0
        return kUnimplemented;
1002
0
    }
1003
1004
1005
0
    virtual bool onSkipScanlines(int /*countLines*/) { return false; }
1006
1007
0
    virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
1008
1009
    /**
1010
     * On an incomplete decode, getPixels() and getScanlines() will call this function
1011
     * to fill any uinitialized memory.
1012
     *
1013
     * @param dstInfo        Contains the destination color type
1014
     *                       Contains the destination alpha type
1015
     *                       Contains the destination width
1016
     *                       The height stored in this info is unused
1017
     * @param dst            Pointer to the start of destination pixel memory
1018
     * @param rowBytes       Stride length in destination pixel memory
1019
     * @param zeroInit       Indicates if memory is zero initialized
1020
     * @param linesRequested Number of lines that the client requested
1021
     * @param linesDecoded   Number of lines that were successfully decoded
1022
     */
1023
    void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
1024
            ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
1025
1026
    /**
1027
     *  Return an object which will allow forcing scanline decodes to sample in X.
1028
     *
1029
     *  May create a sampler, if one is not currently being used. Otherwise, does
1030
     *  not affect ownership.
1031
     *
1032
     *  Only valid during scanline decoding or incremental decoding.
1033
     */
1034
1.61k
    virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
1035
1036
    friend class DM::CodecSrc;  // for fillIncompleteImage
1037
    friend class PNGCodecGM;    // for fillIncompleteImage
1038
    friend class SkSampledCodec;
1039
    friend class SkIcoCodec;
1040
    friend class SkAndroidCodec; // for fEncodedInfo
1041
    friend class SkPDFBitmap; // for fEncodedInfo
1042
};
1043
1044
namespace SkCodecs {
1045
1046
using DecodeContext = void*;
1047
using IsFormatCallback = bool (*)(const void* data, size_t len);
1048
using MakeFromStreamCallback = std::unique_ptr<SkCodec> (*)(std::unique_ptr<SkStream>,
1049
                                                            SkCodec::Result*,
1050
                                                            DecodeContext);
1051
1052
struct SK_API Decoder {
1053
    // By convention, we use all lowercase letters and go with the primary filename extension.
1054
    // For example "png", "jpg", "ico", "webp", etc
1055
    std::string_view id;
1056
    IsFormatCallback isFormat;
1057
    MakeFromStreamCallback makeFromStream;
1058
};
1059
1060
// Add the decoder to the end of a linked list of decoders, which will be used to identify calls to
1061
// SkCodec::MakeFromStream. If a decoder with the same id already exists, this new decoder
1062
// will replace the existing one (in the same position). This is not thread-safe, so make sure all
1063
// initialization is done before the first call.
1064
void SK_API Register(Decoder d);
1065
1066
/**
1067
 *  Return a SkImage produced by the codec, but attempts to defer image allocation until the
1068
 *  image is actually used/drawn. This deferral allows the system to cache the result, either on the
1069
 *  CPU or on the GPU, depending on where the image is drawn. If memory is low, the cache may
1070
 *  be purged, causing the next draw of the image to have to re-decode.
1071
 *
1072
 *  If alphaType is nullopt, the image's alpha type will be chosen automatically based on the
1073
 *  image format. Transparent images will default to kPremul_SkAlphaType. If alphaType contains
1074
 *  kPremul_SkAlphaType or kUnpremul_SkAlphaType, that alpha type will be used. Forcing opaque
1075
 *  (passing kOpaque_SkAlphaType) is not allowed, and will return nullptr.
1076
 *
1077
 *  @param codec    A non-null codec (e.g. from SkPngDecoder::Decode)
1078
 *  @return         created SkImage, or nullptr
1079
 */
1080
SK_API sk_sp<SkImage> DeferredImage(std::unique_ptr<SkCodec> codec,
1081
                                    std::optional<SkAlphaType> alphaType = std::nullopt);
1082
}
1083
1084
#endif // SkCodec_DEFINED