Determine Photo Sizes

The purpose of this section is to figure out how, exactly, the algorithm to determine the sizes of the photos is going to work. This is part of the mechanism to display a stream of photos.

Goal: display a series of photos in a way that looks pleasing, regardless of the sizes and width to height ratios of the individual photos. The width to height ratios (or the exact width and height of the photo) are known.

Looking at the example of the Google Photo app, it looks like the “pleasing” display is going to be achieved by displaying rows of one or more photos, where the photos in a particular row are all the exact same height.

  1. Input: a series of images with their aspect ratios, and the row width in pixels.
  2. Split the series of images (potentially infinite scroll) into sub-series that form the respective rows.
  3. For each row, determine the exact width and height of the image to use for rendering.

How about a very basic approach, which assumes that every photo is going to be rendered in at least 150 pixels high? The exact value of the minimum height may be influenced by pixel density, but let’s start with 150.

  1. Iterate through the series of photos.
  2. Based on 150 pixels height, calculate the width. This gives the preliminary calculated width and height.
  3. If the photo still fits on the row based on the remaining width (taking into account the space between photos), include the photo in the row and go back to step 2 with the next photo.
  4. Once the row is determined, use multiply the calculated sizes (width and height) by available screen width minus total space between photos / total calculated width of images in the row. This gives the actual sizes of the photos to use, and it gives the row height.

This algorithm seems relatively straight-forward and performant to implement. Need to look at rounding and compensate when the total number of pixels don't exactly add up.

What to do about very wide and very tall photos?

Extremely wide photos end up in the row by themselves with a height less than the minimum height. Maybe if the height is less than ⅓ of the minimum height, add fillers at the top and bottom to make sure the photo still provides a reasonable click area?

Extremely tall and skinny photos will be problematic because they end up taking up taking almost no space. So maybe if the width ends up as less than ⅓ of the minimum height, add spacing to the left and right of the photo to still provide a reasonable click area?

The exact numbers used above (150 pixels, ⅓, which translates to 50 pixels) must be constants that can be tweaked, as should the spacing between photos be.

The above algorithm is put in place through the Stream Test page, which displays a hard-coded list of all the non-standard-size photos from the archive. It seems to work well in practice.

Implementation Details

After some trial-and-error, I ended up with 5 thumbnail sizes:

  • Tiny (50px)
  • Small (100px)
  • Medium (150px), the default
  • Large (250px)
  • Extra Large (400px)

I ended up not using the “pixel ratio” which gives an indication of the pixel density, but just relying on the CSS interpretation of pixels on the particular device. That seems to be closer to what it should be than trying to use the pixel ratio.

In the first experiment, I’m downloading photos in full size to display in the stream. That’s much too big, though. So I need to pre-size the photos. I’m thinking the pre-sizing would be to a hight of double the selected thumbnail size.

I will call the new sizes “s” followed by the thumbnail size, so s150 for medium, s50 for tiny, and so on. Note that the size is reflecting the desired height, so s150 would size the image to a height of 300 pixels. The width is proportional based on the actual image size.