xref: /aosp_15_r20/external/skia/src/codec/SkPngCodecBase.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2024 Google LLC.
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 #ifndef SkPngCodecBase_DEFINED
8 #define SkPngCodecBase_DEFINED
9 
10 #include <cstddef>
11 #include <cstdint>
12 #include <memory>
13 #include <optional>
14 
15 #include "include/codec/SkCodec.h"
16 #include "include/core/SkRefCnt.h"
17 #include "include/private/SkEncodedInfo.h"
18 #include "include/private/base/SkDebug.h"
19 #include "include/private/base/SkTemplates.h"
20 
21 class SkColorPalette;
22 class SkSampler;
23 class SkStream;
24 class SkSwizzler;
25 enum class SkEncodedImageFormat;
26 struct SkImageInfo;
27 template <typename T> class SkSpan;
28 
29 // This class implements functionality shared between `SkPngCodec` and
30 // `SkPngRustCodec` (the latter is from `experimental/rust_png`).
31 class SkPngCodecBase : public SkCodec {
32 public:
33     ~SkPngCodecBase() override;
34 
35     static bool isCompatibleColorProfileAndType(const SkEncodedInfo::ICCProfile* profile,
36                                                 SkEncodedInfo::Color color);
37 protected:
38     SkPngCodecBase(SkEncodedInfo&&, std::unique_ptr<SkStream>);
39 
40     // Initialize most fields needed by `applyXformRow`.
41     //
42     // Each call to `applyXformRow` will transform `frameWidth` pixels
43     // (which may be less than `dstInfo.width()` when decoding frames that
44     // depend on earlier frames).
45     Result initializeXforms(const SkImageInfo& dstInfo, const Options& options, int frameWidth);
46 
47     // Initialize other fields needed by `applyXformRow`.
48     //
49     // Needs to be called *after* (i.e. outside of) `onStartIncrementalDecode`.
50     void initializeXformParams();
51 
52     // Transforms a decoded row into the `dstInfo` format that was earlier
53     // passed to `initializeXforms`.
54     //
55     // The first bytes/pixels of `srcRow` will be transformed into the first
56     // bytes/pixels of `dstRow`.  In other words, the transformation ignores
57     // `fcTL.x_offset` field - the caller should offset `dstRow` if desired
58     // (it may not be desirable when working with interlaced rows which are
59     // first transformed into an intermediate buffer).
60     void applyXformRow(SkSpan<uint8_t> dstRow, SkSpan<const uint8_t> srcRow);
61     void applyXformRow(void* dstRow, const uint8_t* srcRow);
62 
getEncodedRowBytes()63     size_t getEncodedRowBytes() const { return fEncodedRowBytes; }
swizzler()64     const SkSwizzler* swizzler() const { return fSwizzler.get(); }
65 
66     struct PaletteColorEntry {
67         uint8_t red;
68         uint8_t green;
69         uint8_t blue;
70     };
71     virtual std::optional<SkSpan<const PaletteColorEntry>> onTryGetPlteChunk() = 0;
72     virtual std::optional<SkSpan<const uint8_t>> onTryGetTrnsChunk() = 0;
73 
74 private:
75     // SkCodec overrides:
76     SkEncodedImageFormat onGetEncodedFormat() const final;
77     SkSampler* getSampler(bool createIfNecessary) final;
78 
79     void allocateStorage(const SkImageInfo& dstInfo);
80     Result initializeSwizzler(const SkImageInfo& dstInfo,
81                               const Options& options,
82                               bool skipFormatConversion,
83                               int frameWidth);
84     bool createColorTable(const SkImageInfo& dstInfo);
85 
86     enum XformMode {
87         // Requires only a swizzle pass.
88         kSwizzleOnly_XformMode,
89 
90         // Requires only a color xform pass.
91         kColorOnly_XformMode,
92 
93         // Requires a swizzle and a color xform.
94         kSwizzleColor_XformMode,
95     };
96     XformMode fXformMode;
97 
98     std::unique_ptr<SkSwizzler> fSwizzler;
99     skia_private::AutoTMalloc<uint8_t> fStorage;
100     int fXformWidth = -1;
101     sk_sp<SkColorPalette> fColorTable;  // May be unpremul.
102 
103     size_t fEncodedRowBytes = 0;  // Size of encoded/source row in bytes.
104 #if defined(SK_DEBUG)
105     size_t fDstRowBytes = 0;      // Size of destination row in bytes.
106 #endif
107 };
108 
109 #endif  // SkPngCodecBase_DEFINED
110