1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PNG_DECODER_H
17 #define PNG_DECODER_H
18 
19 #include "abs_image_decoder.h"
20 #include "input_data_stream.h"
21 #include "nine_patch_listener.h"
22 #include "plugin_class_base.h"
23 #include "png.h"
24 
25 namespace OHOS {
26 namespace ImagePlugin {
27 using namespace Media;
28 
29 enum class PngDecodingState : int32_t {
30     UNDECIDED = 0,
31     SOURCE_INITED = 1,
32     BASE_INFO_PARSING = 2,
33     BASE_INFO_PARSED = 3,
34     IMAGE_DECODING = 4,
35     IMAGE_ERROR = 5,
36     IMAGE_PARTIAL = 6,
37     IMAGE_DECODED = 7
38 };
39 
40 struct PngImageInfo {
41     uint32_t width = 0;
42     uint32_t height = 0;
43     uint8_t bitDepth = 0;
44     uint32_t rowDataSize = 0;
45     int32_t numberPasses = 0;  // interlace is 7 otherwise is 1.
46 };
47 
48 class PngDecoder : public AbsImageDecoder, public OHOS::MultimediaPlugin::PluginClassBase {
49 public:
50     PngDecoder();
51     ~PngDecoder() override;
52     PngDecoder(const PngDecoder &) = delete;
53     PngDecoder &operator=(const PngDecoder &) = delete;
54     void SetSource(InputDataStream &sourceStream) override;
55     void Reset() override;
56     uint32_t SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info) override;
57     uint32_t Decode(uint32_t index, DecodeContext &context) override;
58     uint32_t PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context) override;
59     uint32_t GetImageSize(uint32_t index, Size &size) override;
60     bool HasProperty(std::string key) override;
61 #ifdef IMAGE_COLORSPACE_FLAG
IsSupportICCProfile()62     bool IsSupportICCProfile() override
63     {
64         return false;
65     }
66 #endif
67 
68 private:
69     uint32_t GetDecodeFormat(PixelFormat format, PixelFormat &outputFormat, AlphaType &alphaType);
70     void ChooseFormat(PixelFormat format, PixelFormat &outputFormat, png_byte destType);
71     static void PngErrorExit(png_structp pngPtr, png_const_charp message);
72     static void PngWarning(png_structp pngPtr, png_const_charp message);
73     static void PngWarningMessage(png_structp pngPtr, png_const_charp message);
74     static void PngErrorMessage(png_structp pngPtr, png_const_charp message);
75     // incremental private interface
76     uint32_t PushCurrentToDecode(InputDataStream *stream);
77     uint32_t IncrementalReadRows(InputDataStream *stream);
78     uint32_t PushAllToDecode(InputDataStream *stream, size_t bufferSize, size_t length);
79     static void GetAllRows(png_structp pngPtr, png_bytep row, png_uint_32 rowNum, int pass);
80     static void GetInterlacedRows(png_structp pngPtr, png_bytep row, png_uint_32 rowNum, int pass);
81     static int32_t ReadUserChunk(png_structp png_ptr, png_unknown_chunkp chunk);
82     void SaveRows(png_bytep row, png_uint_32 rowNum);
83     void SaveInterlacedRows(png_bytep row, png_uint_32 rowNum, int pass);
84     uint32_t ReadIncrementalHead(InputDataStream *stream, PngImageInfo &info);
85     bool GetImageInfo(PngImageInfo &info);
86     bool IsChunk(const png_byte *chunk, const char *flag);
87     uint32_t ProcessData(png_structp pngPtr, png_infop infoPtr, InputDataStream *sourceStream,
88                          DataStreamBuffer streamData, size_t bufferSize, size_t totalSize);
89     bool ConvertOriginalFormat(png_byte source, png_byte &destination);
90     uint8_t *AllocOutputBuffer(DecodeContext &context);
91     uint32_t IncrementalRead(InputDataStream *stream, uint32_t desiredSize, DataStreamBuffer &outData);
92     uint32_t DecodeHeader();
93     uint32_t ConfigInfo(const PixelDecodeOptions &opts);
94     uint32_t DoOneTimeDecode(DecodeContext &context);
95     bool FinishOldDecompress();
96     bool InitPnglib();
97     uint32_t GetImageIdatSize(InputDataStream *stream);
98     void DealNinePatch(const PixelDecodeOptions &opts);
99     // local private parameter
100     const std::string NINE_PATCH = "ninepatch";
101     png_structp pngStructPtr_ = nullptr;
102     png_infop pngInfoPtr_ = nullptr;
103     InputDataStream *inputStreamPtr_ = nullptr;
104     PngImageInfo pngImageInfo_;
105     bool decodedIdat_ = false;
106     size_t idatLength_ = 0;
107     size_t incrementalLength_ = 0;
108     uint8_t *pixelsData_ = nullptr;
109     uint32_t outputRowsNum_ = 0;
110     PngDecodingState state_ = PngDecodingState::UNDECIDED;
111     uint32_t streamPosition_ = 0;  // may be changed by other decoders, record it and restore if needed.
112     PixelFormat outputFormat_ = PixelFormat::UNKNOWN;
113     AlphaType alphaType_ = AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
114     PixelDecodeOptions opts_;
115     bool decodeHeadFlag_ = false;
116     uint32_t firstRow_ = 0;
117     uint32_t lastRow_ = 0;
118     bool interlacedComplete_ = false;
119     NinePatchListener ninePatch_;
120 };
121 } // namespace ImagePlugin
122 } // namespace OHOS
123 
124 #endif // PNG_DECODER_H
125