A generated Code 128 image comes out of the generator at the size its module count dictates, and the box your form or label gives it is almost always smaller. The reflex is to scale the bitmap down, and that reflex destroys the symbol. This guide gives you the arithmetic that solves the size problem properly: the width a Code 128 really needs, the two properties that control it, a worked 100 × 31 px example, and a print-and-scan test that proves the result still reads. It is written for developers embedding generated codes in software and for anyone sizing labels for fixed code readers.
Why can't you just resize the finished barcode image?
Because at the minimum module width of X = 1 px, every narrow bar is a single pixel column with nothing to spare: resampling a 165 px symbol into a 100 px bitmap merges neighbouring bars into grey bands the decoder can no longer separate.
A resample computes each destination pixel as a weighted average of source pixels, so a one-pixel black bar beside a one-pixel white space becomes two grey columns. The decoder thresholds those greys back into bar widths, and one width recovered half a module off fails the whole decode. It is the same edge damage that the 1D barcode preprocessing for rotation, blur and glare guide repairs on camera frames — except here you would inject it deliberately.
The read-only width error pushes people into the same trap. An Image's Width and Height are read-only in .NET, so the usual workaround, constructing a new Bitmap at the target size, performs exactly the resample above. Both roads end at a softened symbol; the fix belongs in the generator, before the bitmap exists.
What sets the minimum width of a Code 128 image?
Symbol geometry, not the canvas: every Code 128 character spans 11 modules, the stop pattern spans 13, and a mandatory quiet zone of 10X runs at each end, so the symbol needs W = X × (11c + 55) pixel columns whatever canvas width you request.
Each character is 3 bars and 3 spaces totalling 11 modules, and the check character is mandatory in the Code 128 symbology. The quiet zones are part of the symbol, not decoration: 10X of white at each side, X being the module width. In pixels:
The +20 is the two quiet zones of 10X each, and 11 × (c + 2) + 13 + 20 expands to 11c + 55. You count only data characters (c); the generator adds start, check and stop itself. In subset C one character carries two digits, which is why numeric payloads encode half as wide. The same module-width-first thinking runs through barcode module width for document scanning.
How do you fit a 100 × 31 px target with real data?
Change the data, not the pixels: a 10-character folio needs 165 px at that minimum module width, so a 100 px box holds either 4 alphanumeric characters or, if the folio is numeric, 8 digits packed two-per-character in subset C, which measures 99 px.
Worked example: an order folio into a 100 × 31 px box, modules one pixel wide.
- Alphanumeric payload of 10 characters: c = 10, so W = 1 × (11 × 10 + 55) = 165 px. That is 65 px over the box.
- The same folio as 10 digits in subset C: c = 5, so W = 1 × (11 × 5 + 55) = 110 px. Still 10 px over.
- An 8-digit numeric folio in subset C: c = 4, so W = 1 × (11 × 4 + 55) = 99 px. It fits, quiet zones included.
Height is the easy dimension: 31 px of bars is comfortable, and Y is free geometry. Set Y to 24-31 px here, and keep it at 15 × X or more as a practical floor, so the decoder gets several scan rows before dust, tilt or glare eats one. Subset choice has payload consequences too, which the Code 128 codeset B length limits guide shows for long labels.
Decision for the 100 × 31 case: an 8-digit numeric folio fits at the minimum width with 1 px of margin; a 10-digit folio needs a 110 px box; the 10-character alphanumeric payload needs 165 px or a shorter code.
What do you set in the generator instead of resizing?
Set X to the module width your target process resolves, set Y to the bar height, and let the generator lay out the canvas: with auto-resize enabled, a canvas below the symbol minimum resets to the minimum instead of clipping bars.
- Set the symbology to Code 128 with automatic subset selection. A fixed CODE128A type forces every digit into its own 11-module character; letting the encoder choose subset C for digit runs halves a numeric folio's width.
- Set X = 1 px for on-screen use. For a 203 dpi thermal printer, size in dots instead: one dot is 25.4 / 203 = 0.125 mm, so X = 2-4 dots gives modules of 0.25-0.5 mm, a robust floor for thermal transfer.
- Set Y = 24-31 px, never below 15 × X. Taller bars only add scan rows; they cost nothing but vertical space.
- Enable AutoResize and set BarcodeWidth and BarcodeHeight to your canvas target. With auto-resize on, a canvas smaller than the symbol minimum resets to that minimum rather than clipping, so the output bitmap carries the true size.
- Keep both quiet zones in the render: 10 px of white at each end at the minimum module width, unclipped by the canvas edges.
- Export PNG at the final size and display or print at 100 % scale — never JPEG, never a scale afterwards.
How do you verify the resized code still reads?
Scan the real symbol ten times before you ship it: ten clean reads at 0°, at 90° (ladder orientation) and at ±30° tilt, from the distance your reader is rated for, prove the size; a single miss means one more module width of X and a re-print.
Print at 1:1 — a print dialog left on fit-to-page turns a 165 px label into 150 px silently, and that failure follows the label for weeks. On screen, test at 100 % zoom and at the smallest size your UI ever shows. The Code 128 module size, reading angle and reader distance guide explains how angle and distance trade against module size.
For a bench check inside the printed 60-120 mm reading distance of a compact reader like the LS-CRD-0047, mount the label flat and scan straight on. For desk audits, the handheld LS-HCR-0001 reads over USB 2.0, and handheld code readers generally suit spot checks away from the line.
- Resolution
- Up to 3 MP
- Shutter
- Global
- Resolution
- Up to 3 MP
- Shutter
- Global
On the line, a compact fixed reader such as the MV-ID3013PM-12M-WBN integrates over Fast Ethernet and reads at a fixed standoff, the arrangement most generated-code labels end up in.
- Interface
- Fast Ethernet
- Resolution
- Up to 3 MP
- Shutter
- Global
- Lens mount
- M12
Pass is 10 of 10 at every angle. A size that reads at one distance only counts as failing: production never reproduces the bench.
When is a smaller image the wrong fix?
When the payload is fixed and the box is under 11c + 55 px, no library setting will fit the symbol: shorten the data, pack digits in subset C, or switch to a 2D symbology such as Data Matrix, which packs far more data per pixel column.
| Case | Fix | Width at one-pixel modules |
|---|---|---|
| 8-digit numeric folio, 100 px box | subset C, X = 1 px | 99 px |
| 10-digit folio, 100 px box | widen the box to 110 px, or truncate to 8 digits | 110 px |
| 10-character alphanumeric, 100 px box | 165 px box, or a shorter payload | 165 px |
| Tiny fixed box, growing payload | a 2D code (Data Matrix, QR) instead | not a linear symbol |
Enlarging is the safe direction: re-render at X = 2 or X = 3 px and every bar edge stays a clean column boundary — the integer-scaling rule from QR code quiet zone and integer module scaling for exact image size applies to Code 128 unchanged. Fractional scales such as 1.7× resample and blur. A move to 2D changes the decoder too: QR and Data Matrix carry their own finder patterns and quiet zones (four modules for QR), so the never-resample rule carries over with them.
What do you check before the label goes to print?
Six checks catch every failure mode above before the printer does: the width arithmetic with the real payload, quiet zones of 10X per side, bar height at 15 × X or more, a lossless PNG, 100 % scale at print and on screen, and a ten-scan pass at the reader's rated distance.
- Width arithmetic — W ≥ X × (11c + 55) with the real payload and subset. It is the only guarantee the canvas can hold the symbol.
- Quiet zones — 10X each side, rendered white and unclipped. Decoders anchor the first and last character on them.
- Bar height — Y ≥ 15 × X as the practical floor (24-31 px in the worked example).
- File format — PNG or another lossless export. Lossy formats smear single-pixel bar edges.
- Scale — 100 % at print and on screen. Fit-to-page resampling undoes everything above.
- Ten-scan test — 10 of 10 reads at 0°, 90° and ±30°. One miss at any angle fails.
When those pass, the code is done: sized from the payload, rendered once, proven by scans. If you are also choosing hardware to run the check on a line, the code reader finder and the system configurator take you from module width to a matched reader, and the code-reading guides cover the reading side from angles to preprocessing.
Questions
Can I crop the quiet zone to make the image narrower?
No. The 10X quiet zones are mandatory and decoders anchor on them; cropping the white margin to save 20 px is the fastest way to kill the read rate of an otherwise valid symbol. If width is that tight, the payload needs subset C or a shorter value — the zone stays.
Why does my code read on screen but fail on the printed label?
Three usual causes: the print dialog rescaled the image, the file was exported lossy, or the bars were rendered anti-aliased grey instead of pure black. Export PNG with hard black bars, print at 100 % scale, and compare the paper symbol's width with X × (11c + 55) before scanning.
Does JPEG compression break a barcode image?
It can. Lossy compression rounds pixel values along bar edges, and at a one-pixel module width a single softened column shifts a measured bar width enough to fail the decode. Export PNG or another lossless format as the master; if a JPEG copy is unavoidable for a preview thumbnail, keep the PNG for anything printed or scanned.
Do the same resizing rules apply to QR codes?
The principle carries over, the geometry changes. A QR symbol's module count is fixed by its version — 21 × 21 modules at version 1, then four more modules per version — so its minimum size is modules × X plus the 4-module quiet zone. Set X in the generator; resampling smears the finder patterns first.
What distance should I use when testing a resized code?
The reader's own rated range. The LS-CRD-0047, for example, prints a 60-120 mm reading distance, so test across that span. Add 0°, 90° and ±30° tilt rather than one sweet spot: a code that reads only at a single distance or angle will fail once mounting tolerances stack up in production.


