• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_APNG_PNG_IMAGE_DECODER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_APNG_PNG_IMAGE_DECODER_H
18 
19 #include "base/geometry/size.h"
20 #include "base/memory/ace_type.h"
21 
22 #include "third_party/skia/include/core/SkStream.h"
23 #include "third_party/skia/include/core/SkImage.h"
24 
25 namespace OHOS::Ace {
26 /*
27  PNG  spec: http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html
28  APNG spec: https://wiki.mozilla.org/APNG_Specification
29 
30  ===============================================================================
31  PNG format:
32  header (8): 89 50 4e 47 0d 0a 1a 0a
33  chunk, chunk, chunk, ...
34 
35  ===============================================================================
36  chunk format:
37  length (4): uint32_t big endian
38  fourcc (4): chunk type code
39  data   (length): data
40  crc32  (4): uint32_t big endian crc32(fourcc + data)
41 
42  ===============================================================================
43  PNG chunk define:
44 
45  IHDR (Image Header) required, must appear first, 13 bytes
46  width              (4) pixel count, should not be zero
47  height             (4) pixel count, should not be zero
48  bit depth          (1) expected: 1, 2, 4, 8, 16
49  color type         (1) 1<<0 (palette used), 1<<1 (color used), 1<<2 (alpha channel used)
50  compression method (1) 0 (deflate/inflate)
51  filter method      (1) 0 (adaptive filtering with five basic filter types)
52  interlace method   (1) 0 (no interlace) or 1 (Adam7 interlace)
53 
54  IDAT (Image Data) required, must appear consecutively if there's multiple 'IDAT' chunk
55 
56  IEND (End) required, must appear last, 0 bytes
57 
58  ===============================================================================
59  APNG chunk define:
60 
61  acTL (Animation Control) required, must appear before 'IDAT', 8 bytes
62  num frames     (4) number of frames
63  num plays      (4) number of times to loop, 0 indicates infinite looping
64 
65  fcTL (Frame Control) required, must appear before the 'IDAT' or 'fdAT'
66  chunks of the frame to which it applies, 26 bytes
67  sequence number   (4) sequence number of the animation chunk, starting from 0
68  width             (4) width of the following frame
69  height            (4) height of the following frame
70  x offset          (4) x position at which to render the following frame
71  y offset          (4) y position at which to render the following frame
72  delay num         (2) frame delay fraction numerator
73  delay den         (2) frame delay fraction denominator
74  dispose op        (1) type of frame area disposal to be done after rendering this frame
75                        (0:none, 1:background 2:previous)
76  blend op          (1) type of frame area rendering for this frame (0:source, 1:over)
77 
78  fdAT (Frame Data) required
79  sequence number   (4) sequence number of the animation chunk
80  frame data        (x) frame data for this frame (same as 'IDAT')
81 
82  ===============================================================================
83  `dispose_op` specifies how the output buffer should be changed at the end of the delay
84  (before rendering the next frame).
85 
86  * NONE: no disposal is done on this frame before rendering the next; the contents
87     of the output buffer are left as is.
88  * BACKGROUND: the frame's region of the output buffer is to be cleared to fully
89     transparent black before rendering the next frame.
90  * PREVIOUS: the frame's region of the output buffer is to be reverted to the previous
91     contents before rendering the next frame.
92 
93  `blend_op` specifies whether the frame is to be alpha blended into the current output buffer
94  content, or whether it should completely replace its region in the output buffer.
95 
96  * SOURCE: all color components of the frame, including alpha, overwrite the current contents
97     of the frame's output buffer region.
98  * OVER: the frame should be composited onto the output buffer based on its alpha,
99     using a simple OVER operation as described in the "Alpha Channel Processing" section
100     of the PNG specification
101  */
102 
103 /**
104  * PNG & APNG Alpha type
105  **/
106 typedef enum {
107     PNG_ALPHA_TYPE_PALEETE = 1 << 0,
108     PNG_ALPHA_TYPE_COLOR = 1 << 1,
109     PNG_ALPHA_TYPE_ALPHA = 1 << 2
110 } PngAlphaType;
111 
112 typedef enum {
113     PNG_DISPOSE_OP_NONE = 0,
114     PNG_DISPOSE_OP_BACKGROUND = 1,
115     PNG_DISPOSE_OP_PREVIOUS = 2
116 } PngDisposeOp;
117 
118 /**
119  * APNG image blend mode
120  **/
121 typedef enum {
122     PNG_BLEND_OP_SOURCE = 0,
123     PNG_BLEND_OP_OVER = 1
124 } PngBlendOp;
125 
126 /**
127  * IHDR (Image Header) required, must appear first, 13 bytes
128  * width              (4) pixel count, should not be zero
129  * height             (4) pixel count, should not be zero
130  * bit depth          (1) expected: 1, 2, 4, 8, 16
131  * color type         (1) 1<<0 (palette used), 1<<1 (color used), 1<<2 (alpha channel used)
132  * compression method (1) 0 (deflate/inflate)
133  * filter method      (1) 0 (adaptive filtering with five basic filter types)
134  * interlace method   (1) 0 (no interlace) or 1 (Adam7 interlace)
135  **/
136 typedef struct {
137     uint32_t width = 0;             ///< pixel count, should not be zero
138     uint32_t height = 0;            ///< pixel count, should not be zero
139     uint8_t bitDepth = 0;          ///< expected: 1, 2, 4, 8, 16
140     uint8_t colorType = 0;         ///< see PngAlphaType
141     uint8_t compressionMethod = 0; ///< 0 (deflate/inflate)
142     uint8_t filterMethod = 0;      ///< 0 (adaptive filtering with five basic filter types)
143     uint8_t interlaceMethod = 0;   ///< 0 (no interlace) or 1 (Adam7 interlace)
144 } PngChunkIHDR;
145 
146 /**
147  * fcTL (Frame Control) required, must appear before the 'IDAT' or 'fdAT'
148  * chunks of the frame to which it applies, 26 bytes
149  * sequence number   (4) sequence number of the animation chunk, starting from 0
150  * width             (4) width of the following frame
151  * height            (4) height of the following frame
152  * x offset          (4) x position at which to render the following frame
153  * y offset          (4) y position at which to render the following frame
154  * delay num         (2) frame delay fraction numerator
155  * delay den         (2) frame delay fraction denominator
156  * dispose op        (1) type of frame area disposal to be done after rendering this frame
157  *                       (0:none, 1:background 2:previous)
158  * blend op          (1) type of frame area rendering for this frame (0:source, 1:over)
159  **/
160 typedef struct {
161     uint32_t sequenceNumber = 0;  ///< sequence number of the animation chunk, starting from 0
162     uint32_t width = 0;            ///< width of the following frame
163     uint32_t height = 0;           ///< height of the following frame
164     uint32_t xOffset = 0;         ///< x position at which to render the following frame
165     uint32_t yOffset = 0;         ///< y position at which to render the following frame
166     uint16_t delayNum = 0;        ///< frame delay fraction numerator
167     uint16_t delayDen = 0;        ///< frame delay fraction denominator
168     uint8_t disposeOp = 0;        ///< see PngDisposeOp
169     uint8_t blendOp = 0;          ///< see PngBlendOp
170 } PngChunkfcTL;
171 
172 /**
173  * Chunk information
174  * use for identifier echo chunk data info
175  **/
176 typedef struct {
177     uint32_t offset = 0; ///< chunk offset in PNG data
178     uint32_t fourcc = 0; ///< chunk fourcc
179     uint32_t length = 0; ///< chunk data length
180     uint32_t crc32 = 0;  ///< chunk crc32
181 } PngChunkInfo;
182 
183 /**
184  * APNG frame information
185  * contain current chunk index and size
186  * detail frame info in the fcTL
187  **/
188 typedef struct {
189     uint32_t chunkIndex = 0; ///< the first `fdAT`/`IDAT` chunk index
190     uint32_t chunkNum = 0;   ///< the `fdAT`/`IDAT` chunk count
191     uint32_t chunkSize = 0;  ///< the `fdAT`/`IDAT` chunk bytes
192     PngChunkfcTL frameControl;
193 } PngFrameInfo;
194 
195 /**
196  * PNG & APNG file information
197  * png Header and chunk data
198  * apng frames info
199  **/
200 typedef struct {
201     PngChunkIHDR header;   ///< png header
202     PngChunkInfo *chunks;      ///< chunks
203     uint32_t chunkNum;          ///< count of chunks
204 
205     PngFrameInfo *apngFrames; ///< frame info, NULL if not apng
206     uint32_t apngFrameNum;     ///< 0 if not apng
207     uint32_t apngLoopNum;      ///< 0 indicates infinite looping
208 
209     uint32_t *apngSharedChunkIndexs; ///< shared chunk index
210     uint32_t apngSharedChunkNum;     ///< shared chunk count
211     uint32_t apngSharedChunkSize;    ///< shared chunk bytes
212     uint32_t apngSharedInsertIndex;  ///< shared chunk insert index
213     bool apngFirstFrameIsCover;     ///< the first frame is same as png (cover)
214 } PngInfo;
215 
216 class PNGImageDecoder : public virtual AceType {
217     DECLARE_ACE_TYPE(PNGImageDecoder, AceType);
218 
219 public:
220     PNGImageDecoder(const sk_sp<SkData> &data);
221 
222     ~PNGImageDecoder() override;
223 
224     /**
225      * with image header judge whether is a apng file
226      * use for split png and apng file
227      * @return
228      */
229     bool isApng();
230     Size GetImageSize();
231     uint32_t GetFrameCount();
232 
233     /**
234      * Decode apng image header information
235      * @return
236      */
237     bool DecodeImage();
238 
239     /**
240      * Get apng header info and all frames information
241      * @return
242      */
243     PngInfo *GetApngInfo();
244 
245     /**
246      * Get frame image data
247      * i: undecoded image data
248      * @param index
249      * @param size : return data size
250      * @return
251      */
252     uint8_t *GetFrameData(uint32_t index, uint32_t *size, bool oldWay = false);
253     static bool IsApngSource(const std::string& src);
254 private:
255     sk_sp<SkData> data_;
256     PngInfo *pngInfo_ = nullptr;
257     bool dataCheck_ = false;
258     bool isApng_ = false;
259 };
260 } // namespace OHOS::Ace
261 
262 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_PNG_IMAGE_DECODER_H
263