~BI - Background Image
A Labelary extension, not a ZPL command: draws a Base64-encoded image behind the label to simulate colored or pre-printed stock.
~BI is not a ZPL command. Labelary added it to its own renderer so that a
preview can show colored or pre-printed stock. It registers a Base64-encoded
image, usually a PNG, and draws it behind the label. No Zebra printer implements
it, it appears in no Zebra reference, and it is absent even from Labelary's own
230-row command table. The only place that documents it is Labelary's command
reference, which flags it as a Labelary extension, one of exactly two alongside
~BR. A format that contains it is therefore not portable: on real hardware the
BI mnemonic is ^BI, the industrial 2 of 5 bar code.
Syntax
~BIx,y,m,imageSupport
Recognised as valid ZPL and not implemented yet, so it has no effect on the output.
A Labelary-specific extension rather than ZPL, so no Zebra printer accepts it and it appears in no Zebra reference and in no Labelary command table. It draws a background, so it would change the rendered label. That makes it a real gap, not a safe command to ignore, and nothing schedules it yet. The renderer also does not recognize its own name. The dispatcher matches the two-character mnemonic without the prefix, so the parser reads it as ^BI industrial 2 of 5. It reports no unknown command; see the recorded deviations. — not pinned by a test
Absent from Labelary's command table.
Parameters
xHorizontal positionoptional · dotsLeft edge of the image, measured from the left edge of the label.
- Default
- 0
- Accepted range
- 0 to the label width dots
- Invalid value
- not documented, and we have not measured it. Labelary documents the bounds but not what a position past the label edge does; the renderer does not implement the command.
- Test coverage
- No test at the minimum, maximum or one step outside the range.
yVertical positionoptional · dotsTop edge of the image, measured from the top of the label.
- Default
- 0
- Accepted range
- 0 to the label height dots
- Invalid value
- not documented, and we have not measured it. Labelary documents the bounds but not what a position past the label edge does; the renderer does not implement the command.
- Test coverage
- No test at the minimum, maximum or one step outside the range.
mMagnificationoptional · decimalScale for the image before the renderer draws it. The range starts below 1, so the image can shrink as well as grow; ^XG's magnification starts at 1.
- Default
- 1
- Accepted range
- 0.1 to 10 ×
- Invalid value
- not documented, and we have not measured it. Labelary documents the bounds but not the behavior outside them; the renderer does not implement the command.
- Test coverage
- No test at the minimum, maximum or one step outside the range.
imageImage dataoptional · textThe background image, usually a PNG, Base64-encoded. A ~BI with no arguments clears every background image registered so far.
- Default
- absent, which clears the registered background images
- Invalid value
- not documented, and we have not measured it. Labelary does not document what undecodable data or an unsupported image format does; the renderer does not implement the command.
- Test coverage
Behavior
It registers an image, it is not a field
^FO and ^FT do not position ~BI, ^FS does not close it, and it belongs
to no one label. Labelary registers the image and draws it behind every label it
renders from then on. Measured against api.labelary.com at 8dpmm on
2026-07-29:
- Registration outlives
^XZ. A~BIbefore the first^XAof a two-label format tints the second label as well as the first. - Registrations accumulate. Two
~BIcommands draw two images, and the second does not replace the first. ~BIwith no arguments at all clears every image registered so far, and the labels after it come out plain. That is the only way to remove one.- Either side of
^XAworks. A~BIinside the format draws the same background as a~BIbefore it.
Size and layers
One pixel of the image becomes one dot on the label, multiplied by the
magnification: a 16 by 16 pixel PNG at magnification 10 covers 160 by 160
dots. Magnification goes down to 0.1, so ~BI can shrink an image as well as
enlarge it. The equivalent range of ^XG starts at 1 and only enlarges.
The image sits behind everything the format prints. Text and bar codes drawn over it stay black and legible, and no field can go underneath it.
What this service does
The renderer draws no background, so the label renders on plain white. It reports the command once, as valid ZPL this renderer does not support yet, and reads nothing else out of it.
Until August 2026 the parser dispatched on the two-character mnemonic alone and
did not check the prefix, so ~BI… reached the code path for ^BI industrial
2 of 5. That read the coordinates and the Base64 payload as bar code arguments. It
answered six warnings about a bar code that is not there. Inside ^XA … ^XZ
it also made the next field a bar code field, so ~BI0,0,10,… followed by
^FO70,90^A0N,30,30^FDColoured stock^FS drew nothing at all. ~BI is now its
own command and neither happens.
Colored stock in production
ZPL cannot do it. A thermal printer marks the media in a single color, and the
language has no color model. The color argument of ^GB chooses between black
ink and white erasure, not between hues. Color comes from the media: order
colored or pre-printed stock and let the printer put black on top of it. Keep
~BI for previews if it helps, and strip it before the format reaches a
printer.
Differences from the specification
Labelary against the ZPL II guide
Where Labelary — our compatibility target — behaves differently from the printed specification.
- The command is not in the ZPL II guide, and it is in no Labelary command table either. It is Labelary's own extension, one of exactly two, and only the engine's behavior documents it. — not pinned by a test
zpl.tools against Labelary
Where our output differs from Labelary for the same input. These are the differences that break a migration.
- Labelary draws the image behind the label; the renderer draws no background, so the label renders on plain white. — not pinned by a test
- The parser dispatches on the two-character mnemonic without the prefix, so
~BIreaches the^BIindustrial 2 of 5 arm. It reads the coordinates and Base64 payload as bar code arguments. No diagnostic reports the mismatch. The renderer instead reports six argument warnings against~BI. We measured this on 2026-07-29 with~BI50,50,10,<png>: they readValue '50' is too long and was trimmed to '5'andValue '5' is not a supported value for this argument and was ignored. — not pinned by a test - Because
^BIis a bar code command, a~BIinside^XA…^XZmakes the next field a bar code field. We measured this on 2026-07-29: the following^FDColored stock^FSdraws nothing instead of text, so the label comes out blank. Before^XA, where Labelary's own examples put it, the misparse costs only the warnings and the label renders normally. — not pinned by a test
Example
A 16 by 16 pixel yellow PNG at magnification 10, so it covers 160 by 160 dots starting at (50, 50), with a line of text printed over it:
~BI50,50,10,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAFklEQVR42mP486eSJMQwqmFUw/DVAADGI3Efc+IpFwAAAABJRU5ErkJggg==
^XA
^FO70,90^A0N,30,30^FDBackground image^FS
^XZ
Related commands
~BRBackground RectangleA Labelary extension, not a ZPL command: fills a rectangle in an RGB color behind the label to simulate colored stock.^BIIndustrial 2 of 5 Bar CodeNumeric symbology that encodes data in the bars only. The spaces are separators only.^GFGraphic FieldDraws a bitmap sent inline with the label.^XGRecall GraphicDraws a previously downloaded graphic, optionally magnified.^GBGraphic BoxDraws a rectangle, a line or a filled block.