Transfer files over the air via your smartphone’s camera – InformTFB

Transfer files over the air via your smartphone’s camera

Transfer files over the air via your smartphone’s camera

The problem

Barcodes are great for marking everything from products to people. Now there are about two dozen standards for two-dimensional barcodes in use, and dozens more unsuccessful, tragically misunderstood, self-made and internal corporate options, most of which miserably lose to the usual QR code. Its prevalence and ease of implementation have made it the most popular among two-dimensional barcodes, but it also has a drawback common to all linear counterparts: it contains very little information. In 2-3 kilobytes, you can fit a link or a small piece of text, but even a small picture or an ordinary document will not fit even in the largest code.

It is clear that the capacity of a regular QR-like square can be increased by increasing the size of the matrix, adding colors and playing with the shape of the cells. There is no single standard for such extended codes, except for the proprietary Microsoft Tag (HCCB) with unclear prospects for development and use. Expanding the palette and changing pixels also makes it harder to read code in difficult conditions (poor printing, color or insufficient lighting), but it still gives a very limited increase in capacity and does not allow you to transfer even megabytes of data without pain.

A good example of such a self — made standard is Jabcode

It has long been proposed to solve the problem radically: unlike linear barcodes, QR codes are found not only in printed form, but also on device screens in applications and on websites. So, if you have to give up something in the standard, let it be the ability to physically print the code — let’s make it animated! Thus, we instantly turn a static square into a source of unlimited data that can be transmitted over the air without connecting to any networks. Of course, the transfer rate will be low, and a regular QR reader will not be able to process such a code, but the decoding principle is almost the same and you will not have to reinvent the wheel.


The first ready-made and well-thought-out implementation, of all that I could find, was TXQR from Ivan Danilyuk (blog, GitHub). The project has a go specification and PoC with an iOS app.

At first, the TXQR code simply scrolled through the usual QR codes in a loop, and the phone tried to read them as accurately as possible, receiving error correction only when the loop was repeated the next time. In tests, the author drove a 13-kilobyte file, getting a peak speed of 9 KB/s. In the next iteration, the format began to use fountain codes (more precisely, Luby transform code), so that through redundancy you can perform error correction in any frames without waiting for the loop to scroll:

In short, the source data is divided into blocks that are randomly XORed into encoded blocks that are already being sent to frames. Some blocks may not stick together, which reduces the overhead. On the client, the blocks received from frames are XORed together with the data already received, resulting in the original data structure checked for errors. You can read more on the wiki and in the article Ivana about switching to fountain codes. In General, despite the significant overhead, the data decoding speed has significantly increased:

Now, at its peak, TXQR outputs about 25 KB / s with a low error correction level. Let’s remember this value and move on to its successor, created two years later. Meet me,


Cimbar (Color Icon Matrix bar codes) has moved further away from the QR code standard, retaining only visual similarity. This format squeezes out as much bandwidth as possible, using colors at once, 8×8 icons instead of regular pixels, and, of course, animation. 4 bits of information are encoded in one cell, and another 2 or 3 bits are added by using a color scheme (for 4 or 8 colors), allowing you to store up to 7 bits in one cell:

Encoding in cimbar follows an algorithm similar to image hashing: the decoder compares a 4×4 tile with a dictionary of 16 expected tiles and selects the one with the closest hash. Similarly, for each tile, the average color is taken and compared with the dictionary of expected colors, then the nearest one is selected. Then the received data is checked for errors using the reed-Solomon code combination. Wirehair is used for fountain codes. In the current (not final) format, the grid size is 1024 x 1024 characters, and when used on small screens or with a bad camera, the code does not always read well, so the developer is considering sacrificing bandwidth for the sake of versatility.

The final image looks rather creepy and epileptic, but it allows you to achieve a stable 700-800 KB/s at the usual correction level! This is 32 times faster than the peak speed of TXQR with low error correction, and you can see this for yourself:

  1. Go to and upload a heavier file. At first, it’s better not to go to extremes, I once tried downloading a 10-megabyte. apk and got tired of holding the phone on weight while it was swinging, so it’s worth starting with 500KB-2MB.
  2. Download the app for Android
  3. Turn on airplane mode and scan the code. Don’t forget to choose the right color palette, by default, the website and app is 4 colors.
  4. Enjoy the magic!


So far, the project exists as a PoC, but the developer clearly wants to bring it to mind and develop it into a useful standard. Docks and Python implementations are located in the main repository, the optimized C/C++ library lives separately, and the mobile application is here. On the site the encoder works via wasm, the repo could not be found.

Air-gapped data transfer is cool and always fun to come up with use cases for them. I’ve already tried passing apps through cimbar, and I see a lot of interesting features in it. If you also have some original ideas, we’ll discuss them in the comments.

Valery Radokhleb
Valery Radokhleb
Web developer, designer

Leave a Reply

Your email address will not be published. Required fields are marked *