DEV Community

Cover image for I Built a QR-Inspired Code That Uses 4 Colors, Stores More Data, and Supports Encryption
Akansh Sirohi
Akansh Sirohi

Posted on

I Built a QR-Inspired Code That Uses 4 Colors, Stores More Data, and Supports Encryption

QR codes are everywhere.

Payments, login flows, restaurant menus, Wi-Fi sharing, tickets, product packaging, device pairing, authentication, links. They have become one of those technologies that quietly works almost everywhere.

And there is a very good reason for that.

QR Code is mature, standardized, extremely well optimized, and surprisingly resilient.

But while working with QR codes, I kept thinking about one simple question:

Why are we still representing data using only two visible states when the cameras scanning these codes can distinguish millions of colors?

A traditional QR data module is effectively binary:

Black → one state
White → another state
Enter fullscreen mode Exit fullscreen mode

So one data module represents one binary choice.

Modern cameras, displays, image processing, and computing hardware are far more capable than when QR Code was originally designed.

That led me to an experiment:

What happens if a QR-inspired matrix code uses four reliably distinguishable visual states instead of two?

That experiment became QuadQR.

QuadQR is an experimental open-source 2D matrix-code format that uses Red, Green, Blue, and White as its four data states.

It now includes:

  • 2 bits per data cell
  • RGBW color calibration
  • perspective correction
  • camera scanning
  • image scanning
  • Reed-Solomon error correction
  • confidence-assisted error recovery
  • spectral-spatial interleaving
  • CRC integrity checking
  • optional AES-256-GCM encrypted payloads
  • password and raw-key security modes
  • multiple scanner-safe visual styles
  • Node.js and browser APIs
  • CLI support
  • npm distribution
  • benchmark tooling
  • a documented wire format

And yes, you can already generate and scan one in your browser.

Live Demo:
https://akanshsirohi.github.io/QuadQR/demo/

Documentation:
https://akanshsirohi.github.io/QuadQR/docs-site/

GitHub:
https://github.com/akanshSirohi/QuadQR

npm:
https://www.npmjs.com/package/quadqr-js


The basic idea

The core idea is surprisingly simple.

A binary module gives us:

2 possible states

log2(2) = 1 bit
Enter fullscreen mode Exit fullscreen mode

If we can reliably distinguish four states:

4 possible states

log2(4) = 2 bits
Enter fullscreen mode Exit fullscreen mode

So QuadQR uses:

Color Bits
Red 00
Green 01
Blue 10
White 11

One QuadQR data cell therefore carries exactly:

2 bits
Enter fullscreen mode Exit fullscreen mode

An encoded byte contains 8 bits, so it maps naturally to four cells:

8 bits / 2 bits per cell = 4 cells
Enter fullscreen mode Exit fullscreen mode

There is no base-3 encoding, fractional packing, or unusual bit arithmetic required.

It is simply a quaternary alphabet mapped directly onto binary pairs.


Why RGBW?

I experimented with different possibilities while building QuadQR.

Using more colors sounds attractive because, mathematically, more states can carry more information.

For example, eight states could theoretically represent:

log2(8) = 3 bits
Enter fullscreen mode Exit fullscreen mode

But there is a major problem.

A camera does not see colors the same way your source image does.

A perfect (255, 0, 0) red pixel can become something completely different because of:

  • ambient lighting
  • shadows
  • reflections
  • display brightness
  • camera white balance
  • printer ink
  • paper color
  • JPEG compression
  • sensor noise
  • exposure
  • viewing angle
  • screen color calibration

The more colors you add, the closer those states become in color space and the easier they are to confuse.

So instead of chasing the maximum theoretical density, I wanted a small set of colors with strong separation.

The current QuadQR alphabet is:

Red
Green
Blue
White
Enter fullscreen mode Exit fullscreen mode

And importantly, black is not used as payload data.

Black remains useful for structural information such as finder patterns, timing structures, and alignment references.

