tags:

views:

770

answers:

9

Here is a link to another question I asked concerning the same project I am working on. I think that bit of background will be helpful.

For those that are too lazy to open a new tab to that question, I'll summarize what I'm trying to do here: I've downloaded about 250,000 images from 4scrape and I want to go through the GIFs and find which ones are animated or not. I need to do this programmatically, because I really don't feel my soul (or my relationship with my girlfriend) could use looking at a couple thousand GIFs from 4chan to see if they are animated or not. If you know the nature of 4chan, then you know the nature of the images (i.e. "tits or GTFO").

I know PHP and Python, but would be willing to explore other solutions. A stand-alone piece of software that works on Windows would also work.

Thanks a lot!

+1  A: 

Read the GIF89A specification and extract the information. http://www.w3.org/Graphics/GIF/spec-gif89a.txt

Or easy and lazy and ready for a hack use the intergif program which can extract the single images out of an animated gif. Extract into a temp directory and look how many files you get. http://utter.chaos.org.uk/~pdh/software/intergif/download.htm

Lothar
+4  A: 

A few solutions are given on the PHP docs page for the imagecreatefromgif function.

From the solutions I've read, this one seems the best due to its tighter memory requirements.

<?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;
}
?>
Ben S
+3  A: 

I've never seen a program that will tell you this. But GIF is a block structured format and you can check if the block indicating animated GIF is present in your files.

From wikipedia article noted below: at offset 0x30D an Application Extension (ie: 3 byte magic number 21 FF 0B) block in the GIF file, followed by magic number 4E 45 54 53 43 41 50 45 32 9at offset 0x310 indicates that the rest of the file contains multiple images, and they should be animated.

Really the Wikipedia article explains it better and the format docs noted below expand on the Wiki article.

So you can parse the GIFs using a program written in Python (I parsed GIFs using C many years ago, it was mainly an exercise in moving the file pointer around and reading bytes). Determine if the AE is present with the correct 3 byte ID, and followed by the 9 byte magic number.

See http://en.wikipedia.org/wiki/Graphics%5FInterchange%5FFormat#Animated%5F.gif

Also see http://www.martinreddy.net/gfx/2d/GIF87a.txt

Also see http://www.martinreddy.net/gfx/2d/GIF89a.txt

Sorry, best I can do for you.

Eric M
+1  A: 

I'm no GIF file format expert, but this is an interesting problem to me so I looked into it a bit. This would work only if it's always true that animated gifs have the value NETSCAPE2.0 at position 0x310 (edit)AND static gifs do not,(/edit) which was the case in my test files. This is C#, if you want I could compile it to a console app that takes a directory as an argument and you could run some test on your very large gif collection to see if it produces reliable results.

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";
     }
    }
}
Jason Kostempski
+1  A: 

If you're on Linux (or any system with ImageMagick) you can use a one-liner shell script and identify program:

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

I know you said you prefer PHP and Python, but you also said you are willing to explore other solutions. :)

Denilson Sá
+8  A: 

With Python and PIL:

import Image
gif= Image.open('path.gif')
try:
    gif.seek(1)
except EOFError:
    isanimated= False
else:
    isanimated= True
bobince
This worked great. Thanks!
Joel Verhagen
A: 

try this

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
A: 

see if there is more than one LocalDescriptor are there in the GIF file.

Jake