# ThumbnailGenerator Demo

## What Is It

The `ThumbnailGenerator` is a functional interface that creates an image thumbnail for a `File`:

    BufferedImage createThumbnail(File file,
                                  int requestedMaxSize) throws Exception;

## How To Use It

A simple invocation may resemble:

    try {
      File myFile = getFile();
      BasicThumbnailGenerator g = new BasicThumbnailGenerator();
      BufferedImage thumbnail = g.createThumbnail(myFile,
                                                  ThumbnailGenerator.UNDEFINED);
    } catch(Exception e) {
      // the file may not be supported, or an IO error occurred
    }

## How It Works

### The BasicThumbnailGenerator

There are a few `ThumbnailGenerators` to choose from (see below), but the `BasicThumbnailGenerator` is the most thorough. It multiplexes which other `ThumbnailGenerator` to use, and it may also try multiple generators to find one that is successful.

### Thumbnail Size

The second argument is the maximum thumbnail width/height. The code snippet above uses an UNDEFINED value, which means the generator should take whatever is faster/easier to generate. For example: if a high-resolution JPEG includes an embedded thumbnail, then that is probably the easiest thing to return.

However in some cases you may need a specific size. If you pass in a fixed value (like "100" or "256") then the generator will try to return a thumbnail that respects that maximum value‐even if that means ignoring a file's embedded thumbnail.

## Discussion

There are currently four `ThumbnailGenerators`:

### ScalingThumbnailGenerator

This uses the `Scaling` class to read the entire (unscaled) image and produce a thumbnail. The scaling class is designed to keep as little in memory as possible, but even so: churning through a high-resolution image is going to be expensive. This generator works with JPGs, BMPs, PNGs, and GIFs.

Note this can also parse and scale down embedded JPEG thumbnails. The performance comparison below deactivates this feature, though, for the sake of comparison.

### JPEGMetaDataThumbnailGenerator

This uses the `JPEGMetaData` class to fetch a thumbnail from a JPEG's metadata. This exclusively looks at the metadata; this may return null if the image doesn't have an embedded thumbnail.

### MacQuickLookThumbnailGenerator

This uses the "qlmanage" command-line tool on Macs to retrieve an image using Quick Look. This supports the widest variety of file formats, but it's also the slowest generator. And in some cases (like PDFs) every invocation can cause a new image to temporarily appear in your dock. The exact file formats this supports will vary from one machine to another, because every application you install can supply its own Quick Look plugin.

### BasicThumbnailGenerator

This consults the other available generators. This is the "one size fits all" option that you should use 90% of the time.

## Performance

Here is a chart showing how long each generator took to create 10 thumbnails from a 2750x1063 JPG:

It's no surprise the `JPEGMetaData` beat the `ScalingThumbnailGenerator`.

The Quick Look generator was pretty disappointing performance-wise, but the range of file formats it supports suggests you should always keep it in your back pocket.

I used to include a different generator: the `MacCImageThumbnailGenerator`. This took about 1/3 the time of the `ScalingThumbnailGenerator`. I removed it because it relied on reflection to access the `sun.lwawt.macosx.CImage` class on Mac.

These results were observed for a JPG on a Mac, so all the current generators could be consulted. If you're reading a PNG on Windows: there's only one generator (the `ScalingThumbnailGenerator`) that can get the job done in that context.