32 const SkImageInfo&
GetInfo()
override;
42 unsigned int frame_index)
override;
51 unsigned int frame_index,
52 std::optional<unsigned int> prior_frame)
override;
60 static constexpr std::array<uint8_t, 8>
kPngSignature = {137, 80, 78, 71,
64 static constexpr size_t kChunkCrcSize = 4;
67 static constexpr size_t kFrameDataSequenceNumberSize = 4;
70 kImageHeaderChunkType =
'IHDR',
71 kAnimationControlChunkType =
'acTL',
72 kImageDataChunkType =
'IDAT',
73 kFrameControlChunkType =
'fcTL',
74 kFrameDataChunkType =
'fdAT',
75 kImageTrailerChunkType =
'IEND',
83 void UpdateChunkCrc32();
86 uint32_t ComputeChunkCrc32();
89 class __attribute__((packed, aligned(1))) ImageHeaderChunkData {
99 class __attribute__((packed, aligned(1))) AnimationControlChunkData {
104 class __attribute__((packed, aligned(1))) FrameControlChunkData {
129 std::unique_ptr<SkCodec> codec;
132 std::vector<uint8_t> pixels;
135 std::optional<ImageGenerator::FrameInfo> frame_info;
138 unsigned int x_offset;
141 unsigned int y_offset;
144 APNGImageGenerator(sk_sp<SkData>&
data,
145 SkImageInfo& image_info,
146 APNGImage&& default_image,
147 unsigned int frame_count,
148 unsigned int play_count,
149 const void* next_chunk_p,
150 const std::vector<uint8_t>& header);
152 static bool IsValidChunkHeader(
const void* buffer,
154 const ChunkHeader* chunk);
156 static const ChunkHeader* GetNextChunk(
const void* buffer,
158 const ChunkHeader* current_chunk);
163 template <
typename T>
164 static constexpr const T* CastChunkData(
const ChunkHeader* chunk) {
165 if constexpr (std::is_same_v<T, ImageHeaderChunkData>) {
166 FML_DCHECK(chunk->get_type() == kImageHeaderChunkType);
167 }
else if constexpr (std::is_same_v<T, AnimationControlChunkData>) {
168 FML_DCHECK(chunk->get_type() == kAnimationControlChunkType);
169 }
else if constexpr (std::is_same_v<T, FrameControlChunkData>) {
170 FML_DCHECK(chunk->get_type() == kFrameControlChunkType);
172 static_assert(!
sizeof(T),
"Invalid chunk struct");
175 return reinterpret_cast<const T*
>(
reinterpret_cast<const uint8_t*
>(chunk) +
176 sizeof(ChunkHeader));
179 static constexpr size_t GetChunkSize(
const ChunkHeader* chunk) {
180 return sizeof(ChunkHeader) + chunk->get_data_length() + kChunkCrcSize;
183 static constexpr bool IsChunkCopySafe(
const ChunkHeader* chunk) {
186 return (chunk->get_type() & 0x20) != 0;
191 static std::pair<std::optional<std::vector<uint8_t>>,
const void*>
192 ExtractHeader(
const void* buffer_p,
size_t buffer_size);
198 static std::pair<std::optional<APNGImage>,
const void*> DemuxNextImage(
199 const void* buffer_p,
201 const std::vector<uint8_t>& header,
202 const void* chunk_p);
204 bool DemuxNextImageInternal();
206 bool DemuxToImageIndex(
unsigned int image_index);
208 bool RenderDefaultImage(
const SkImageInfo& info,
214 SkImageInfo image_info_;
215 unsigned int frame_count_;
216 unsigned int play_count_;
220 std::vector<APNGImage> images_;
222 unsigned int first_frame_index_;
224 const void* next_chunk_p_;
225 std::vector<uint8_t> header_;
bool GetPixels(const SkImageInfo &info, void *pixels, size_t row_bytes, unsigned int frame_index, std::optional< unsigned int > prior_frame) override
Decode the image into a given buffer. This method is currently always used for sub-pixel image decodi...