首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >我能否以编程方式确定PNG是否是动画的?

我能否以编程方式确定PNG是否是动画的?
EN

Stack Overflow用户
提问于 2010-12-24 08:37:16
回答 5查看 4.4K关注 0票数 19

我有PNG (以及JPEG)图片上传到我的网站。

它们应该是静态的(即一个框架)。

有像APNG这样的东西。

(它将在Firefox中动画化)。

根据维基百科文章..。

APNG将后续帧隐藏在PNG辅助块中,这样APNG不知情的应用程序就会忽略它们,但在其他情况下,不需要对格式进行任何更改以允许软件区分动画图像和非动画图像。

这是否意味着无法确定PNG是否带有代码?

如果可能的话,你能给我指出正确的方向吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-12-24 08:46:28

APNG图像被设计成“伪装”为PNG,供那些不支持它们的读者使用。也就是说,如果读取器不支持它们,它只会假设它是一个普通的PNG文件,并且只显示第一个帧。这意味着它们与PNG (image/png)具有相同的MIME类型,它们具有相同的魔术号(89 50 4e 47 0d 0a 1a 0a),并且通常保存时具有相同的扩展名(尽管这并不是检查文件类型的好方法)。

那么,你如何区分它们呢?APNG中有一个"acTL“块。因此,如果您搜索字符串acTL (或者,以十六进制表示,61 63 54 4C (块标记之前的4个字节(即00 00 00 08)是大端格式的块的大小,而不包括字段末尾的大小、标记或CRC32 ),那么您应该是很好的。为了得到更好的结果,请检查这个块是否出现在第一次出现"IDAT“块之前(只需查找IDAT)。

这段代码(取自apng.php )将完成以下任务:

代码语言:javascript
代码运行次数:0
运行
复制
<?php
# Identifies APNGs
# Written by Coda, functionified by Foone/Popcorn Mariachi#!9i78bPeIxI
# This code is in the public domain
# identify_apng returns:
# true if the file is an APNG
# false if it is any other sort of file (it is not checked for PNG validity)
# takes on argument, a filename.
function identify_apng($filename)
    {
    $img_bytes = file_get_contents($filename);
    if ($img_bytes)
        {
        if(strpos(substr($img_bytes, 0, strpos($img_bytes, 'IDAT')), 
                 'acTL')!==false)
            {
        return true;
        }
        }
    return false;
    }
?>
票数 19
EN

Stack Overflow用户

发布于 2010-12-24 08:41:24

AFAIK,不支持APNG的库将只使用PNG的第一个框架。在您的示例中,您只需从APNG (或PNG、JPEG等)创建一个新的图像。把它重新保存为PNG。如果使用GD,它应该删除动画数据,除非库已经更新以支持APNG。

票数 6
EN

Stack Overflow用户

发布于 2018-10-07 11:17:20

我想建议一个更优化的版本,它不会读取整个文件,因为这些文件可能相当大,并且仍然依赖于IDAT规则之前的acTL:

代码语言:javascript
代码运行次数:0
运行
复制
function identify_apng($filepath) {
    $apng = false;

    $fh = fopen($filepath, 'r');
    $previousdata = '';
    while (!feof($fh)) {
        $data = fread($fh, 1024);
        if (strpos($data, 'acTL') !== false) {
            $apng = true;
            break;
        } elseif (strpos($previousdata.$data, 'acTL') !== false) {
            $apng = true;
            break;
        } elseif (strpos($data, 'IDAT') !== false) {
            break;
        } elseif (strpos($previousdata.$data, 'IDAT') !== false) {
            break;
        }

        $previousdata = $data;
    }

    fclose($fh);

    return $apng;
}

速度从5倍提高到10倍或更高,这取决于文件的大小,而且它使用的内存也要少得多。

注意:这可能会随着fread的大小或者与当前块的连接而被更多的调整。顺便说一句,我们需要这种连接,因为acTL/IDAT字可能被分成两个读块。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4525152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档