That separation makes detection significantly simpler.


QuadQR still looks familiar for a reason

I did not want to completely reinvent the geometry of a matrix code.

There are things traditional QR Code does extremely well.

QuadQR therefore keeps several familiar ideas:

  • square overall matrix
  • square modules
  • three large finder patterns
  • timing structures
  • alignment references
  • quiet zone
  • masking
  • error correction
  • structured data placement

The major experiment happens primarily in the data representation and decoding pipeline.

Instead of interpreting data cells as black or white, QuadQR reconstructs the geometry and then classifies each payload position as:

R
G
B
W
Enter fullscreen mode Exit fullscreen mode

This also means white cannot simply mean "empty."

The decoder first determines which matrix positions are structural and which are data cells.

Only then does it classify the sampled data color.


Color calibration is essential

Simply asking:

if (pixel === RED) ...
Enter fullscreen mode Exit fullscreen mode

would fail almost immediately with a real camera.

Instead, QuadQR includes known calibration references in the symbol.

The scanner uses those references to understand what red, green, blue, white, and structural black actually look like inside the current image.

So the scanner is not expecting perfect source RGB values.

Conceptually:

Generated red
↓
camera + lighting + screen + exposure
↓
observed reddish color
↓
calibration
↓
classified as QuadQR Red
Enter fullscreen mode Exit fullscreen mode

The scanner can then perform nearest-color classification relative to the observed calibration values rather than blindly comparing against ideal RGB constants.

That is one of the most important parts of making a color-based code practical.


Scanning is much more than reading colors

Generating the matrix is the easy part.

Scanning it from a real-world image is where things become interesting.

The current QuadQR scanner performs a pipeline roughly like this:

Camera / Image
      ↓
Finder detection
      ↓
Alignment detection
      ↓
Perspective / homography correction
      ↓
Matrix reconstruction
      ↓
Module sampling
      ↓
Color calibration
      ↓
RGBW classification
      ↓
Unmasking
      ↓
Spectrum ECC / Reed-Solomon recovery
      ↓
CRC verification
      ↓
Payload
Enter fullscreen mode Exit fullscreen mode

That allows QuadQR to handle perspective distortion instead of requiring the code to be perfectly aligned with the camera.

Larger versions also use distributed alignment markers to give the scanner more geometric references.

And the library supports both:

  • uploaded image scanning
  • live camera scanning

from the browser.


Error correction needed a color-aware approach

A higher-density code is not very useful if one shadow makes it unreadable.

So reliability became one of the biggest parts of the project.

QuadQR uses GF(256) Reed-Solomon error correction.

If you have worked with QR Code, storage formats, CDs, networking protocols, or data transmission systems, you may already be familiar with Reed-Solomon.

It allows a decoder to reconstruct damaged symbols using redundant parity information.

QuadQR currently exposes four project-defined ECC profiles:

L
M
Q
H
Enter fullscreen mode Exit fullscreen mode

Higher levels dedicate more space to redundancy and reduce the available payload capacity.

But I wanted to take advantage of something a color scanner knows that a normal hard-decision decoder often throws away:

confidence.


Spectrum ECC

I call the QuadQR-specific recovery system Spectrum ECC.

When the scanner looks at a data module, it does not only decide:

This is Blue.
Enter fullscreen mode Exit fullscreen mode

It also measures how confident that decision is.

Imagine a sampled module where the calibrated color distances look like this:

Blue  = very close
Green = far away
Red   = very far
White = far away
Enter fullscreen mode Exit fullscreen mode

That is probably a reliable Blue decision.

But another module might look like:

Blue  = 42
Green = 45
Enter fullscreen mode Exit fullscreen mode

Now the scanner has much less confidence.

That information is valuable.

QuadQR keeps a confidence score for every RGBW module.

Four data modules form one GF(256) Reed-Solomon byte symbol, so those module confidences can be combined into a confidence score for the byte itself.

Normally Reed-Solomon decoding first attempts conventional recovery.

