Skip to content

MrPresidentWhite/Quantumbits

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Quantumbits

Store and restore arbitrary files inside 4K PNG images (3840×2160) – the “Quantumbits” format with magic header QBNT.

Idea and background

The original idea for Quantumbits came from classic CRT screen noise and a fascination with hiding data in images. The very first proof‑of‑concept was to read a file bit by bit and map each bit directly to a pixel: black = 0, white = 1, written row by row, pixel by pixel into an image.

Why 4K images? The goal was to pack as much data as possible into a single image. A native 4K resolution is a good fit because it provides a lot of pixels and thus a high raw capacity per frame.

The next question was: “How can I squeeze even more data into the same space?” From this simple black/white representation came the idea of layering: instead of just two states, use grayscale, which immediately made the increased density visible in a single 4K image.

My ADHD brain then pushed this further and connected it to quantum physics: quantum particles in superposition can be in many states at once. Translated to images, this led to using RGB colors instead of grayscale – each pixel effectively carries multiple “states” at the same time. Data density per image increased again in a visibly dramatic way.

From this analogy between bits and quantum states the name “Quantumbits” was born. The very first version of the project was just a proof‑of‑concept to explore and visualize this idea.

General notes

This version of Quantumbits was “vibecoded” together with Cursor – it’s experimental rather than carefully designed. The project is not intended for production use. It exists mainly as a playground for ideas, born out of boredom and curiosity, not out of a concrete use case.

There are parts of the code where even I don’t fully remember what happens in detail. You should therefore not use this project as the basis for production systems, safety‑critical applications, or important backups.

Quantumbits does not aim to solve a real‑world problem – it’s primarily an experimental project that shows how to store data in high‑resolution images and how different layering ideas (bits → grayscale → RGB) can visibly increase data density.

Project structure

quantumbits/
├── main.py              # Entry point: encode, decode, info, debug (CLI)
├── requirements.txt
├── README.md
├── LICENSE
├── frames_output/       # Default folder for frames (created if needed)
└── quantumbits/         # Package with all core logic
    ├── __init__.py
    ├── common.py        # Constants, header, safe_output_filename, limits
    ├── encoder.py       # encode_file (2D/3D, optional gzip, parity/recovery)
    ├── decoder.py       # decode_files, list_sequences (recovery using zfec)
    └── debug.py         # get_pixel_bytes, hex dump / header debug

All commands are executed via python main.py <command>.
Optionally you can call python -m quantumbits.encoder … or python -m quantumbits.decoder … directly if you only want the low‑level modules.

Installation

pip install -r requirements.txt

Dependencies

  • Python 3.9+
  • numpy
  • Pillow
  • tqdm
  • zfec (erasure coding for frame recovery)

How it works

Core idea

  • The encoder reads an input file in binary mode (rb), optionally gzip‑compresses it.
  • The bytes are written into 4K PNG frames:
    • 2D (grayscale): 1 byte per pixel.
    • 3D (RGB): 3 bytes per pixel (higher capacity).
  • The first frame contains a QBNT header at the end, with:
    • number of data frames (total_frames)
    • optional number of parity frames (parity_frames)
    • compressed/original size
    • compression flag (gzip yes/no)
    • filename, extension, MIME type.

The decoder reads the header, reconstructs the byte stream from the frames (including decompression), and writes the original file back to disk.

Parity and recovery (lost frames)

  • If there are 2 or more data frames, the encoder automatically creates 2 parity frames using zfec:
    • N = total_frames (data frames)
    • K = 2 (parity frames)
    • In total N + K frames are written.
  • If there is only one frame (total_frames == 1), no parity frames are created – losing that one frame would make recovery impossible anyway.

On decode:

  • The decoder scans all qb_frame_XXXX.png files and groups them into sequences.
  • Each sequence has:
    • total_frames (data frames)
    • parity_frames (parity frames)
    • segment length = total_frames + parity_frames.
  • If parity frames are present (parity_frames > 0):
    • The decoder needs at least N = total_frames frames in total (data or parity).
    • If at most K = parity_frames frames are missing, they can be reconstructed with zfec.
    • On successful recovery you’ll see output like:
      X frame(s) were missing and could be recovered.
    • If fewer than N frames are available:
      Threshold for successful recovery of missing/corrupt frames exceeded – recovery and decoding aborted.
  • Without parity (old files or single‑frame encodes), all data frames must be present.

