2009-09-11 11 views
11

Aquí hay un enlace a another question que pregunté sobre el mismo proyecto en el que estoy trabajando. Creo que ese poco de fondo será útil.¿Cómo compruebo programáticamente si una imagen GIF está animada?

Para aquellos que son demasiado perezosos para abrir una nueva pestaña a esa pregunta, resumiré lo que estoy tratando de hacer aquí: he descargado unas 250,000 imágenes de 4scrape y quiero pasar por los GIF y encuentre cuáles están animados o no. Necesito hacer esto programáticamente, porque realmente no siento que mi alma (o mi relación con mi novia) pueda usar mirando un par de miles de GIF de 4chan para ver si están animados o no. Si conoce la naturaleza de 4chan, entonces conoce la naturaleza de las imágenes (es decir, "tetas o GTFO").

Conozco PHP y Python, pero estaría dispuesto a explorar otras soluciones. También funcionaría una pieza de software independiente que funciona en Windows.

¡Muchas gracias!

+2

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

Respuesta

16

Con Python y PIL:

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

Esto funcionó muy bien. ¡Gracias! –

+1

Gracias por este consejo. Tiny nit: podría ser importante volver a buscar la imagen en 0, ya que 'gif.tell()' devolverá 1 incluso en el bloque 'except', si no me equivoco. – Ben

+0

En realidad es bastante fácil con la función 'getIteratorIndex' http://php.net/manual/en/imagick.getiteratorindex.php – arghav

3

Algunas soluciones se dan en la página PHP docs para la función imagecreatefromgif.

De las soluciones que he leído, este parece el mejor debido a sus requisitos de memoria más estrictos.

<?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

ADVERTENCIA! Este fragmento de código tiene un error importante en él. La instrucción while debe incluir corchetes, de lo contrario esta función NO capturará todos los gifs animados. Aunque atrapará a algunos (que de couse es peor que falla al 100%). Ver el código completo y fijo en este stackoverflow url http://stackoverflow.com/questions/280658/can-i-detect-animated-gifs-using-php-and-gd – billmalarky

+0

De hecho, hay una versión aún más nueva de este script que corrige un error creado potencialmente por los gifs animados de photoshop cs5. Véalo [aquí] (http://www.php.net/manual/en/function.imagecreatefromgif.php#104473) – billmalarky

+0

@billmalarky He editado la respuesta – Kornel

7

Nunca he visto un programa que te diga esto. Pero GIF es un formato estructurado de bloque y puede verificar si el bloque que indica el GIF animado está presente en sus archivos.

Del artículo de Wikipedia señalado a continuación: en offset 0x30D una extensión de aplicación (es decir: 3 bytes número mágico 21 FF 0B) bloquea en el archivo GIF, seguido por número mágico 4E 45 54 53 43 41 50 45 32 9at offset 0x310 indica que el resto del archivo contiene múltiples imágenes, y deben estar animadas.

Realmente el artículo de Wikipedia lo explica mejor y los documentos de formato detallados a continuación amplían el artículo de Wiki.

Para que pueda analizar los GIF usando un programa escrito en Python (analicé GIF usando C hace muchos años, era principalmente un ejercicio para mover el puntero del archivo y leer bytes). Determine si el AE está presente con la ID correcta de 3 bytes, y seguido por el número mágico de 9 bytes.

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

Véase también http://www.martinreddy.net/gfx/2d/GIF87a.txt

Véase también http://www.martinreddy.net/gfx/2d/GIF89a.txt

En este momento, lo mejor que puedo hacer por usted.

1

No soy un experto en formato de archivo GIF, pero este es un problema interesante para mí, así que lo analicé un poco. Esto funcionaría solo si siempre es cierto que los gifs animados tienen el valor NETSCAPE2.0 en la posición 0x310 (editar) Y los gifs estáticos no, (/ edit) cual fue el caso en mis archivos de prueba.Esto es C#, si lo deseas, podría compilarlo en una aplicación de consola que tome un directorio como argumento y podrías ejecutar algunas pruebas en tu gran colección gif para ver si produce resultados confiables.

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

Si estás en Linux (o cualquier sistema con ImageMagick) se puede utilizar una secuencia de comandos de una sola línea de shell y el programa identify:

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

Sé que usted ha dicho que prefiere PHP y Python, pero también dijiste que estás dispuesto a explorar otras soluciones. :)

0

probar esto

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

ver si hay hay más de un LocalDescriptor están en el archivo GIF.

+1

Por favor, expande tu respuesta. Esto es más como un comentario. –

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

Aunque este código puede responder a la pregunta, proporcionando contexto adicional con respecto a _por qué_ y/o _how_ responde la pregunta mejoraría significativamente su valor a largo plazo . Por favor [edite] su respuesta para agregar alguna explicación. –

Cuestiones relacionadas