If that fails, QuadQR can identify the least-confident byte symbols and treat them as erasures.

That distinction matters.

An error says:

Something is wrong somewhere.

An erasure says:

This specific symbol is probably wrong.

Reed-Solomon can use its available redundancy more efficiently when the decoder knows the likely location of the damage.

So instead of throwing away the uncertainty produced by color classification, QuadQR feeds it back into error recovery.

That is Spectrum ECC.


Spreading physical damage across the data

There was another problem.

Imagine a shadow covering one rectangular area of a code.

Or:

  • a scratch
  • glare
  • folded paper
  • ink damage
  • a dirty camera lens
  • a reflection from a display

If neighboring physical cells also contain neighboring logical bytes, one localized defect can destroy a continuous part of the encoded stream.

QuadQR therefore uses a deterministic spectral-spatial interleaver.

After error correction, logically neighboring codeword cells are redistributed across physically distant locations in the matrix.

Conceptually:

Logical:

A A A A B B B B C C C C

Physical:

A D B F C A E B G C ...
Enter fullscreen mode Exit fullscreen mode

The real permutation is deterministic and reversible, but that is the basic idea.

Now a localized shadow or scratch is more likely to damage smaller parts of many Reed-Solomon symbols rather than completely destroying one contiguous region.

And importantly:

The interleaver does not consume additional data cells.

It changes placement, not capacity.


CRC as the final integrity check

Reed-Solomon answers:

Can this damaged information be reconstructed?

But after decoding I still want a strong indication that the reconstructed payload matches what was originally encoded.

QuadQR therefore includes CRC-32 integrity verification.

The simplified pipeline looks like:

Payload
↓
Header + CRC-32
↓
Reed-Solomon ECC
↓
Interleaving
↓
RGBW encoding
Enter fullscreen mode Exit fullscreen mode

During decoding, the process runs in reverse.

The CRC gives the decoder a final acceptance check rather than blindly returning bytes after an uncertain recovery.


But error correction is not encryption

This is an important distinction.

A QR-like symbol can have excellent error correction while offering zero confidentiality.

Anyone with a compatible decoder can read a normal payload.

CRC protects against accidental corruption.

Reed-Solomon protects against physical or transmission errors.

Neither prevents someone from reading the data.

So I added a separate security layer.


Secure Payload v1

QuadQR now supports optional authenticated encryption directly at the payload layer.

The feature is called:

Secure Payload v1
Enter fullscreen mode Exit fullscreen mode

It intentionally sits above the matrix codec.

That means encryption does not require another type of QuadQR geometry.

The same:

  • RGBW encoding
  • scanner
  • Spectrum ECC
  • Reed-Solomon layer
  • perspective correction
  • rendering pipeline

continues to work.

Only the payload being encoded changes.

The secure pipeline becomes:

Plaintext
↓
Secure Payload v1
↓
AES-256-GCM ciphertext
↓
QuadQR framing + CRC
↓
Reed-Solomon
↓
Spectral-spatial interleaving
↓
RGBW matrix
Enter fullscreen mode Exit fullscreen mode

Security is optional.

Normal unencrypted QuadQR remains the default.


AES-256-GCM

Secure Payload v1 uses:

AES-256-GCM
Enter fullscreen mode Exit fullscreen mode

GCM is important because it provides both:

Confidentiality

Someone scanning the symbol without the correct secret cannot read the plaintext.

Authentication

If the encrypted payload has been modified, decryption should fail authentication instead of quietly returning corrupted plaintext.

That means Secure Payload is not simply:

encrypt(data)
Enter fullscreen mode Exit fullscreen mode

It is authenticated encryption.

A wrong secret or altered ciphertext does not produce a successful trusted decode.


Two security modes

QuadQR currently supports two ways to protect a payload.

1. Password mode

For cases where humans need to exchange a protected QuadQR, you can encrypt using a password.

The password is not used directly as the AES key.

