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