我正在尝试将libpng/apng移植到Android平台,使用带有apng补丁的libpng来读取动画png文件。
我的问题是我没有找到在 png.h 中声明的任何"跳过"方法。我想做的是直接跳转到特定帧。但是除非我从头开始阅读并为前面的每一帧执行 png_read_frame_head() 和 png_read_image(),否则我无法获得正确的结果。
有没有办法通过指定索引来跳转到特定帧而无需读取前面的所有帧信息/数据?
以下代码来自 apng 示例 http://littlesvr.ca/apng/tutorial/x57.html 您可以看到它在循环中读取 apng 文件。而且似乎你必须调用png_read_frame_head()和png_read_image()才能使png_ptr_read和info_ptr_read中的内部信息更新。因此,如果有任何方法可以简单地修改这两个结构以更正为读取特定帧而准备的信息,那么我的问题就解决了。
for(count = 0; count < png_get_num_frames(png_ptr_read, info_ptr_read); count++)
{
sprintf(filename, "extracted-%02d.png", count);
newImage = fopen(filename, "wb");
if(newImage == NULL)
fatalError("couldn't create png for writing");
writeSetup(newImage, &png_ptr_write, &info_ptr_write);
if(setjmp(png_ptr_write->jmpbuf))
fatalError("something didn't work, jump 2");
png_read_frame_head(png_ptr_read, info_ptr_read);
if(png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_fcTL))
{
png_get_next_frame_fcTL(png_ptr_read, info_ptr_read,
&next_frame_width, &next_frame_height,
&next_frame_x_offset, &next_frame_y_offset,
&next_frame_delay_num, &next_frame_delay_den,
&next_frame_dispose_op, &next_frame_blend_op);
}
else
{
/* the first frame doesn't have an fcTL so it's expected to be hidden,
* but we'll extract it anyway */
next_frame_width = png_get_image_width(png_ptr_read, info_ptr_read);
next_frame_height = png_get_image_height(png_ptr_read, info_ptr_read);
}
writeSetup2(png_ptr_read, info_ptr_read, png_ptr_write, info_ptr_write,
next_frame_width, next_frame_height);
png_write_info(png_ptr_write, info_ptr_write);
png_read_image(png_ptr_read, rowPointers);
png_write_image(png_ptr_write, rowPointers);
png_write_end(png_ptr_write, NULL);
png_destroy_write_struct(&png_ptr_write, &info_ptr_write);
fclose(newImage);
printf("extracted frame %d into %sn", count, filename);
}
libpng 旨在将 PNG 数据视为流,因此它按顺序逐个解码块。不知道为什么需要跳过 APNG 帧。就像在视频格式中一样,一帧可能存储为"上一帧之后更改的内容",而不是全帧,因此您可能也需要前一帧。
这些代码示例可能很有用:https://sourceforge.net/projects/apng/files/libpng/examples/