2009-09-11 22 views
11

Oto link do another question Zapytałem o ten sam projekt, nad którym pracuję. Myślę, że odrobina tła będzie pomocna.Jak programowo sprawdzić, czy obraz GIF jest animowany?

Dla tych, którzy są zbyt leniwi, aby otworzyć nową kartę tego pytania, podsumuję to, co próbuję tutaj zrobić: pobrałem około 250 000 obrazów z 4scrape i chcę przejrzeć GIF-y i dowiedzieć się, które z nich są animowane, czy nie. Muszę to zrobić programowo, ponieważ naprawdę nie czuję, że moja dusza (lub mój związek z moją dziewczyną) mogłaby skorzystać z oglądania kilku tysięcy GIF-ów z 4chan, aby sprawdzić, czy są animowane czy nie. Jeśli znasz naturę 4chan, to znasz naturę obrazów (tj. "Cycki lub GTFO").

Znam PHP i Python, ale byłbym skłonny zbadać inne rozwiązania. Pomocny będzie również samodzielny program działający pod Windows.

Wielkie dzięki!

+2

Zobacz http://stackoverflow.com/questions/280658/can-i-detect-animated-gifs-using-php-and-gd –

Odpowiedz

16

z Python i PIL:

from PIL import Image 
gif = Image.open('path.gif') 
try: 
    gif.seek(1) 
except EOFError: 
    isanimated = False 
else: 
    isanimated = True 
+0

To działało świetnie. Dzięki! –

+1

Dzięki za tę wskazówkę. Tiny nit: może być ważne, aby uzyskać obraz z powrotem do 0, ponieważ 'gif.tell()' zwróci 1 nawet w bloku 'except', jeśli się nie mylę. – Ben

+0

To naprawdę całkiem proste z funkcją 'getIteratorIndex' http://php.net/manual/en/imagick.getiteratorindex.php – arghav

3

Kilka rozwiązań podane są na stronie PHP docs dla funkcji imagecreatefromgif.

Z rozwiązań, które czytałem, ten wydaje się najlepszy ze względu na mniejsze wymagania dotyczące pamięci.

<?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; 
} 
?> 
+0

OSTRZEŻENIE! Ten fragment kodu zawiera poważny błąd. Instrukcja while powinna zawierać nawiasy klamrowe, w przeciwnym razie ta funkcja NIE będzie przechwytywała wszystkich animowanych gifów. Chociaż to złapie niektóre (które z nich są gorsze niż 100%). Zobacz pełny i poprawny kod na tym stackoverflow url http://stackoverflow.com/questions/280658/can-i-detect-animated-gifs-using-php-and-gd – billmalarky

+0

W rzeczywistości istnieje jeszcze nowsza wersja ten skrypt naprawia błąd potencjalnie stworzony przez animowane gify z programu photoshop cs5. Zobacz to [tutaj] (http://www.php.net/manual/en/function.imagecreatefromgif.php #104473) – billmalarky

+0

@billmalarky Edytowałem odpowiedź – Kornel

7

Nigdy nie widziałem programu, który ci to powie. Ale GIF jest formatem blokowym i możesz sprawdzić, czy blok wskazujący animowany GIF jest obecny w twoich plikach.

Z artykułu wikipedii wymienionego poniżej: przy przesunięciu 0x30D w pliku GIF blokuje się rozszerzenie aplikacji (np. 3 bajty magiczne 21 FF 0B), a następnie numer magiczny 4E 45 54 53 43 41 50 45 32 przesunięcie 9at 0x310 wskazuje że reszta pliku zawiera wiele obrazów i powinny one być animowane.

Naprawdę artykuł w Wikipedii wyjaśnia to lepiej, a dokumenty formatu opisane poniżej rozwijają artykuł na Wiki.

Można więc parsować GIF-y za pomocą programu napisanego w Pythonie (analizowałem GIF-y za pomocą C wiele lat temu, było to głównie ćwiczenie przesuwania wskaźnika pliku i czytania bajtów). Sprawdź, czy w AE występuje poprawny 3-bajtowy identyfikator, a następnie 9-bajtowy numer magiczny.

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

zobaczyć również http://www.martinreddy.net/gfx/2d/GIF87a.txt

zobaczyć również http://www.martinreddy.net/gfx/2d/GIF89a.txt

Niestety, najlepsze, co mogę dla ciebie zrobić.

1

Nie jestem ekspertem w zakresie formatu plików GIF, ale jest to dla mnie interesujący problem, więc przyjrzałem się temu nieco. To działałoby tylko wtedy, gdy zawsze jest prawdą, że animowane gify mają wartość NETSCAPE2.0 na pozycji 0x310 (edycja) ORAZ statyczne gify nie, (/ edycja), co miało miejsce w moich testowych plikach.To jest C#, jeśli chcesz, mogę skompilować go do aplikacji konsolowej, która pobiera katalog jako argument i możesz uruchomić test na swojej bardzo dużej kolekcji gif, aby sprawdzić, czy zapewnia ona wiarygodne wyniki.

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"; 
     } 
    } 
} 
13

Jeśli jesteś na Linuksie (lub dowolny system z ImageMagick) można użyć skryptu powłoki jedno-liner i identify program:

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

wiem mówiłeś, że wolą PHP i Python, ale powiedziałeś także, że chcesz eksplorować inne rozwiązania. :)

0

spróbować

import Image 

def checkAnimate(): 
    im = Image.open('image.gif') 
    if not im.info['version'].__contains__('GIF'): 
     print "It's not a GIF file" 
    else: 
     if im.info.has_key('duration'): 
      if im.info['duration'] > 0: 
       return True 
      else: 
       return False 
     else: 
      return False 
1

sprawdzić, czy istnieje więcej niż jeden LocalDescriptor są w pliku GIF.

+1

Proszę rozwinąć swoją odpowiedź. To jest bardziej jak komentarz. –

0
from PIL import Image 
fp = open('1.gif', 'rb') 
im = Image.open(fp) 
is_gif = bool(im.format and im.format.upper() == 'GIF') 
+0

Mimo że ten kod może odpowiedzieć na pytanie, podając dodatkowy kontekst dotyczący _why_ i/lub _how_ to odpowiada , pytanie znacznie poprawiłoby jego długoterminową wartość . Proszę [edytuj] swoją odpowiedź, aby dodać wyjaśnienie. –

Powiązane problemy