Static photo gallery generator

08 December 2013 (updated 04 March 2015)

I always had this burning need to have something slightly different when publishing photos online, didn't you? Maybe you wanted to show the EXIF and the hosting service did not support that, or maybe you just hate the look of the pages - that wasted space filled with useless buttons and forms - grandma will never use that, she just want to see your trip photos.

Sometimes the UI is nice, but the photos have ugly thumbnails with bad aliasing or maybe just a bad combination of resampling and compression algorithms make the fullsize pictures a pain to look at.

But overall, it's all about control, programmers want to have control over the result ...

So what about programmers?

Programmers make photos too right? They can work with markup, right? And they need no stinky UI to upload photos, right?

That's right, there should be a good tool, for programmers, which they can use to generate a nice, easy to customize photo gallery!

So I've been looking at this a bit, and turns out, there no good tool that lets you generate a gallery that you can just upload to S3 or Github Pages.

This is how I think it should work:

Flow diagram for static photo gallery generator

Now, about that UI *

There should be a good, extensible theme and it should have some sensible defaults:

  • A good choice for thumbnail sizes.

  • A good choice for thumbnail layout. It appears that now everyone it doing packing layouts - don't crop, and don't waste any space. It looks good. There are two ways to do it:

    • Row packing: photos are packed in rows. Every photo has the same height. You can see this in Google+ and Flickr. Flickr implemented it recently, maybe it is real good?
    • Column packing: photos are packed in columns. Every photo has the same width.

    Now you can imagine that column packing will make the portraits look bigger so it is a good layout if you do lots of portrait oriented photography.

  • Good balance of compression and resampling algorithm choices.

  • A usable UI on handheld devices. Something that:

    • Knows touch events.
    • Is not a ugly afterthought.
    • Has good navigation and doesn't make you reload the page over that slow internet connection every damn time.
    • Doesn't make your phone or tablet freeze because it just tried to load 20 MBytes worth of data in one page load.

File layout *

And because programmers are lazy, there should be a minimal amount of fuss required to generate that initial setup and generate galleries.

The tool, the generator, should require as little information as possible, preferably needing only a directory that has some photos in it. But it should be easy to tune and customize.

So I'm thinking about a file layout like this:

.
β”œβ”€β”€ defaults.yaml (optional)
β”œβ”€β”€ gallery1
β”‚   β”œβ”€β”€ config.yaml (optional)
β”‚   β”œβ”€β”€ IMG_0001.jpg
β”‚   β”œβ”€β”€ IMG_0002.jpg
β”‚   β”œβ”€β”€ IMG_0003.jpg
β”‚   β”œβ”€β”€ IMG_0004.jpg
β”‚   β”œβ”€β”€ IMG_0005.jpg
β”‚   β”œβ”€β”€ IMG_0006.jpg
β”‚   β”œβ”€β”€ IMG_0007.jpg
β”‚   β”œβ”€β”€ IMG_0008.jpg
β”‚   β”œβ”€β”€ IMG_0009.jpg
β”‚   └── IMG_0010.jpg
└── gallery2
    β”œβ”€β”€ config.yaml (optional)
    β”œβ”€β”€ IMG_0001.jpg
    β”œβ”€β”€ IMG_0002.jpg
    β”œβ”€β”€ IMG_0003.jpg
    β”œβ”€β”€ IMG_0004.jpg
    β”œβ”€β”€ IMG_0005.jpg
    β”œβ”€β”€ IMG_0006.jpg
    β”œβ”€β”€ IMG_0007.jpg
    β”œβ”€β”€ IMG_0008.jpg
    β”œβ”€β”€ IMG_0009.jpg
    └── IMG_0010.jpg

This will render to:

  • index.html - contains a list of galeries (with some preview picture)
  • gallery1/index.html - contains the photos from gallery1
  • gallery2/index.html - contains the photos from gallery2
  • resized images
  • theme assets (css, js etc)

Configuration *

Goals of the configuration: be as little as possible *

