qr-backup C restore program

In 2025, I posted two bounties for qr-backup. One I did myself, and the other has now been completed by Claude. The task was as follows:

qr-backup is designed to save to paper, and restore from the command-line.

[...]

this feature request is to add a printable, 1-page short C program which you can type in by hand, compile, and use to restore backups from an image.

This is a very difficult technical challenge in minimization. You should provide a 1-page (2KB) short version of qr-backup's restore process, written in C. Library use is not allowed.

[...]

The reward is 5 hours of my time and everlasting fame.

Claude has succeeded! Although, it took seven hours of my time to get it to succeed so... I'm deducting that. It gets nothing. Sorry, Claude.

First, I asked it to just write any C program that can do a restore. That's... already extremely hard, especially the QR decoding part. I really had to hand-hold it through how to set up testing. Advice: suggest red/green testing. I also had to tell it to test incrementally. For example, when decoding a QR, check where the finders are. Then compare that to where you know the finders are -- don't try testing end-to-end. Also -- a reminder to freely look at other open-source QR decoders, and add print debugging to that, to see intermediate output! For example, it's really useful to see the parsed grid of pixels from a QR, to make sure you're doing that step right.

Sampled QR (21x21):
#######....#..#######
#.....#..##.#.#.....#
#.###.#.##..#.#.###.#
#.###.#.#.#...#.###.#
#.###.#.##..#.#.###.#
#.....#.#.#.#.#.....#
#######.#.#.#.#######
........#............
#.#####..##.#.#####..
#..###.#######..#.###
#.#...##...###.##.#.#
#..#.#.##.#.#..#.....
.#.##.###.#..#.#.#...
........##.....#..#..
#######....#...#..##.
#.....#.#.###..##.#..
#.###.#.##.#.#.##.##.
#.###.#.#.#.#.#...#..
#.###.#.#.##.#..#.#..
#.....#..#..##.####.#
#######.##..#.#.##...

At this point, most of my contributions to LLM work are contributing my own heuristics, or noticing when they're stuck. In a couple months they won't need me past goal-setting. Also, I seem to be a bit better at logical thinking? LLMs are not great at debugging in the "human" way.

Anyway, eventually we got a working version! It's very complicated. First, we look at the image of a QR, and locate the "finders" -- the three squares on the corners.

 finders in three corners of a QR code
finders in three corners of a QR code

How do we locate them? They have black-white-black-white-black runs in the ratio of: 1:1:3:1:1, passing through the center, along horizontal and vertical lines.

 false positives are no big deal
false positives are no big deal

If it's rotated, it's still the same ratio through the center -- but every length is up to 41% longer.

This gets us several "candidate" centers. There might be some false positives (shown above), but the three real finders should be included. Then we basically guess the right finders, and run some checks. In the worst case, a check could be "try to decode the QR, assuming this is right" -- it's brute-force but it works.

 explaining the concept of flattening to a technical audience
explaining the concept of flattening to a technical audience

We apply homography to "flatten" and de-rotate the image, using the finder locations. Then we detect the QR version, size, encoding, and apply error correction for any damaged or smudged pixels.

Now we have a QR decoder! But the qr-backup process is a bit more complicated. We also:

  • Combine the QRs in order (they have numbers at the beginning of each)
  • Base-64 decode the contents of each
  • Apply erasure coding which restores missing or damaged QRs.
  • Decompress the zipped contents
  • Decrypt using standard gpg, using a user-supplied password
  • Do a checksum of the result to make sure the data is undamaged.

We do all of this with no libraries (other than libc).

The result is the qr_restore.c. It clocks in at 5300 lines (208K).

What's next? Why, we want to start trimming the fat of course. Let's remove any GPG features we don't need, redundant code, etc. We'll generate tables instead of hard-coding them. We'll remove intermediate debug outputs, like the .png s above showing where finders are.

This process takes multiple days and very hard work.

Now we have qr_strip.c, sitting at only 2000 lines of code. It's still human-readable, but much simpler.

Now the final pass. C code doesn't need whitespace. And why use all those long, descriptive variable names?

 why are all my code reviews just AAAAAAAAH
why are all my code reviews just AAAAAAAAH

Running it through a custom minifier, we reduce the size even smaller.

 from 208K to 35K
from 208K to 35K

If we print in really tiny font, we can fit that on a single page.


Limitations. At the time of writing, decoded some rotated/skewed QRs is a bit broken. I'm not sure why, they used to be working. I'll fix it soon, and post updated code/PDFs.

Tagged ,
leave comment

qr-backup bounties

I am offering two bounties to improve qr-backup. I think both are worth doing regardless.

My rewards are time-in-trade. You can use 5 or 10 hours of my time however you like. I usually charge over $100/hr, so this is a good deal.

If the github bugs are open, the bounties are unclaimed. I will try to update this post when they are claimed, too.

