42 unsigned int frame_index)
override;
51 unsigned int frame_index,
52 std::optional<unsigned int> prior_frame)
override;
57 static constexpr uint8_t kPngSignature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
58 static constexpr size_t kChunkCrcSize = 4;
61 kImageHeaderChunkType =
'IHDR',
62 kAnimationControlChunkType =
'acTL',
63 kImageDataChunkType =
'IDAT',
64 kFrameControlChunkType =
'fcTL',
65 kFrameDataChunkType =
'fdAT',
66 kImageTrailerChunkType =
'IEND',
74 void UpdateChunkCrc32();
77 uint32_t ComputeChunkCrc32();
80 class __attribute__((packed, aligned(1))) ImageHeaderChunkData {
90 class __attribute__((packed, aligned(1))) AnimationControlChunkData {
95 class __attribute__((packed, aligned(1))) FrameControlChunkData {
120 std::unique_ptr<SkCodec> codec;
123 std::vector<uint8_t> pixels;
126 std::optional<ImageGenerator::FrameInfo> frame_info;
129 unsigned int x_offset;
132 unsigned int y_offset;
137 APNGImage&& default_image,
138 unsigned int frame_count,
139 unsigned int play_count,
140 const void* next_chunk_p,
141 const std::vector<uint8_t>&
header);
143 static bool IsValidChunkHeader(
const void*
buffer,
145 const ChunkHeader* chunk);
147 static const ChunkHeader* GetNextChunk(
const void*
buffer,
149 const ChunkHeader* current_chunk);
154 template <
typename T>
155 static constexpr const T* CastChunkData(
const ChunkHeader* chunk) {
156 if constexpr (std::is_same_v<T, ImageHeaderChunkData>) {
157 FML_DCHECK(chunk->get_type() == kImageHeaderChunkType);
158 }
else if constexpr (std::is_same_v<T, AnimationControlChunkData>) {
159 FML_DCHECK(chunk->get_type() == kAnimationControlChunkType);
160 }
else if constexpr (std::is_same_v<T, FrameControlChunkData>) {
161 FML_DCHECK(chunk->get_type() == kFrameControlChunkType);
163 static_assert(!
sizeof(
T),
"Invalid chunk struct");
166 return reinterpret_cast<const T*
>(
reinterpret_cast<const uint8_t*
>(chunk) +
167 sizeof(ChunkHeader));
170 static constexpr size_t GetChunkSize(
const ChunkHeader* chunk) {
171 return sizeof(ChunkHeader) + chunk->get_data_length() + kChunkCrcSize;
174 static constexpr bool IsChunkCopySafe(
const ChunkHeader* chunk) {
177 return (chunk->get_type() & 0x20) != 0;
182 static std::pair<std::optional<std::vector<uint8_t>>,
const void*>
183 ExtractHeader(
const void* buffer_p,
size_t buffer_size);
189 static std::pair<std::optional<APNGImage>,
const void*> DemuxNextImage(
190 const void* buffer_p,
192 const std::vector<uint8_t>&
header,
193 const void* chunk_p);
195 bool DemuxNextImageInternal();
197 bool DemuxToImageIndex(
unsigned int image_index);
206 unsigned int frame_count_;
207 unsigned int play_count_;
211 std::vector<APNGImage> images_;
213 unsigned int first_frame_index_;
215 const void* next_chunk_p_;
216 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...