动画 PNG 的特点是存在acTL
(动画控制块),以及fcTL
(帧控制块)-参见维基百科文章.
所以,我认为一个合适的测试是运行pngcheck
使用详细选项,并至少查找acTL
chunk:
pngcheck -v animated.png | grep -E "acTL|fcTL"
样本输出
chunk acTL at offset 0x00025, length 8
chunk fcTL at offset 0x00039, length 26
chunk fcTL at offset 0x02f27, length 26
chunk fcTL at offset 0x05901, length 26
chunk fcTL at offset 0x083a2, length 26
chunk fcTL at offset 0x0aea8, length 26
chunk fcTL at offset 0x0d98c, length 26
chunk fcTL at offset 0x10406, length 26
chunk fcTL at offset 0x12e19, length 26
chunk fcTL at offset 0x15985, length 26
chunk fcTL at offset 0x185e2, length 26
chunk fcTL at offset 0x1b2b0, length 26
chunk fcTL at offset 0x1dfe1, length 26
chunk fcTL at offset 0x20d24, length 26
chunk fcTL at offset 0x23a03, length 26
chunk fcTL at offset 0x26663, length 26
chunk fcTL at offset 0x29218, length 26
chunk fcTL at offset 0x2bcdf, length 26
chunk fcTL at offset 0x2e7e0, length 26
chunk fcTL at offset 0x312b0, length 26
chunk fcTL at offset 0x33c51, length 26
chunk fcTL at offset 0x36598, length 26
chunk fcTL at offset 0x38f49, length 26
chunk fcTL at offset 0x3b9bd, length 26
chunk fcTL at offset 0x3e45e, length 26
chunk fcTL at offset 0x40ed9, length 26
chunk fcTL at offset 0x4393c, length 26
chunk fcTL at offset 0x46521, length 26
chunk fcTL at offset 0x4919b, length 26
chunk fcTL at offset 0x4bde2, length 26
chunk fcTL at offset 0x4eabd, length 26
chunk fcTL at offset 0x51827, length 26
chunk fcTL at offset 0x5453a, length 26
chunk fcTL at offset 0x571c7, length 26
chunk fcTL at offset 0x59d94, length 26
因此,这将建议在脚本中进行此测试:
# Test an animated image, `grep` exit status is zero meaning `acTL` was found
pngcheck -v animated.png | grep -q "acTL"
echo $?
0
# Test a still image, `grep` exit status is 1 meaning `acTL` was not found
pngcheck -v still.png | grep -q "acTL"
echo $?
1
如果您没有或不想发货pngcheck
在你的项目中,我制作了一个 Perl 脚本,它只是对 PNG 文件进行分块并告诉你分块和偏移量,并且它应该在任何地方运行,因为它是 Perl。欢迎您使用它。
样品运行
./pngchunks ball.png
13 IHDR
8 acTL <--- This one means it is animated
26 fcTL
4634 IDAT
26 fcTL
4344 fdAT
26 fcTL
4042 fdAT
26 fcTL
3828 fdAT
26 fcTL
3521 fdAT
26 fcTL
3168 fdAT
26 fcTL
2777 fdAT
26 fcTL
2588 fdAT
26 fcTL
2720 fdAT
26 fcTL
2792 fdAT
26 fcTL
2665 fdAT
26 fcTL
2581 fdAT
26 fcTL
2652 fdAT
26 fcTL
2774 fdAT
26 fcTL
2844 fdAT
26 fcTL
2886 fdAT
26 fcTL
2966 fdAT
26 fcTL
3197 fdAT
26 fcTL
3518 fdAT
26 fcTL
3995 fdAT
0 IEND
#!/usr/bin/perl -w
################################################################################
# pngchunks
# Mark Setchell
#
# Simple Perl tool to read the chunks in a PNG image file
# See https://en.wikipedia.org/wiki/Portable_Network_Graphics
#
# Usage: pngchunks image.png
################################################################################
use strict;
use Fcntl qw( SEEK_CUR );
my $f=shift or die "Usage: pngchunks image.png\n";
my ($handle,$offset,$buffer,$type,$length);
# Open file
open($handle,'<',$f) || die("Error opening file\n");
# Check 8 byte PNG signature
read($handle,$buffer,8);
if(substr($buffer,0,8) ne "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a"){
die("ERROR: Invalid PNG signature\n");
}
# Loop till IEND chunk
for(;;){
# Read 4 bytes of length, Network (big-endian)
read($handle,$buffer,4);
$length=unpack("N",$buffer);
# Read 4 bytes of chunk type
read($handle,$buffer,4);
$type=substr($buffer,0,4);
printf("%d %s\n",$length,$type);
# Break out of loop if IEND chunk
last if $type eq "IEND";
# Seek past this chunk and its 4 byte CRC
$offset=4+$length;
seek($handle,$offset,SEEK_CUR);
}