Instead QuadQR derives a 256-bit key using:

PBKDF2-HMAC-SHA-256
Enter fullscreen mode Exit fullscreen mode

The current default uses:

600,000 iterations
Enter fullscreen mode Exit fullscreen mode

with a randomly generated:

16-byte salt
Enter fullscreen mode Exit fullscreen mode

So two encryptions of the same content using the same password do not simply reuse an identical derived-key context.

This mode is useful for things like:

  • privately shared information
  • protected notes
  • credentials exchanged through another trusted channel
  • configuration payloads
  • human-readable secure transfers

The password itself is not stored inside the QuadQR.

That would defeat the purpose.


2. Raw 256-bit key mode

Applications often should not rely on human passwords at all.

So QuadQR also supports an exact:

32-byte / 256-bit key
Enter fullscreen mode Exit fullscreen mode

supplied by the application.

This is more appropriate for use cases such as:

  • provisioning
  • enterprise scanners
  • device pairing systems
  • tickets
  • internal applications
  • secure workflows
  • application-to-application transfer

The secret raw key is never embedded inside the QuadQR.

Instead, QuadQR can include a small non-secret key identifier derived from the key.

By default this is an 8-byte fingerprint based on SHA-256.

That lets an application determine something like:

This QR expects key ID ABC123...
Enter fullscreen mode Exit fullscreen mode

without exposing the actual encryption key.

The application can then select the matching secret from its own secure key store.


Why the security envelope is versioned

Cryptographic formats need room to evolve.

I did not want the entire QuadQR matrix format tied forever to one specific KDF or encryption structure.

So Secure Payload has its own versioning.

Today:

Secure Payload v1
Enter fullscreen mode Exit fullscreen mode

can use AES-256-GCM and the currently defined key derivation modes.

A future security envelope could introduce something different without requiring a redesign of:

RGBW
finder patterns
ECC
interleaving
matrix geometry
scanner
Enter fullscreen mode Exit fullscreen mode

Keeping cryptographic framing separate from physical encoding makes the architecture much cleaner.


Secure codes work with both scanners

Security is integrated into the decoding flow rather than being an unrelated utility.

When the image scanner or camera scanner finds an encrypted QuadQR, it recognizes the secure envelope.

But it does not immediately expose plaintext.

Instead, the decoded result indicates that decryption is required.

The user or application provides:

Password
Enter fullscreen mode Exit fullscreen mode

or:

Raw key
Enter fullscreen mode Exit fullscreen mode

and authenticated decryption is then attempted.

For the live camera scanner, once the secure code is successfully detected, the application can stop scanning and move into the decryption flow.

So the camera does not need to know the password before it can locate and decode the physical QuadQR.

It first reconstructs the encrypted payload.

Then the security layer handles decryption.


How much more data can QuadQR store?

This is where I want to be very careful.

At the raw data-cell level, the answer is mathematically straightforward:

Traditional binary data cell = 1 bit
QuadQR RGBW data cell         = 2 bits
Enter fullscreen mode Exit fullscreen mode

So the raw alphabet density is exactly 2x.

But real barcode capacity is not determined only by bits per module.

Both formats reserve space for things such as:

  • positioning
  • timing
  • alignment
  • metadata
  • masking
  • error correction
  • framing

QuadQR additionally needs color calibration.

So I built a benchmark instead of claiming that every QuadQR simply stores exactly twice as much data.

The current representative results using the project's M profile are:

Version Matrix QuadQR Standard QR reference Ratio
1 21×21 24 B 14 B 1.71x
2 25×25 48 B 26 B 1.85x
5 37×37 227 B 84 B 2.70x
10 57×57 630 B 213 B 2.96x
20 97×97 1992 B 666 B 2.99x
30 137×137 4054 B 1370 B 2.96x
40 177×177 6858 B 2331 B 2.94x

For example:

Version 10
Matrix: 57 × 57

