Как программно проверить, анимировано ли изображение GIF? - PullRequest
13 голосов
/ 11 сентября 2009

Вот ссылка на другой вопрос Я задал вопрос о том же проекте, над которым я работаю. Я думаю, что немного фона будет полезно.

Для тех, кому лень открывать новую вкладку для этого вопроса, я подведу итог, что я пытаюсь сделать здесь: я скачал около 4 000 000 изображений с 4scrape и хочу просмотреть GIF-файлы и найти какие из них анимированные или нет. Мне нужно сделать это программно, потому что я действительно не чувствую, что моя душа (или мои отношения с моей девушкой) могут использовать просмотр пары тысяч GIF-файлов из 4chan, чтобы увидеть, анимированы они или нет. Если вы знаете природу 4chan, то вы знаете природу изображений (то есть "сиськи или GTFO").

Я знаю PHP и Python, но хотел бы изучить другие решения. Отдельная часть программного обеспечения, которая работает в Windows, также будет работать.

Большое спасибо!

Ответы [ 11 ]

17 голосов
/ 12 сентября 2009

с Python и PIL :

from PIL import Image
gif = Image.open('path.gif')
try:
    gif.seek(1)
except EOFError:
    isanimated = False
else:
    isanimated = True
13 голосов
/ 12 сентября 2009

Если вы работаете в Linux (или в любой системе с ImageMagick ), вы можете использовать однострочный сценарий оболочки и identify программу:

identify *.gif | fgrep '.gif[1] '

Я знаю, что вы сказали, что предпочитаете PHP и Python, но вы также сказали, что готовы исследовать другие решения. :)

7 голосов
/ 11 сентября 2009

Я никогда не видел программу, которая скажет вам это. Но GIF - это блочно-структурированный формат, и вы можете проверить, присутствует ли в ваших файлах блок, указывающий анимированный GIF.

Из статьи в википедии, отмеченной ниже: по смещению 0x30D блок расширения приложения (т. Е. Магическое число 3 байта 21 FF 0B) в файле GIF, за которым следует магическое число 4E 45 54 53 43 41 50 45 32 9 смещение 0x310 указывает, что Остальная часть файла содержит несколько изображений, и они должны быть анимированными.

Действительно, статья в Википедии объясняет это лучше, а документы о формате, указанные ниже, расширяют статью Вики.

Таким образом, вы можете анализировать GIF-файлы с помощью программы, написанной на Python (я анализировал GIF-файлы, используя C много лет назад, в основном это было упражнение в перемещении указателя файла и чтении байтов). Определите, присутствует ли AE с правильным 3-байтовым идентификатором, и за которым следует 9-байтовое магическое число.

См. http://en.wikipedia.org/wiki/Graphics_Interchange_Format#Animated_.gif

Также см. http://www.martinreddy.net/gfx/2d/GIF87a.txt

Также см. http://www.martinreddy.net/gfx/2d/GIF89a.txt

Извините, лучшее, что я могу для вас сделать.

3 голосов
/ 12 июня 2018

30 июня 2015 г. добавлена ​​подушка is_animated.

Это добавляет свойство is_animated, чтобы проверить, имеет ли изображение несколько слоев или кадров.

Пример использования:

from PIL import Image
print(Image.open("test.gif").is_animated)
3 голосов
/ 11 сентября 2009

На странице PHP docs приведено несколько решений для функции imagecreatefromgif.

Из решений, которые я прочитал, это кажется лучшим из-за более жестких требований к памяти.

<?php
function is_ani($filename) {
    if(!($fh = @fopen($filename, 'rb')))
        return false;
    $count = 0;
    //an animated gif contains multiple "frames", with each frame having a
    //header made up of:
    // * a static 4-byte sequence (\x00\x21\xF9\x04)
    // * 4 variable bytes
    // * a static 2-byte sequence (\x00\x2C)

    // We read through the file til we reach the end of the file, or we've found
    // at least 2 frame headers
    while(!feof($fh) && $count < 2) {
        $chunk = fread($fh, 1024 * 100); //read 100kb at a time
        $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00\x2C#s', $chunk, $matches);
    }
    fclose($fh);
    return $count > 1;
}
?>
2 голосов
/ 11 сентября 2009

Я не эксперт по формату файлов GIF, но это интересная проблема для меня, поэтому я немного разбирался в этом. Это будет работать, только если всегда верно, что анимированные GIF-файлы имеют значение NETSCAPE2.0 в позиции 0x310 (правка), а статические GIF-изображения - нет (/ / правка), как было в моих тестовых файлах. Это C #, если вы хотите, я мог бы скомпилировать его в консольное приложение, которое принимает каталог в качестве аргумента, и вы могли бы запустить некоторый тест для вашей очень большой коллекции gif, чтобы проверить, дает ли она надежные результаты.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            string ani = @"C:\path\to\ani.gif";
            string sta = @"C:\path\to\static.gif";

            Console.WriteLine(isAnimated(ani));
            Console.WriteLine(isAnimated(sta));
        }

        static bool isAnimated(string path)
        {
            byte[] bytes = File.ReadAllBytes(path);
            byte[] netscape = bytes.Skip(0x310).Take(11).ToArray();

            StringBuilder sb = new StringBuilder();

            foreach (var item in netscape)
            {
                sb.Append((char)item);
            }

            return sb.ToString() == "NETSCAPE2.0";
        }
    }
}
2 голосов
/ 11 сентября 2009

Прочитайте спецификацию GIF89A и извлеките информацию. http://www.w3.org/Graphics/GIF/spec-gif89a.txt

Или просто, лениво и готово к взлому, используйте программу intergif, которая может извлечь отдельные изображения из анимированного GIF. Извлеките во временный каталог и посмотрите, сколько файлов вы получите. http://utter.chaos.org.uk/~pdh/software/intergif/download.htm

1 голос
/ 24 апреля 2019

Функция ImageMagick getNumberImages сделает это за вас. Так как возвращает количество изображений в объекте. Imagick :: getNumberImages

<?php

$image = new Imagick( YOUR_FILE );

if ( $image->getNumberImages() ) {
    echo "It's animated";
}
1 голос
/ 03 июня 2010

посмотреть, есть ли в GIF-файле более одного LocalDescriptor.

0 голосов
/ 27 апреля 2016
from PIL import Image
fp = open('1.gif', 'rb')
im = Image.open(fp)
is_gif = bool(im.format and im.format.upper() == 'GIF')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...