Work the Shell - Displaying Image Directories in Apache, Part II

May 1st, 2007 by Dave Taylor in

Get the Apache images in thumbnails by putting everything in a for loop.
Your rating: None

Last month, we started writing a shell script to turn the boring Apache directory display into a more useful and visually interesting page that helps you figure out what images you have and what they look like.

By utilizing the file command, I showed how you easily can differentiate between files that actually are images and those that aren't, so you don't get into an awkward situation where you're trying something like this:

<img src=mypage.html alt=mypage.html />

If you tell the Web browser to try to display an HTML source file as an image, well, the results aren't going to be what you desire!

Everything in a for Loop

The basic script iterates through every file in the current directory with a for loop, using the common shell construct:

for name in *
do
   commands
done

Let me point out that this won't display files that start with a ., which is good in that it doesn't display . and .., but which is potentially a problem if you were being tricky and had filenames like .secret-pict.png. But, then again, if you're trying to hide files by making them dot files, it's not unreasonable that this script glosses over them too.

As I've shown earlier, if you do have an image file, the best way to display it in HTML is to use something akin to:

<img src="filename" alt="filename" />

A better solution is maybe to label the image in the alt tag, but let's just jump into the loop and add this code. Recall that I'm using the file command to figure out what's an image and what isn't, so now our core loop looks like this:

for name in *
do
  if [ ! -z "$(file $name | grep 'image data')" ]
  then
    echo "<img src=$name><br />$name<br /><br />"
  else
    echo "<a href=$name>$name</a><br /><br />"
  fi
done

This works pretty well, displaying the images (and their names) for those files that are recognized as images, and just displaying a hypertext reference to the other files in the directory without erroneously indicating they're images.

Thumbnails Please

The problem with this approach is demonstrated quickly if, like me, you have lots of variable-size images; the resultant page is huge! What I really want displayed are small thumbnails or previews of my images, not the big images themselves.

Fortunately, Web browsers are pretty darn good at scaling images if you ask them to do the work. For example, if you have a 300x300 image but specify a height and width of 50, the image is scaled and displayed as 50x50 in the browser automagically. What you might not realize is that browsers also can scale an image if you simply specify either a different height or width value. In other words, this works fine:

<img src=100x100.png height=50 />

That's good news, because although you can figure out the size of an image on the fly in your shell script, it's fairly complicated. So, if we simply can specify that one parameter always should be a given height, you quickly can get quasi-thumbnails, albeit sometimes oddly sized ones.

The problem, by the way, is if we say that we always want images to be 50-pixels high and scale appropriately, an image that's 480 wide by 50 wide becomes, well, a 480-pixel-wide thumbnail. Ideally, our thumbnails would fix into a 50x50 box instead, but let's start with a basic solution:

for name in *
do
  if [ ! -z "$(file $name | grep 'image data')" ]
  then
    echo "<img src=$name alt=$name height=50 />"
    echo "<br />$name<br /><br />"
  else
    echo "<a href=$name>$name</a><br /><br />"
  fi
done

I also added an alt attribute to the img, though it doesn't really make any difference in the display. As you can see in Figure 1, the display overall is pretty nice. But, I have one image, logo-small.png, that turns out to be 850x40, so forcing a height of 50 pixels actually increases its width, by scaling up, not down!

Figure 1. Example Thumbnail Display

Figuring Out Image Size

It would be quite useful to be able to ascertain the size of an image and scale it appropriately. In some versions of Linux, you can get the image size information from the file command itself:

$ file xml.gif walt-disney-world-logo.jpg zeralights-logo.png
xml.gif:  GIF image data, version 89a, 36 x 14,
walt-disney-world-logo.jpg: JPEG image data,
JFIF standard 1.01, resolution (DPI), "AppleMark", 72 x 72
zeralights-logo.png: PNG image data, 225 x 93,
8-bit/color RGB, non-interlaced

The problem here is that the file command doesn't know how to ascertain the size of JPEG files, so the 72x72 reported for the image walt-disney-world-logo.jpg is actually the resolution of the image, not its size—a terrible limitation, but one we can live with, albeit reluctantly. Anyway, you should be using PNG format, not JPEG, right?

Based on that output, here's a shell function that returns height and width for GIF and PNG images and a null value for JPEG and any non-image files:

figuresize()
{
   image=$1

   fileout="$(file -b "$1")"

   if [ ! -z "$(echo $fileout|grep "GIF image")" ]
   then
     # GIF image, width x height are params 6-8
     width=$(echo $fileout | cut -f6 -d\  )
     height=$(echo $fileout | cut -f8 -d\  )
   elif [ ! -z "$(echo $fileout|grep "PNG imag")" ]
   then
     # PNG image, width x height are params 4-6
     width=$(echo $fileout | cut -f4 -d\  )
     height=$(echo $fileout | cut -f6 -d\  )
   else
     height=""; width=""
   fi
}

This is now integrated easily into our original loop, so we also can display the size of the image in our output:

for name in *
do
  if [ ! -z "$(file -b $name|grep 'image data')" ]
  then
    figuresize $name
    if [ ! -z "$height" ] ; then
      echo "<img src=$name alt=$name height=50 />"
      echo "<br />$name ($height x $width)<br />"
    else
      echo "<img src=$name alt=$name height=50 />"
      echo "<br />$name<br />"
    fi
  else
    echo "<a href=$name>$name</a><br /><br />"
  fi
done

I've run out of space to show how you can use that information to change how you scale your thumbnails, so that'll have to cascade into next month, but I encourage you to experiment with this code a bit and see what kind of results you get. Also, as a tip, if you want to get the size of all image types reliably, there's no better toolkit to add to your Linux box than ImageMagick, which you can find at www.imagemagick.org.

Dave Taylor is a 26-year veteran of UNIX, creator of The Elm Mail System, and most recently author of both the best-selling Wicked Cool Shell Scripts and Teach Yourself Unix in 24 Hours, among his 16 technical books. His main Web site is at www.intuitive.com, and he also offers up tech support at AskDaveTaylor.com.

__________________________


Special Magazine Offer -- Free Gift with Subscription
Receive a free digital copy of Linux Journal's System Administration Special Edition as well as instant online access to current and past issues. CLICK HERE for offer

Linux Journal: delivering readers the advice and inspiration they need to get the most out of their Linux systems since 1994.

Post new comment

Please note that comments may not appear immediately, so there is no need to repost your comment.
The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <pre> <ul> <ol> <li> <dl> <dt> <dd> <i> <b>
  • Lines and paragraphs break automatically.

More information about formatting options

Newsletter

Each week Linux Journal editors will tell you what's hot in the world of Linux. You will receive late breaking news, technical tips and tricks, and links to in-depth stories featured on www.linuxjournal.com.
Sign up for our Email Newsletter

Tech Tip Videos

From the Magazine

December 2009, #188

If last month's Infrastrucuture issue was too "big" for you then try on this month's Embedded issue. Find out how to use Player for programming mobile robots, build a humidity controller for your root cellar, find out how to reduce the boot time of your embedded system, and if you're new to embedded systems find out the basics that go into one. You can also read about the Beagle Board, the Mesh Potato and a spate of other interestingly named items. And along with our regular columns don't miss our new monthly column: Economy Size Geek.


Read this issue