QuadQR:             630 bytes
Standard reference: 213 bytes
Enter fullscreen mode Exit fullscreen mode

That is approximately:

2.96x
Enter fullscreen mode Exit fullscreen mode

usable payload capacity in the current same-dimension benchmark.

But there is an extremely important caveat.


A 2.96x capacity ratio does NOT mean QuadQR is 2.96x better

The L, M, Q, and H profiles in QuadQR are project-defined profiles.

They currently do not claim the same standardized physical damage recovery percentages as the corresponding ISO QR Code error correction levels.

So this benchmark means:

Same matrix dimensions and same ECC label.

It does not yet mean:

Same dimensions and independently proven identical real-world damage tolerance.

Those are different experiments.

The ratios approaching 3x also do not mean each QuadQR module somehow stores 3 bits.

It does not.

Every QuadQR data cell still stores exactly:

2 bits
Enter fullscreen mode Exit fullscreen mode

The additional difference comes from how the two formats allocate structural, framing, and ECC overhead.

One of the major future benchmarks I want to build is an equal-reliability comparison.

That would expose QuadQR and traditional QR Codes to comparable:

  • blur
  • noise
  • shadows
  • scratches
  • JPEG artifacts
  • perspective distortion
  • low light
  • glare
  • partial obstruction

and compare capacity only after both formats achieve similar decode success rates.

That will be a much more meaningful comparison.


Version 1 needed special treatment

Small symbols are surprisingly difficult.

At a 21×21 matrix, fixed structural metadata occupies a much larger percentage of the available cells.

The original QuadQR framing was simply too expensive for a useful Version 1 symbol at the project's M profile.

So Version 1 now has a dedicated compact profile.

At M:

21×21 QuadQR
24 bytes payload
Enter fullscreen mode Exit fullscreen mode

while the standard QR byte-mode reference at the same dimensions is:

14 bytes
Enter fullscreen mode Exit fullscreen mode

Versions 2 and above use the normal QuadQR framing structure.

It was a good reminder that theoretical density is only the beginning.

Format overhead matters enormously at small sizes.


Safe visual styling without changing the format

Once the scanner was working, I also wanted QuadQR to look a little less mechanical.

But styling machine-readable codes can be dangerous.

Effects like:

  • heavy shadows
  • gradients
  • transparency
  • random colors
  • distorted finder patterns

can quickly destroy scan reliability.

So QuadQR keeps visual rendering completely separate from the encoded matrix.

It currently provides four rendering styles:

classic

Solid square modules.

depth

Subtle deterministic fading and edge treatment creates more visual depth while preserving encoded colors.

soft

Rounded payload modules create a softer appearance.

inset

Adds a recessed edge treatment while preserving the exact encoded RGBW color around the center of the module.

Usage looks like:

renderToCanvas(code, canvas, {
  moduleSize: 12,
  quietZone: 4,
  style: "inset"
});
Enter fullscreen mode Exit fullscreen mode

The critical structural elements remain solid and square:

  • finder patterns
  • timing structures
  • alignment markers
  • calibration cells

The scanner primarily samples the center area of data modules, so styles are designed around preserving that encoded center.

The styles are also deterministic.

Generating the same QuadQR with the same style produces the same visual result instead of randomly changing modules every time.


Using QuadQR from JavaScript

QuadQR is now available on npm as:

npm install quadqr-js
Enter fullscreen mode Exit fullscreen mode

Basic usage:

import {
  encodeText,
  decodeMatrix
} from "quadqr-js";

const code = encodeText("Hello from QuadQR", {
  ecc: "M"
});

const result = decodeMatrix(code.matrix);

console.log(result.text);
Enter fullscreen mode Exit fullscreen mode

The library includes APIs for:

  • text encoding
  • binary encoding
  • matrix decoding
  • canvas rendering
  • ImageData rendering
  • image scanning
  • video-frame scanning
  • live camera scanning
  • version/capacity inspection
  • secure payload handling
  • benchmarking