What to we want to configure?

  • Any number of display modes - allow configuring unlimited number of display modes - to allow easy configuration of themes that don't subscribe to the traditional thumbnal/fullsize convention. Each display mode should:
    • Allow configuring any processing filters.
    • Allow configuring resampling mode.
  • Photo discovery - be able to select what photos are displayed.
  • Photo ordering - be able override the default ordering. This should be painless if you only want to have few specific photos in front and for the rest the default ordering.

Titles and/or photo order should come from the filenames. Most people don't need titles so it would be natural to just name the file name to get the display order.

YAML? *

What about JSON, or XML? They are too verbose. JSON is nice but it's a bit too verbose in my opinion. Quote everything? Brackets everywhere? Hell no.

YAML has one disadvantage: easy to make mistakes. Just one different character and you have totally different data type!

But I think that with a good validator (I'm looking at schema) that gives good validation error messages this can be acceptable.

Discovery & ordering *

Very importantly, what's the best way to do discovery of photos? What programmers use all day long [1]? globs! The are also knows as wildcard expressions - they should be fairly common knowledge. So the idea is to have some sort of list that holds the globs that will match photos.

Now that we got a list with the globs, so why don't we use that to decide the order of the photo? We can show photos in the order of the globs that matched the files.

[1]Unless they program without a filesystem ...

config.yaml *

This holds configuration for galleries: resizing configuration, thumbnail sizes, layout configuration, titles and slug overrides. The galleries inherit configuration from the index. All configuration is optional.

Sample configuration:

title: My trip to England
slug: my-trip-to-england
layout: row
photos:
    - IMG_0002.jpg: Abstract 01
    - IMG_0003.jpg: Abstract 02
    - IMG_0004.jpg: Some bridge
    - IMG_0001.jpg:
        title: Some street
        thumbnail:
            resampling: antialias
        display:
            resampling: antialias
            width: 3000
            height: 2000
            filters:
                pre:
                - edge_enhance
                post:
                - contrast: 0.5
    - "*":
        title: Untitled
        thumbnail:
            width: 300
            height: 200
            resampling: bicubic
            titles: on-hover
        display:
            width: 1920
            height: 1080
            resampling: bicubic

Reference *

title:

A string - title for the gallery or galleries index

slug:

Will be the url for the gallery

layout:

Type of layout. One of row (default, will look like Flickr and Google+) or column (will look like pass.us).

photos:

List of overrides for individual photos. Filenames are matched using glob expressions (you can use * and ?)

The photos are sorted by these criterias:

  • order of the matching entries in photos section
  • file name

If value is a string then it's used as the title, otherwise these keys are accepted:

title:

Title to use for this photo. The default titles for photos are the filenames (without the extension).

mode:

Mode could be thumbnail, display or anything the theme can understand.

with:

Maximum width in pixels. (default: 580)

height:

Maximum height in pixels. (default: 580)

titles:

How to show photo titles on thumbnails. One of hide, on-hover (default) or always.

resampling:

Resampling algorithm to use when resizing.

filters:

Any filters to apply.

pre:List of pre-resize filters to apply.
post:List of post-resize filters to apply.

defaults.yaml *

You can specify defaults here for some of the configuration that you put in config.yaml.

Sample configuration:

layout: row
thumbnail:
    width: 300
    height: 200
    resampling: bicubic
    titles: on-hover
display:
    width: 1920
    height: 1080
    resampling: bicubic

Reference *

layout:

Type of layout. One of row (default, will look like Flickr and Google+) or column (will look like pass.us).

mode:

Mode could be thumbnail, display or anything the theme can understand.

with:

Maximum width in pixels. (default: 580)

height:

Maximum height in pixels. (default: 580)

titles:

How to show photo titles on mode. One of hide, on-hover (default) or always.

resampling:

Resampling algorithm to use when resizing.

filters:

Any filters to apply.

pre:List of pre-resize filters to apply.
post:List of post-resize filters to apply.

Still not sure that default.yaml is actually needed ...

What's next? *

Now I haven't got around in implementing what's described above yet ...

I sure could use some feedback. Maybe I'm missing something important or there's already a solution like that.

This entry was tagged as python