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.

1 Like