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