Important: The system can recover at most K lost frames, independent of the total number of frames – it’s a fixed number, not a percentage.

CLI usage (recommended)

The default folder for frames is always frames_output, so you usually don’t need to pass it explicitly.

# Encode: file -> frames_output (default)
python main.py encode my_file.pdf
python main.py encode music.mp3 --compress --mode 3d

# Different output folder
python main.py encode document.zip -o other_frames

# Append new frames instead of overwriting
# (multiple files one after another into the same folder)
python main.py encode new_file.pdf --no-overwrite

# Decode: frames_output (default) -> file (name from header)
python main.py decode

# Show metadata only (no decoding)
python main.py info

# Debug: first bytes as hex, optional header dump
python main.py debug
python main.py debug --header
python main.py debug -n 50 -i frames_output

# Decode from another folder or with explicit output file / directory
python main.py decode -i other_frames
python main.py decode -o restored.pdf
python main.py decode -o ./output_dir
Command Default behaviour (when omitted)
encode Output folder: frames_output
decode Input folder: frames_output, output: current directory, filename from header
info Prints metadata (filename, size, frames, compression, parity) from frames_output
debug Hex‑dump of first bytes (+ optional --header) from frames_output

Multiple files in one folder:
If you encode multiple files into the same folder one after another (e.g. frames 0–2 = file A, frames 3–4 = file B), the decoder detects this automatically. Each file starts with a frame that contains a QBNT header. On decode, main.py decode will prompt you when multiple sequences are found and ask whether you want to decode specific indices or all of them.

Example output when multiple files are found:

Found QBNT files:
  1) photo.zip      (123456 bytes, 3 frame(s))
  2) music.mp3      (7890123 bytes, 42 frame(s))
  3) installer.exe  (50123456 bytes, 96 frame(s))
  4) Decode all

Selection (number(s) separated by spaces, or 'all'):

Encoder/decoder directly (without main.py):
python -m quantumbits.encoder <input_file> <output_folder> [--compress] [--mode 2d|3d]
python -m quantumbits.decoder <folder> [target_file] [-o output_folder] [--info]

Formats

  • 2D (grayscale): Single channel, header in the last 1024 pixels of the first frame. The decoder automatically detects grayscale PNGs.
  • 3D (RGB): Three channels, header in the last 1024 pixels of the red channel in the first frame. Higher capacity per frame.

Encoder and decoder support both modes; the decoder auto‑detects 2D vs. 3D from the first frame.

Debug

The debug mode is mainly for exploration and sanity checks.

  • python main.py debug
    Reads the first frame from the given folder (default: frames_output), detects the mode (2D/3D) and prints the first bytes as a hex dump.
  • python main.py debug --header
    Additionally parses and prints the QBNT header of the first frame.
  • python main.py debug -n 50 -i other_folder
    Reads the first 50 bytes from other_folder/qb_frame_0000.png.

Typical output without --header:

Mode: 3D (RGB)
First 100 bytes (hex):
51 42 4e 54 00 02 00 00 00 00 00 00 00 00 3a 98 ...

Typical output with --header:

Mode: 2D (Grayscale)
--- Header (QBNT) ---
  total_frames: 96
  parity_frames: 2
  compressed_size: 50123456
  original_size: 73400320
  compress_flag: 1
  filename: installer.exe
  extension: .exe
  mime_type: application/vnd.microsoft.portable-executable

First 100 bytes (hex):
51 42 4e 54 00 02 00 00 00 00 00 00 00 03 00 00 ...

This makes it easy to check:

  • whether the header was written correctly (frames/parity/sizes/name),
  • whether the detected mode (2D/3D) matches your expectations,
  • and whether the first bytes look roughly as expected (e.g. for certain file types).

License

This project is licensed under the MIT License (see LICENSE).

Important notes:

  • The software is provided “as is”, without warranty of any kind and without liability for any damage or data loss.
  • You may freely use, modify, fork, and integrate the code into other projects as long as the copyright and license notice is preserved.
  • Quantumbits uses the library zfec, which itself is licensed under GPL-2+ and the Transitive Grace Period Public Licence (TGPPL).
    If you redistribute a combined work, you must additionally comply with zfec’s license terms (see the zfec project on PyPI/GitHub).

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages