Add a logo without hiding essential QR data

Error correction lets a QR code survive damage, and a logo is deliberate damage. How much you can hide depends on which codewords the logo covers, not on a percentage of the picture.

Codewords, blocks and Reed–Solomon

A QR code doesn't store your text as a picture. It converts it into bytes called codewords, then adds extra error-correction codewords calculated with Reed–Solomon coding. Each codeword is 8 bits, drawn as 8 modules, usually in a 2-module-wide zigzag. Larger codes split the codewords into several blocks, each with its own error correction, and interleave the blocks so that a scratch in one area spreads its damage across several blocks.

When a decoder doesn't know where the damage is, which is the normal case, Reed–Solomon can repair up to half as many codewords in a block as that block has error-correction codewords. That per-block limit is the number that matters. If one block loses more than it can repair, the whole code fails, however healthy the other blocks are.

The four levels

ISO/IEC 18004 defines four error correction levels. DENSO WAVE, which created the QR code, describes theirrecovery capacity as a share of codewords:

LevelNameCodewords restorable (DENSO)
LLowabout 7%
MMediumabout 15%
QQuartileabout 25%
HHighabout 30%

Those are rounded, version-independent figures. The real numbers depend on the version. Here is version 4 (33 × 33 modules, 100 codewords in total), worked out from the block structure the standard specifies:

LevelBlocksData + EC per blockFixable per blockFixable in totalData codewords
L180 + 201010 (10%)80
M232 + 18918 (18%)64
Q224 + 261326 (26%)48
H49 + 16832 (32%)36

Notice the trade. Moving from L to H more than halves the room for your data, and at H the 100 codewords are split into four small blocks that can each fix only 8.

Why “H means a logo can cover 30%” is wrong

You'll often read that level H lets a logo cover 30% of a QR code. It mixes up two different things. The 30% is a share of codewords, and it's the theoretical maximum when nothing else is wrong. A logo is measured in area. Several things separate the two:

  • Partly covered codewords are lost entirely. A codeword is 8 modules in an irregular zigzag. If the logo's edge hides even one of them, that codeword is probably wrong, so a logo damages more codewords than its area suggests.
  • Not all of the area is data. The finder patterns, timing patterns, format information and quiet zone take up a large share of the image. A logo of a given area covers a larger share of the data region than of the whole code.
  • The worst block decides. Damage isn't shared out evenly. A centered logo can hit one block much harder than another, and that block fails first.
  • Real prints need spare capacity. If the logo uses all the error correction, there's nothing left for glare, a scuff, a fold or a slightly blurry photo. A code that scans perfectly on screen can then fail on a crumpled flyer.

So a logo should use well under the theoretical capacity, and the only reliable way to know how much it uses is to count the codewords it actually hides.

What a logo really hides

Both diagrams below encode the same link with the same logo knockout, about 18% of the code's width plus one module of padding. The dashed square is the knockout. Magenta and pink modules sit outside it but belong to codewords the logo has already damaged, so they're wasted too.

Too much at level QLevel Q. At level Q (version 4), this logo hides 81 modules carrying parts of 17 codewords, which uses up to 77% of one block's correction capacity.
Comfortable at level HLevel H. The code grows a version, and each block has more to spare. At level H (version 5), this logo hides 81 modules carrying parts of 15 codewords, which uses up to 36% of one block's correction capacity.

At Q the knockout is only about 7% of the symbol's area, yet it uses over three quarters of one block's correction capacity, because of which codewords it lands on. That's the gap between area and codewords. The generator would reject Q here and choose H.

How our generator chooses the level

We don't use a rule of thumb. When you add a logo, the generator:

  1. Encodes your content at level Q and works out the logo's knockout area: the logo plus its padding, kept clear of the finder patterns.
  2. Lists every module in that area and looks up which codeword each one belongs to.
  3. Groups the damaged codewords by Reed–Solomon block and compares each block's count with what that block can repair.
  4. Accepts the level if no block uses more than half of its correction capacity. Otherwise it tries again at H. If the logo is still too large at H, it tries up to three larger versions at H, because a slightly bigger grid fits the same logo with less damage per block. If none fits, it keeps H and tells you to make the logo smaller.

Without a logo it uses M, which is a sensible default for print, and moves up for free when a higher level fits in the same number of modules. You can always override the level by hand.

The scan check then reports the result in plain terms: how many codewords the logo hides, and the largest share of any block's error correction it uses, like the figures under the diagram above. It passes up to 50%, warns up to 80% and fails beyond that. The half-capacity budget is our own conservative choice, not a number from the standard. It leaves the other half for real-world damage.

Finally, the check decodes the actual styled artwork, logo included, so you're not relying on the arithmetic alone.

Higher error correction makes the code denser

Error-correction codewords take space. At a higher level, the same content needs a larger version with more, smaller modules at any given print size. Here's one link, https://example.com/spring-menu?table=12&lang=en, at each level:

LevelVersionModules
L329 × 29
M433 × 33
Q537 × 37
H641 × 41

Denser codes need to be printed larger to keep each module readable (see the print size guide). That's why “always use H” isn't free advice, and why we only raise the level as far as the logo needs.

Keep the function patterns intact

Error correction protects codewords only. The structures that let a scanner find and read the grid are not codewords, and if they're damaged, error correction can't help:

Blue: finder patterns and separators. Magenta: timing patterns. Green: alignment patterns. Brown: format and version information. Grey: data and error-correction codewords.
  • Finder patterns, the three large corner squares, tell the scanner where the code is and which way up it is.
  • Timing patterns, alternating lines between the finders, set the module grid.
  • Alignment patterns, the small squares in version 2 and up, correct for perspective and curved surfaces. From version 7 there's one in the center, which a centered logo will cover. Decoders still have the others, but it's another reason to test the real artwork.
  • Format and version information tell the decoder the error correction level, mask and version. It's stored twice with its own small error-correcting code, but it isn't covered by the Reed–Solomon blocks.

Decorative module shapes are fine as long as each module stays clearly dark or light at its center. Heavy styling of the finder patterns, or a logo that drifts into a corner, is a common reason designed codes fail.

Practical guidance

  • Keep the logo simple and centered, with a little padding of plain background around it.
  • Shorter content gives more room: fewer data codewords means a logo of the same size hides a smaller share.
  • Aim for the logo to use half or less of the error correction, as the generator's check reports.
  • Print at a size where modules stay above about 0.5 mm, and test the printed code on several phones.

Ready? Make a QR code with your logo.