Reading GIF Dimensions in Perl

When you are building web pages for a newspaper, you have a lot of images. Every story might have a photo, every section has navigation graphics, every ad is a GIF. If you want pages to render properly, you need to include width and height attributes in your <img> tags. Without them, the browser has to download the image before it knows how to lay out the page, and everything jumps around as images load.

The problem is that we have hundreds of images, and nobody wants to open each one in a graphics program, write down the dimensions, and type them into the HTML by hand. I needed a way to do this automatically.

The GIF file format stores the image dimensions in a fixed location in the file header. The first three bytes are the signature (the letters G, I, F). The width is stored at byte offset 6 as a 16-bit little-endian integer, and the height follows immediately after at offset 8. So you can open the file, seek to the right position, read four bytes, and you have your dimensions.

Here is the complete script:

#!/usr/local/bin/perl
# Program name: gifsize
# Author: Rajiv Pant (Betul)
# Version: 1.0. October 1994.

foreach $gif (@ARGV)
  {
  ($width, $height, $type) = &gifsize ($gif) ;
  ($type =~ m/GIF/i)
  ? print "<img src=\"$gif\"    width=$width height=$height   border=0>\n"
  : print "$gif is not a GIF.\n" ;
  }


sub gifsize
{
local ($gif) = @_ ;
local ($w, $w2, $h, $h2, $gifwidth, $gifsize, $type) = () ;
open (GIF, $gif) ; read (GIF, $type, 3) ;
seek (GIF, 6, 0) ; read (GIF, $w,  1) ;
read (GIF, $w2, 1) ;
$width  = ord ($w) + ord ($w2) * 256 ;
read (GIF, $h,  1) ; read (GIF, $h2, 1) ;
$height = ord ($h) + ord ($h2) * 256 ;
close (GIF) ;
return ($width, $height, $type) ;
} # end of sub gifsize

You run it like perl gifsize.pl logo.gif masthead.gif photo1.gif and it outputs ready-to-paste HTML:

<img src="logo.gif"    width=200 height=50   border=0>
<img src="masthead.gif"    width=600 height=80   border=0>

It also checks the first three bytes to confirm the file is actually a GIF before trying to read dimensions. If someone passes in a JPEG or a text file, it tells you rather than printing garbage numbers.

The gifsize subroutine is separated out so you can require the file and call it from other scripts. I use it in our publishing system at Philadelphia Newspapers to generate img tags as part of the page-building process. The pages are assembled from templates, and the image tags get their dimensions filled in automatically.

This is not the first script I have shared here — I previously wrote about splitting files for floppy disks. Reading binary file headers directly is a useful technique. The GIF spec is public, the header layout is simple, and Perl’s read, seek, and ord functions make it straightforward. No external libraries needed.