Scale bar and captions
For microscopy, a stacked image is usually a figure, and a figure needs a scale bar. This section makes one, and a caption to go with it, and burns both into the saved files.
They are drawn into the fused image, the weighted average and every stereo and rocking view (after the shear — a bar sheared by the depth map would bend). They are not drawn into the depth maps, the slabs or the 3D model's texture.
Calibration
calibration in the panel, --scale-bar CAL on the command line.
CAL is the size of one pixel of the frames, in micrometers: 0.325, or with an explicit
unit, 325nm. That is the camera's pixel pitch divided by the magnification, or whatever a
stage micrometer measured.
Automatic calibration
auto (the command line's default for CAL) reads the calibration from the first frame's
TIFF metadata:
| Source | What is read |
|---|---|
| ImageJ | unit=micron in the ImageDescription, with XResolution in pixels per unit |
| OME-XML | PhysicalSizeX and PhysicalSizeXUnit |
| A plain TIFF resolution | In cm or inch, only from a writer that is not a camera |
That last condition matters: a camera's 72 or 300 dpi says nothing whatsoever about the subject, so a file with a Make tag is ignored for this purpose.
In the browser, after a run the calibration the first frame carries is offered with a use button, so you can accept it rather than typing it.
One number serves every output at full size. Alignment brings every frame onto frame 0's pixel grid and the crop only cuts that grid, so the calibration never has to be adjusted for the crop.
The bar
bar length in the panel, the optional :LENGTH in --scale-bar CAL:LENGTH.
Leave it empty and lapstack picks the 1–2–5 value nearest a fifth of the image width — 100 µm,
250 µm, 2 mm, whatever fits. Set it explicitly (100um, 2mm, 500nm) to control it. A
length that does not fit is brought down to the largest 1–2–5 value that does, and the log
says so.
The bar is snapped to whole pixels, and its length is written above it in whichever unit keeps the number under a thousand: 500 nm, 100 µm, 2.5 mm.
The caption
text in the panel, --text TEXT on the command line. \n breaks a line.
These tokens are filled in:
| Token | Becomes |
|---|---|
{date} | The first frame's capture date |
{time} | The first frame's capture time |
{frames} | The number of frames in the stack |
{first} | The first frame's file name, without extension |
{n} | The stack's number, in a batch |
lapstack --scale-bar auto:100um \
--text 'Drosophila melanogaster\n{frames} frames · {date}' \
-o figure.tif slide/*.tifPosition, size, color and style
| Control | Command line | Default |
|---|---|---|
| Corners | --overlay-pos BAR[,TEXT] — tl, tr, bl, br | br,bl |
| Size | --overlay-size PCT — the font's em as a percentage of image height | 3 |
| Color | --overlay-color white|black | white |
| Style | --overlay-style halo|box|plain | halo |
When bar and text share a corner, the text goes above the bar at the bottom of the image and below it at the top.
halo draws a thin outline in the opposite color — the ink dilated by a disk — which reads on any background and is the right default for a figure. box puts a translucent box behind instead. plain is neither.
Everything scales with the font size: the margins, the bar's thickness, the gap under the label and the halo's width are all fractions of the em. The same settings therefore give the same-looking figure at any resolution, and an animation shrunk to a smaller long edge carries the same bar, shrunk with it.
What you see is what you get
In the browser the engine renders the overlay for the saved file's size and returns RGBA patches over the corners it occupies, which the viewer draws over the Stack layers — LAP, DFR, WAV and the kept results — inside the crop window. So the screen shows what the file will carry. (Not while retouching: the brush preview lives on that canvas.)
The section's status line says what the bar came to, for example:
scale bar 100 µm = 308 px at 0.325 µm/px, bottom rightThe Save step's Scale bar and text switch leaves the overlay out of the files, and off the screen, without losing the settings. The settings are part of the panel's parameters, so they persist between sessions and travel inside a project file.
How it is drawn
The text is set in Fira Sans — the app's own face, a 30 KB subset of the Regular weight embedded in lapstack itself — and rasterized by lapstack, not by the browser or the system: a TrueType outline reader and the signed-area coverage accumulation of font-rs and stb_truetype v2, where each edge deposits the area it sweeps into the pixels it crosses and a running sum along the row gives exact anti-aliased coverage.
The overlay is a few small patches of coverage over the corners it occupies, so nothing the size of the image is ever allocated for it. This is why the same bar appears identically in the command-line output, the browser, and every animation frame.