Automosaic: Automatic aspect-preserving layouting (for photos)

Hi there!

I recently created a travel photo book using typst, and a major annoyance was laying out the images such that

  • their aspect-ratio is preserved,
  • orderly alignment at edges,
  • constant gap between images,
  • varying layouts between pages.

So I created automosaic. You can either manually specify a course arrangement and let the cell sizes be computed internally, like so:

#import "@preview/automosaic:0.1.0": *

#context display-content-tree(
  (
    image("a.jpg"), // root level
    (
      image("b.jpg"), // sub-group
      (
        image("c.jpg"), // subsub-group
        image("d.jpg"),
        // (...)        // can be nested infinitely
      ),
    ),
  ),
  axis: "horizontal", // root-level direction, horizontal or vertical
)

, or pass a flat list of images (or other content) to compute the optimal layout like so:

#import "@preview/automosaic:0.1.0": *

#context display-auto-layout(
  (
    image("a.jpg"),
    image("b.jpg"),
    image("c.jpg"),
    (body: image("d.jpg"), weight: 2), // specify a weight (default: 1) to give this element more space in the auto-layout
    // (body: [Some Text], aspect: 0, constant-size: 3cm) // work-around for text or other content which can't be scaled the same way as images
  ),
  selector: "1",                // select the "best" layout
  // selector: "1.", "1..", ... // equally well-scored reorderings of the same layout
  // selector: "2", "3", ...    // next-best layouts, in descending order of score
)

To determine the optimal layout, a cost function weights:

  • the amount of used-up space by the entire layout (compared to the available space),
  • and the relative area of each image (i.e., ‘weight: 2’ means that image ideally gets double the space as other ‘weight: 1’ images).

Examples

Example of the same auto-layout in varying parent containers:

An auto-layout with a few more elements:

Let me know what you think! I hope it is useful to some.

Thoughts

I do not think there is a way to force typst to preserve aspect ratios in, for example, grids (without manually computing cell sizes). If you have an idea, please share it.
Also, text content requires a constant area constraint, as opposed to the constant aspect-ratio constraint implemented here. This would be a great addition in the future! Right now (unscaled) text needs some workarounds, and the auto-layout can need some tuning if text is involved.

2 Likes

It looks very nice! I’m trying to solve similar problem with a package called Erna, as discussed here: Erna - a Typst library to scale and align rows of images (currently proposed for inclusion in Universe).

At first glance it seems that Automosaic is more versatile, but perhaps at the expense of more complex API. I like that you can embed other types of content than just images. Nice work!