Bounty 1: Improve QR code scanning on Linux

Chances are, there is exactly one command-line program your distro has available to scan QR codes: zbar

Even on digitally-generated images, which are perfectly correct, pixel-aligned, and generally perfect, it still fails to read the codes sometimes. At least one-third of the bugs in the issue tracker are about this problem.

The bounty is to fix this issue in zbar, getting it to read QR codes with a 0% failure rate. The current failure rate is at least 0.1%.

A reproduction case and some debugging tips are in the bounty details.

The reward is 10 hours of my time.

Bounty 2: Code a one-page short C program to restore qr-backup backups

qr-backup is designed to save to paper, and restore from the command-line.

but, it's possible that someday we might lose all the nice infrastructure we have today.

  • you want to restore your backup, but you're poor and don't have an internet connection
  • no one runs "unix" any more. we just have neural meshes
  • it's been 50 years and you can't figure out how to install all these programs no one has heard of like "zbar" and "qr-backup"
  • your country has become a totalitarian state, and you can't be seen downloading "archiving" programs.
  • you are a lizard-person who has recovered piles of paper from a previous civilization. what secrets could they hold?

who knows! wouldn't it be great if you could still restore?

this feature request is to add a printable, 1-page short C program which you can type in by hand, compile, and use to restore backups from an image.


This is a very difficult technical challenge in minimization. You should provide a 1-page (2KB) short version of qr-backup's restore process, written in C. Library use is not allowed. Arguments will be accepted for other short programs if 2KB is impossible.

Details are in the bounty description.

A short version of the steps:

  • Read QR codes
  • Sort them, remove duplicates
  • Base64 decode each code
  • Erasure coding
  • Append and truncate
  • Decrypt
  • Decompress
  • Print SHA256 checksum

qr-backup actually prints a bash one-liner to do the restore, if you prefer to reference that.

Each of the steps is done by qr-backup in the most standard way possible. Decompression calls zcat, for example. You should be able to re-use existing code easily, the challenge is just to shrink it.

The reward is 5 hours of my time and everlasting fame.

Tagged
leave comment

qr-backup v1.1

qr-backup v1.1 is released. qr-backup is a command-line Linux program. You can use it to back up a file as a series of QR codes. You can restore the QR codes using a webcam or scanner, and get back the original file.

The main features of qr-backup are ease-of-use and futureproofing (restore does not require qr-backup).

Please report any bugs on github. Once this is stable, I will do the first pip/package manager release. To test the alpha, check out the latest code using git.

See also USAGE and extensive FAQ.

New features in v1.1:

  • Feature complete. New features are unlikely to be added. Future efforts will focus on quality, GUIs, and porting.
  • restore using qr-backup. Previously, the only restore was a bash one-liner (which still works).
    • qr-backup --restore restores using the webcam
    • qr-backup --restore IMAGE IMAGE IMAGE restores from scanned images
  • After generating a PDF backup, qr-backup automatically does a digital test of the restore process
  • Erasure coding. Lose up to 30% of QRs and restore will still work, as long as you are using qr-backup to restore
  • Increased code density, which about cancels out the erasure coding.
  • Back up directories and files. qr-backup makes a .tar file for you
  • Option to use password protection (encryption)
  • Option to print multiple copies of every QR code
  • Option to randomize order of QR codes
  • Optionally print extra cover sheet instructions on how to restore. For long-term archivists.
  • Option to add custom notes and labels to each page
  • Improved support for using qr-backup in a pipe
  • Various bugfixes
  • See CHANGELOG for complete details

P.S. As a special request, if anyone is on OS X, let me know if it works for you?

Tagged , ,
leave comment

qr-backup

qr-backup is a program to back up digital documents to physical paper. Restore is done with a webcam, video camera, or scanner. Someday smart phone cameras will work.

I’ve been making some progress on qr-backup v1.1. So far I’ve added:

  • --restore, which does a one-step restore for you, instead of needing a bash one-line restore process
  • --encrypt provides password-based encryption
  • An automatic restore check that checks the generated PDF. This is mostly useful for me while maintaining qr-backup, but it also provides peace-of-mind to users.
  • --instructions to give more fine-tuned control over printing instructions. There’s a “plain english” explanation of how qr-backup works that you can attach to the backup.
  • --note for adding an arbitrary message to every sheet
  • Base-64 encoding is now per-QR code, each QR is self-contained.
  • Codes are labeled N01/50 instead of 01/50, to support more code types in the future.
  • Code cleanup of QR generation process.
  • Several bugfixes.

v1.1 will be released when I make qr-backup feature complete:

  • Erasure coding, so you only need 70% of the QRs to do a restore.
  • Improve webcam restore slightly.

v1.2 will focus on adding a GUI and support for Windows, Mac, and Android. Switching off zbar is a requirement to allow multi-platform support, and will likely improve storage density.

Tagged , , , ,
leave comment