ionel's codelog

Static photo gallery generator

Sun 08 December 2013

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

blog comments powered by Disqus