zpl.tools
Label geometry

^MU - Set Units of Measurement

Switches position and size arguments from dots to inches or millimeters.

^MU changes the unit of every length in the format, so a layout in millimeters or inches keeps its physical size on printers of different densities. Its second and third arguments do the related job in dots: they scale a format authored for one resolution onto a higher one. ^MU is a mode, not a hint for ^FO alone. It rewrites the length arguments of nearly every command that follows, including font sizes, bar code heights and ^BY module widths.

Syntax

^MUa,b,c

Support

Supportedparsed: full · state: full · rendered: full

Every documented parameter renders the same output Labelary produces.

Labelary renders this command.

Parameters

aUnitsoptional · one of a set

Unit for every later length argument. It applies to the commands that follow, never to ^MU itself, and stays in force across ^XZ into the next format.

Default
D
Invalid value
discarded, and the current value is kept. An unrecognized unit letter, or a bare ^MU, leaves the current unit in place. Lower case works too.
Test coverage
Values exercised: D, I, M. The invalid-value rule is pinned by 1 test.
D
Dots (default)
I
Inches
M
Millimeters
bBase dots per inchoptional · one of a set

Resolution the label assumes. Together with c this rescales a format built for one printer onto another, by the integer factor c / b.

Default
no resolution conversion, or the factor an earlier ^MU set
Invalid value
discarded, and the current value is kept. The parser validates b and c as a pair. Both must be one of the four values, and c must be a whole multiple of b. A rejected pair leaves the current conversion factor untouched.
Test coverage
Values exercised: 150, 300. Not exercised: 200, 600. The invalid-value rule is not pinned by a test.
150
Authored for a 6 dot/mm printer
200
Authored for an 8 dot/mm printer
300
Authored for a 12 dot/mm printer
600
Authored for a 24 dot/mm printer
cTarget dots per inchoptional · one of a set

Resolution to scale to. Only ever scales up: c must be b or an integer multiple of it.

Default
no resolution conversion, or the factor an earlier ^MU set
Invalid value
discarded, and the current value is kept. See b: the pair is accepted or rejected together.
Test coverage
Values exercised: 300. Not exercised: 150, 200, 600. The invalid-value rule is pinned by 2 tests.
150
Render as for a 6 dot/mm printer
200
Render as for an 8 dot/mm printer
300
Render as for a 12 dot/mm printer
600
Render as for a 24 dot/mm printer

Behavior

What gets converted

Every length-valued argument, and we measured these pairwise against Labelary:

  • ^FO and ^FT positions
  • ^LH, ^LS, ^LT, ^PW and ^LL
  • the width, height and border thickness of ^GB and the other graphic commands
  • the height and width of ^A, ^A@ and ^CF
  • both arguments of ^BY
  • the height argument of every bar code command

So ^MUI^BY.05,3,1 and ^MUD^BY10,3,200 render the same symbol.

^FB is the exception. Its width, line spacing and hanging indent stay in dots under every unit mode and under the resolution factor. A ^MUM format that sets a field block width of 50 gets 50 dots, not 50 mm — which silently breaks the text wrap in a format that assumes otherwise. Counts, indices, flags and field data stay untouched.

A fractional value rounds to the nearest dot. That also applies in dots mode, where ^FO.493,.493 places the field at 0,0.

Order of conversion

The renderer converts each command with the mode in force at it, so a format can switch modes and each field keeps its author's units. The mode is sticky. It survives ^XZ into the next format in the same submission, and a bare ^MU or an unrecognized letter leaves it unchanged rather than reset to dots. The renderer accepts lower case, so ^MUi and ^MUI are the same.

The renderer checks range limits after conversion, on the resulting dot value. That is why ^MUI^LS60 clamps to 9999 dots and ^MUI^LT1 — 200 dot rows, past the ±120 of ^LT — does nothing at all.

The resolution factor

b and c are a pair: an author wrote the format for b dots per inch, and the renderer must render it as though for c. Every dot value multiplies by c / b, so ^MUD,150,300 doubles the label. The renderer accepts whole-number increases only — both values must be one of 150, 200, 300 and 600, and c must be an exact multiple of b. The renderer rejects ^MUD,150,250 and ^MUD,300,150, and leaves the current factor alone.

Two details that are easy to get wrong:

  • The factor applies to dots mode only. Under ^MUI or ^MUM the renderer ignores it, because an inch is an inch whatever the format was authored for.
  • The renderer holds the factor independently of the unit mode, and a later ^MU that omits b and c does not clear it. ^MUD,150,300^MUD still doubles.

Inch conversion at 25 mm

^MUI converts one inch to dots per mm × 25 dots — 200 at 8 dot/mm, 150 at 6, 300 at 12, 600 at 24 — rather than to the true dot-per-inch figure. Millimeters use the exact device density. This matches Labelary and diverges from the guide, whose own three-way equivalence example on p. 231 assumes 203 dots per inch and so is not pixel-identical. Where a dimension must be exact, write it in millimeters or dots.

Tested behavior

Differences from the specification

Labelary against the ZPL II guide

Where Labelary — our compatibility target — behaves differently from the printed specification.

  • Labelary converts inches as though an inch were 25 mm, not 25.4. At 8 dot/mm, ^MUI^FO1,1 lands at 200 dots rather than the 203 the guide's own worked example on p. 231 implies. We measured this across 6, 8, 12 and 24 dot/mm on 2026-07-28: the factor is always dots per mm × 25. Millimeters use the exact device density. — pinned by test_mu_inches_scale_positions
  • The guide restricts b to 150, 200 or 300 and c to 300 or 600. Labelary accepts any pair drawn from 150, 200, 300 and 600 where c is a whole multiple of b. So Labelary honors ^MUD,200,200 and ^MUD,150,600 where the guide does not list them. — not pinned by a test
  • The guide describes b and c as a general lower-resolution printing feature. Labelary applies the factor to dot values only, and ignores b and c outside D mode. — not pinned by a test

zpl.tools against the ZPL II guide

Where our renderer behaves differently from the specification.

  • The renderer follows Labelary on all three points above, including the 25-millimeter inch, because Labelary is the compatibility target. — not pinned by a test

Example

The same 400-by-100-dot box twice, once in millimeters and once in dots. At 8 dot/mm, 50 mm by 12.5 mm is 400 by 100 dots, and both boxes come out the same size:

^XA
^MUM
^FO12.5,12.5^GB50,12.5,12.5^FS
^MUD
^FO100,250^GB400,100,100^FS
^XZ

Open in viewer

A format authored for a 6 dot/mm printer, rendered at 12 dot/mm. Every dot value doubles — the origin, the font size and the box — so the layout keeps its proportions:

^XA
^MUD,150,300
^FO25,25^A0N,20,20^FDauthored for 150 dpi^FS
^FO25,60^GB200,15,15^FS
^XZ

Open in viewer