1 /* 2 * Copyright (c) 2022-2023 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_APNG_IMAGE_PLAYER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_APNG_APNG_IMAGE_PLAYER_H 18 19 #include <unordered_map> 20 21 #include "base/memory/ace_type.h" 22 #include "core/animation/animator.h" 23 #include "apng_image_animation.h" 24 #include "core/image/image_source_info.h" 25 #include "core/image/image_provider.h" 26 #include "apng_image_decoder.h" 27 #include "core/pipeline/base/scoped_canvas_state.h" 28 29 namespace OHOS::Ace { 30 31 /** 32 Dispose method specifies how the area used by the current frame is to be treated 33 before rendering the next frame on the canvas. 34 */ 35 typedef enum { 36 /** 37 No disposal is done on this frame before rendering the next; the contents 38 of the canvas are left as is. 39 */ 40 ImageDisposeNone = 0, 41 42 /** 43 The frame's region of the canvas is to be cleared to fully transparent black 44 before rendering the next frame. 45 */ 46 ImageDisposeBackground, 47 48 /** 49 The frame's region of the canvas is to be reverted to the previous contents 50 before rendering the next frame. 51 */ 52 ImageDisposePrevious, 53 } ImageDisposeMethod; 54 55 /** 56 Blend operation specifies how transparent pixels of the current frame are 57 blended with those of the previous canvas. 58 */ 59 typedef enum { 60 /** 61 All color components of the frame, including alpha, overwrite the current 62 contents of the frame's canvas region. 63 */ 64 ImageBlendNone = 0, 65 66 /** 67 The frame should be composited onto the output buffer based on its alpha. 68 */ 69 ImageBlendOver, 70 } ImageBlendOperation; 71 72 /** 73 * Apng Header and frames information 74 */ 75 typedef struct { 76 uint32_t index = 0; ///< sequence number of the animation chunk, starting from 0 77 uint32_t width = 0; ///< width of the following frame 78 uint32_t height = 0; ///< height of the following frame 79 uint32_t offsetX = 0; ///< x position at which to render the following frame 80 uint32_t offsetY = 0; ///< y position at which to render the following frame 81 float duration = 0.0; 82 ImageDisposeMethod dispose = ImageDisposeNone; 83 ImageBlendOperation blend = ImageBlendNone; 84 bool isFullSize = false; ///< Whether frame fill the canvas. 85 uint32_t blendFromIndex = 0; ///< Blend from frame index to current frame. 86 #ifndef USE_ROSEN_DRAWING 87 sk_sp<SkImage> image = nullptr; 88 #else 89 std::shared_ptr<RSImage> image = nullptr; 90 #endif 91 } APngAnimatedFrameInfo; 92 93 94 class APngImagePlayer : public virtual AceType { 95 DECLARE_ACE_TYPE(APngImagePlayer, AceType); 96 97 public: 98 APngImagePlayer( 99 ImageSourceInfo source, 100 UploadSuccessCallback successCallback, 101 const WeakPtr<PipelineBase>& weakContext, 102 const RefPtr<PNGImageDecoder>& decoder, 103 int32_t dstWidth = -1, 104 int32_t dstHeight = -1); 105 106 ~APngImagePlayer() override; 107 108 void Pause(); 109 110 void Resume(); 111 112 void RenderFrame(const int32_t& index); 113 114 /** 115 * Use for draw each frame image in self 116 **/ 117 void Paint(const flutter::Paint& paint, const Offset& offset, const ScopedCanvas& canvas, const Rect& paintRect); 118 SetTargetSize(int32_t width,int32_t height)119 void SetTargetSize(int32_t width, int32_t height) 120 { 121 dstWidth_ = width; 122 dstHeight_ = height; 123 } 124 125 private: 126 ImageSourceInfo imageSource_; 127 UploadSuccessCallback successCallback_; 128 WeakPtr<PipelineBase> context_; 129 130 const RefPtr<PNGImageDecoder> apngDecoder_; 131 int32_t frameCount_; 132 int32_t repetitionCount_; 133 bool needBlend_; 134 int32_t blendFrameIndex_; 135 int32_t width_; //image source width 136 int32_t height_; 137 std::vector<APngAnimatedFrameInfo> frameInfos_; 138 139 int32_t dstWidth_ = -1; 140 int32_t dstHeight_ = -1; 141 142 // used to cache required frame. 143 std::unordered_map<int32_t, std::unique_ptr<APngAnimatedFrameInfo *>> cachedFrame_; 144 145 // used to cache last required frame. this will be reset during looping. 146 int32_t lastRequiredFrameIndex_ = -1; 147 148 /** 149 * Use a blank canvas draw each frame to get frame image 150 **/ 151 #ifndef USE_ROSEN_DRAWING 152 SkBitmap bitmap_; 153 SkCanvas *blendCanvas_ = nullptr; 154 #else 155 RSBitmap bitmap_; 156 RSCanvas *blendCanvas_ = nullptr; 157 #endif 158 RefPtr<Scheduler> scheduler_; 159 RefPtr<APngImageAnimation> pictureAnimation_; 160 161 /** 162 * Decode apng image and get all frame head information 163 * but didn't decode image data 164 **/ 165 bool GetApngAllFrames(); 166 167 /** 168 * Decode frame image data to SKImage 169 * Before decode frame need decode frame header before 170 **/ 171 APngAnimatedFrameInfo *DecodeFrameImage(const int32_t &index); 172 173 /** 174 * Copy bitmap to a dst bitmap 175 **/ 176 #ifndef USE_ROSEN_DRAWING 177 static bool CopyTo(SkBitmap *dst, const SkBitmap &src); 178 #else 179 static bool CopyTo(RSBitmap *dst, const RSBitmap &src); 180 #endif 181 182 float DelayToSeconds(uint16_t num, uint16_t den); 183 184 #ifndef USE_ROSEN_DRAWING 185 SkCanvas *CreateBlendCanvas(); 186 187 /** 188 * Get frame image with index or frameinfo 189 **/ 190 sk_sp<SkImage> GetImage(const int32_t &index, bool extendToCanvas); 191 192 sk_sp<SkImage> GetImage(const APngAnimatedFrameInfo *frameInfo); 193 #else 194 RSCanvas *CreateBlendCanvas(); 195 196 /** 197 * Get frame image with index or frameinfo 198 **/ 199 std::shared_ptr<RSImage> GetImage(const int32_t &index, bool extendToCanvas); 200 201 std::shared_ptr<RSImage> GetImage(const APngAnimatedFrameInfo *frameInfo); 202 #endif 203 204 /** 205 * Before render image in backgroud thread predecode image all frames 206 **/ 207 bool PreDecodeAllFrames(); 208 209 void ClearCanvasRect(const APngAnimatedFrameInfo *frameInfo); 210 211 /** 212 * Use blend role draw frame image to canvas 213 */ 214 void BlendImage(const APngAnimatedFrameInfo *frameInfo); 215 216 /*** 217 * Debug function 218 * */ 219 void DrawTest(); 220 221 #ifndef USE_ROSEN_DRAWING 222 void DrawTestBorder(SkRect &rect); 223 #else 224 void DrawTestBorder(RSRect &rect); 225 #endif 226 }; 227 228 } // namespace OHOS::Ace 229 230 231 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_APNG_APNG_IMAGE_PLAYER_H 232