It can be used in browser and Node.js environments.

The package also includes TypeScript declarations for consumers even though the project itself is JavaScript-focused.


There is a CLI too

You can generate a QuadQR directly from the terminal:

npx quadqr-js encode "Hello QuadQR" -o hello.png
Enter fullscreen mode Exit fullscreen mode

And decode it:

npx quadqr-js decode hello.png
Enter fullscreen mode Exit fullscreen mode

Secure payloads work from the CLI as well:

npx quadqr-js encode "Private data" \
  --password "my-password" \
  -o secure.png
Enter fullscreen mode Exit fullscreen mode

Then:

npx quadqr-js decode secure.png \
  --password "my-password"
Enter fullscreen mode Exit fullscreen mode

Raw 256-bit key mode is supported too.

This makes QuadQR usable outside the demo application and also makes automated testing much easier.


Browser, Node, CDN, and WASM packaging

I wanted the project to be more than a demo page.

The npm package currently exposes builds for:

ES modules
CommonJS
Browser
Node.js
CDN usage
Benchmark utilities
Enter fullscreen mode Exit fullscreen mode

So applications do not have to copy pieces from the repository manually.

The package is currently published as:

quadqr-js
Enter fullscreen mode Exit fullscreen mode

Testing

A format like this is very easy to make work for one perfectly generated image.

That is not enough.

The current test suite covers areas including:

  • RGBW mapping
  • binary round trips
  • Unicode text
  • version selection
  • capacity boundaries
  • all ECC profiles
  • Reed-Solomon corruption recovery
  • Spectrum ECC behavior
  • image scanning
  • rotation
  • perspective distortion
  • color casts
  • secure payload encryption/decryption
  • package distribution
  • benchmark reference data
  • codec performance

There is still significantly more real-device testing to do, especially across different cameras, printers, papers, lighting conditions, and display technologies.


QuadQR is not a replacement for QR Code

This is probably the most important part of this article.

QuadQR is experimental.

It is not an ISO QR Code.

A normal phone QR scanner cannot decode it.

Traditional QR Code has enormous advantages:

  • decades of deployment
  • ISO standardization
  • billions of compatible devices
  • highly optimized decoders
  • proven print behavior
  • mature error correction
  • enormous real-world datasets
  • extensive interoperability

I would not currently recommend replacing a production-critical QR workflow with QuadQR.

That is not what this project is claiming.

The question I am exploring is different:

If we were designing a QR-inspired matrix code around modern color-capable cameras and displays today, what could we do differently?

QuadQR is my attempt to explore that question through actual code rather than just theory.


There are still hard problems

Color gives us more information, but it also introduces an entirely new class of problems.

Some of the things I still want to investigate deeply are:

  • different printer and ink combinations
  • colored or reflective paper
  • OLED vs LCD displays
  • screen brightness
  • camera white balance
  • extreme shadows
  • low-light conditions
  • motion blur
  • display moiré
  • glare
  • color-blind camera processing
  • very small module sizes
  • extreme viewing angles
  • physical scratches
  • partially hidden symbols
  • RGBW confusion matrices
  • large-symbol alignment
  • print-quality grading
  • cross-device scanning performance

There is a big difference between:

"It works on my phone."
Enter fullscreen mode Exit fullscreen mode

and:

"We understand the statistical reliability of this format."
Enter fullscreen mode Exit fullscreen mode

The second one is much harder.

And much more interesting.


What I want to build next

There are several directions I want to continue exploring.

The biggest one is an automated torture-test system.

I want to generate QuadQR symbols and programmatically apply:

blur
noise
perspective distortion
JPEG compression
shadows
brightness changes
color shifts
occlusion
glare simulation
scaling
rotation
Enter fullscreen mode Exit fullscreen mode

Then measure exactly where decoding succeeds and fails.

After that, physical testing matters even more.

Generate.

Print.

Damage.

Photograph.

Scan.

Repeat across devices.

