Могу ли я программно определить, является ли PNG анимированным? - PullRequest
13 голосов
/ 24 декабря 2010

У меня есть PNG (а также JPEG) изображения, загруженные на мой сайт.

Они должны быть статическими (то есть один кадр).

Существует такая вещь, как APNG .

Bouncy ball

(он будет анимирован в Firefox).

Согласно статье Википедии ...

APNG скрывает последующие кадры во вспомогательных фрагментах PNG таким образом, что приложения, не поддерживающие APNG, будут их игнорировать, но в противном случае нет никаких изменений в формате, позволяющих программам различать анимированные и неанимированные изображения.

Означает ли это, что невозможно определить, анимируется ли PNG с кодом?

Если это возможно, не могли бы вы указать мне правильное направление в отношении PHP (GD, ImageMagick)?

Ответы [ 3 ]

15 голосов
/ 24 декабря 2010

APNG-изображения предназначены для «маскировки» PNG для читателей, которые их не поддерживают.То есть, если читатель не поддерживает их, он просто предположит, что это обычный файл PNG и отобразит только первый кадр.Это означает, что у них тот же тип MIME, что и у PNG (image / png), у них одинаковое магическое число (89 50 4e 47 0d 0a 1a 0a), и, как правило, они сохраняются с тем же расширением (хотя это не совсем хороший способ проверитьтип файла).

Итак, как вы их различаете?У APNG есть кусок "acTL".Таким образом, если вы ищете строку acTL (или, в шестнадцатеричном виде, 61 63 54 4C (4 байта перед маркером фрагмента (т.е. 00 00 00 08) - это размер фрагмента в формате с прямым порядком байтов, без учета размера,маркером или CRC32 в конце поля)) у вас должно получиться довольно хорошо.Чтобы сделать его еще лучше, убедитесь, что этот чанк появляется перед первым появлением чанка "IDAT" (просто ищите IDAT).

Этот код (взятый из http://foone.org/apng/identify_apng.php) будет делатьхитрость:

<?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;
    }
?>
5 голосов
/ 24 декабря 2010

AFAIK, библиотеки, которые не поддерживают APNG, просто возьмут первый кадр PNG. В вашем случае вы можете просто создать новое изображение из APNG (или PNG, JPEG и т. Д.) И повторно сохранить его как PNG. При использовании GD следует удалить данные анимации, если библиотека не была обновлена ​​для поддержки APNG.

0 голосов
/ 07 октября 2018

Я хотел бы предложить более оптимизированную версию, которая не читает весь файл, поскольку они могут быть довольно большими, и при этом все еще полагаться на acTL перед правилом IDAT:увеличивается с 5x до 10x и более в зависимости от размера файла, а также использует намного меньше памяти.

Примечание: возможно, это может быть изменено больше с размером, заданным для fread или с конкатенациейпредыдущий кусок с текущим.Кстати, нам нужна эта конкатенация, поскольку слово acTL / IDAT может быть разделено на два блока чтения.

...