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 uint8_t kPngSignature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
61 static constexpr size_t kChunkCrcSize = 4;
64 static constexpr size_t kFrameDataSequenceNumberSize = 4;
67 kImageHeaderChunkType =
'IHDR',
68 kAnimationControlChunkType =
'acTL',
69 kImageDataChunkType =
'IDAT',
70 kFrameControlChunkType =
'fcTL',
71 kFrameDataChunkType =
'fdAT',
72 kImageTrailerChunkType =
'IEND',
80 void UpdateChunkCrc32();
83 uint32_t ComputeChunkCrc32();
86 class __attribute__((packed, aligned(1))) ImageHeaderChunkData {
96 class __attribute__((packed, aligned(1))) AnimationControlChunkData {
101 class __attribute__((packed, aligned(1))) FrameControlChunkData {
126 std::unique_ptr<SkCodec> codec;
129 std::vector<uint8_t> pixels;
132 std::optional<ImageGenerator::FrameInfo> frame_info;
135 unsigned int x_offset;
138 unsigned int y_offset;
141 APNGImageGenerator(sk_sp<SkData>&
data,
142 SkImageInfo& image_info,
143 APNGImage&& default_image,
144 unsigned int frame_count,
145 unsigned int play_count,
146 const void* next_chunk_p,
147 const std::vector<uint8_t>& header);
149 static bool IsValidChunkHeader(
const void* buffer,
151 const ChunkHeader* chunk);
153 static const ChunkHeader* GetNextChunk(
const void* buffer,
155 const ChunkHeader* current_chunk);
160 template <
typename T>
161 static constexpr const T* CastChunkData(
const ChunkHeader* chunk) {
162 if constexpr (std::is_same_v<T, ImageHeaderChunkData>) {
163 FML_DCHECK(chunk->get_type() == kImageHeaderChunkType);
164 }
else if constexpr (std::is_same_v<T, AnimationControlChunkData>) {
165 FML_DCHECK(chunk->get_type() == kAnimationControlChunkType);
166 }
else if constexpr (std::is_same_v<T, FrameControlChunkData>) {
167 FML_DCHECK(chunk->get_type() == kFrameControlChunkType);
169 static_assert(!
sizeof(T),
"Invalid chunk struct");
172 return reinterpret_cast<const T*
>(
reinterpret_cast<const uint8_t*
>(chunk) +
173 sizeof(ChunkHeader));
176 static constexpr size_t GetChunkSize(
const ChunkHeader* chunk) {
177 return sizeof(ChunkHeader) + chunk->get_data_length() + kChunkCrcSize;
180 static constexpr bool IsChunkCopySafe(
const ChunkHeader* chunk) {
183 return (chunk->get_type() & 0x20) != 0;
188 static std::pair<std::optional<std::vector<uint8_t>>,
const void*>
189 ExtractHeader(
const void* buffer_p,
size_t buffer_size);
195 static std::pair<std::optional<APNGImage>,
const void*> DemuxNextImage(
196 const void* buffer_p,
198 const std::vector<uint8_t>& header,
199 const void* chunk_p);
201 bool DemuxNextImageInternal();
203 bool DemuxToImageIndex(
unsigned int image_index);
205 bool RenderDefaultImage(
const SkImageInfo& info,
211 SkImageInfo image_info_;
212 unsigned int frame_count_;
213 unsigned int play_count_;
217 std::vector<APNGImage> images_;
219 unsigned int first_frame_index_;
221 const void* next_chunk_p_;
222 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...