That data can then guide improvements to:

  • calibration
  • Spectrum ECC
  • erasure selection
  • alignment strategies
  • interleaving
  • color classification
  • version selection

instead of relying on guesses.


Why I made it open source

A new matrix-code format is much more interesting when other people can inspect it, break it, test it, and challenge the assumptions behind it.

The project includes documentation for the format itself, not just the library API.

So if someone wants to:

  • inspect the encoding
  • build another decoder
  • test the ECC
  • improve the scanner
  • benchmark another camera
  • investigate color classification
  • find a flaw in the format
  • experiment with another implementation

they can.

QuadQR is licensed under AGPL-3.0.

Contributions, experiments, test images, benchmarks, scanner improvements, and criticism are all welcome.


AI helped me build parts of it

One other thing I want to be transparent about.

I designed the idea, researched the architecture, made the format decisions, tested the behavior, and iterated on the project.

I also used OpenAI Codex as a pair-programming tool during development.

It was particularly useful while working through some of the more complex implementation areas, including:

  • codec work
  • Reed-Solomon logic
  • scanner/image-processing code
  • tests
  • optimizations
  • repetitive implementation tasks

I think projects like this are also a good example of where AI-assisted development becomes interesting.

The hard part is not asking an AI to "make a QR code."

The hard part is repeatedly asking:

Does this design actually make sense?

What fails when lighting changes?

Are these benchmarks fair?

What happens when the color decision is uncertain?

Can the ECC use that uncertainty?

Does adding another color really help?

Does this visual effect reduce scanning reliability?

Are we measuring capacity or actual robustness?
Enter fullscreen mode Exit fullscreen mode

AI can accelerate implementation enormously.

But engineering decisions, experiments, skepticism, and validation still matter.


Try QuadQR yourself

You do not need to install anything to experiment with it.

Live Demo

https://akanshsirohi.github.io/QuadQR/demo/

You can:

  • generate QuadQR symbols
  • choose ECC profiles
  • try different rendering styles
  • scan image files
  • scan using your camera
  • create secure encrypted symbols
  • test password-protected payloads
  • view capacity comparisons
  • explore benchmarks

Documentation

https://akanshsirohi.github.io/QuadQR/docs-site/

GitHub

https://github.com/akanshSirohi/QuadQR

npm

npm install quadqr-js
Enter fullscreen mode Exit fullscreen mode

https://www.npmjs.com/package/quadqr-js


Final thoughts

QuadQR started from one small question:

Why should every visible data cell still be binary?

That question turned into a much larger experiment involving:

color theory
matrix encoding
computer vision
perspective geometry
Reed-Solomon coding
erasure decoding
interleaving
cryptography
camera processing
benchmarking
browser APIs
Enter fullscreen mode Exit fullscreen mode

And there is still a lot to learn.

Four colors give each QuadQR data cell exactly two bits of raw information.

But making those four colors reliably recoverable from a real camera is where the real engineering begins.

Adding Spectrum ECC made the scanner capable of using its uncertainty instead of ignoring it.

Spectral-spatial interleaving made localized physical damage less concentrated.

Secure Payload v1 added optional AES-256-GCM authenticated encryption without changing the physical code format.

And publishing the entire thing as an open-source JavaScript library means other developers can now experiment with it too.

I do not know whether color matrix codes will ever become as universally practical as traditional QR Code.

But I think the question is worth exploring.

And that is exactly what QuadQR is for.

If you work with computer vision, error-correcting codes, cryptography, barcode systems, or image processing, I would genuinely love to hear what you would test, break, or improve first.

GitHub: https://github.com/akanshSirohi/QuadQR

Live Demo: https://akanshsirohi.github.io/QuadQR/demo/

npm: quadqr-js

Top comments (1)

Collapse
 
alexshev profile image
Alex Shev

A color-based code gets interesting when scanning reliability is treated as a first-class problem. More data is useful only if lighting, camera quality, printing variance, and error correction are handled honestly.