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