^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,cSupport
Every documented parameter renders the same output Labelary produces.
Labelary renders this command.
Parameters
aUnitsoptional · one of a setUnit 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 setResolution 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
^MUset - Invalid value
- discarded, and the current value is kept. The parser validates
bandcas a pair. Both must be one of the four values, andcmust be a whole multiple ofb. 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 setResolution 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
^MUset - 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:
^FOand^FTpositions^LH,^LS,^LT,^PWand^LL- the width, height and border thickness of
^GBand 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
^MUIor^MUMthe 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
^MUthat omitsbandcdoes not clear it.^MUD,150,300^MUDstill 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,1lands 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 alwaysdots per mm × 25. Millimeters use the exact device density. — pinned bytest_mu_inches_scale_positions - The guide restricts
bto 150, 200 or 300 andcto 300 or 600. Labelary accepts any pair drawn from 150, 200, 300 and 600 wherecis a whole multiple ofb. So Labelary honors^MUD,200,200and^MUD,150,600where the guide does not list them. — not pinned by a test - The guide describes
bandcas a general lower-resolution printing feature. Labelary applies the factor to dot values only, and ignoresbandcoutsideDmode. — 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
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
Related commands
^FOField OriginSets the top-left corner of the next field.^GBGraphic BoxDraws a rectangle, a line or a filled block.^JMSet Dots per MillimetreHalves the print density, which doubles the physical size of everything on the label.^PWPrint WidthSets the printable width of the label.