13 September 2026
Converting Quite OK Image (QOI) to PNG: Fast Lossless Compression Architecture
In late 2021, game developer Dominic Szablewski released a technical manifesto that captivated the systems engineering world: The Quite OK Image Format.
Frustrated by the extreme complexity of PNG—which relies on DEFLATE compression, LZ77 sliding dictionaries, Huffman trees, and five distinct per-scanline adaptive filters—Dominic designed QOI (.qoi). Its goal was radical simplicity: achieve compression ratios comparable to PNG while encoding and decoding 20x to 50x faster, using a specification that fits on a single sheet of paper and an implementation written in less than 400 lines of clean C.
Game engines, embedded systems, and graphics developers quickly adopted QOI for real-time texture streaming. However, standard web browsers, desktop operating systems, and image editors still lack native QOI display support.
This engineering guide examines the forensic byte architecture of QOI streams, walks through its 6-opcode state machine and 64-entry color indexing cache, and explains how convrtr's QOI to PNG engine converts .qoi images into universal 32-bit RGBA PNGs directly in your browser.
The 14-Byte QOI Header Specification
Every valid QOI file begins with a fixed 14-byte big-endian header:
| Offset (Bytes) | Field Name | Data Type | Forensic Description |
| :--- | :--- | :--- | :--- |
| 0x00 - 0x03 | Magic Signature | 4 ASCII chars | Constant "qoif" (0x71 0x6F 0x69 0x66) |
| 0x04 - 0x07 | Width | 32-bit uint (BE) | Image width in pixels |
| 0x08 - 0x0B | Height | 32-bit uint (BE) | Image height in pixels |
| 0x0C | Channels | 8-bit uint | 3 = 24-bit RGB, 4 = 32-bit RGBA |
| 0x0D | Color Space | 8-bit uint | 0 = sRGB with linear alpha, 1 = all channels linear |
The file terminates with an 8-byte end-of-stream sentinel marker:
00 00 00 00 00 00 00 01
The 64-Color Indexing Cache and Running State
QOI achieves its phenomenal decoding speed by processing pixels sequentially using a minimal internal state:
- A
currentPixelregister initialized to{ r: 0, g: 0, b: 0, a: 255 }(opaque black). - A 64-entry running color array
colorIndex[64], initialized to all zeros.
Whenever a pixel is encountered or modified, its color is recorded into colorIndex at an index derived from a custom integer hash function:
indexPosition = (r * 3 + g * 5 + b * 7 + a * 11) % 64
Because the hash uses small prime multipliers and bitwise modulo 64 (& 63), computing the array index takes less than a nanosecond on modern CPUs.
The Six Byte-Aligned Opcodes
QOI encodes image data as a continuous stream of byte-aligned tokens. The decoder determines the operation by inspecting the first byte's high 2 bits (or the entire byte for full RGB/RGBA updates):
1. QOI_OP_INDEX (00xxxxxx)
- Tag:
00(2 bits) - Data:
xxxxxx(6 bits, value0to63) - Operation: The next pixel is an exact duplicate of the color stored at
colorIndex[index]. This achieves 1-byte encoding for previously seen palette colors.
2. QOI_OP_DIFF (01xxxxxx)
- Tag:
01(2 bits) - Data: 2-bit
dr, 2-bitdg, 2-bitdb(each biased by2, representing deltas from-2to+1) - Operation: Small pixel-to-pixel color changes:
r = currentPixel.r + (dr - 2)g = currentPixel.g + (dg - 2)b = currentPixel.b + (db - 2)- Alpha remains unchanged.
3. QOI_OP_LUMA (10xxxxxx)
- Tag:
10(2 bits) - Data: 6-bit
dg(biased by32, delta-32to+31), followed by a second byte with two 4-bit nibbles:dr_dganddb_dg(each biased by8, delta-8to+7). - Operation: Handles larger brightness transitions where green (luminance) changes moderately and red/blue track relatively close to green. Takes 2 bytes total.
4. QOI_OP_RUN (11xxxxxx)
- Tag:
11(2 bits) - Data:
xxxxxx(6 bits, value0to61, biased by-1, representing run lengths from1to62) - Operation: Run-length encoding. Repeats
currentPixelconsecutively for up to 62 pixels in a single byte.
5. QOI_OP_RGB (11111110 / 0xFE)
- Tag:
0xFE(8 bits) - Data: 3 bytes containing raw
red,green,bluevalues. - Operation: Full 24-bit color update when deltas exceed LUMA bounds. Alpha remains unchanged. Takes 4 bytes total.
6. QOI_OP_RGBA (11111111 / 0xFF)
- Tag:
0xFF(8 bits) - Data: 4 bytes containing raw
red,green,blue,alphavalues. - Operation: Complete 32-bit color and alpha update. Takes 5 bytes total.
In-Browser Decompression and PNG Encoding
Because QOI avoids expensive LZ77 table allocations and bit-level entropy decoders, convrtr's browser engine decompresses QOI byte streams into raw RGBA pixel arrays in just 1 to 5 milliseconds for multi-megapixel textures.
The pipeline executes entirely in memory:
- Validates the 14-byte
qoifheader and extracts dimensions. - Allocates a typed
Uint8ClampedArrayof sizewidth * height * 4. - Iterates through the opcode stream, updating
colorIndexand writing raw 32-bit RGBA bytes. - Encodes the resulting RGBA raster buffer into a standardized W3C PNG with full 8-bit alpha transparency.
Zero-Server Processing
Textures, game sprites, UI assets, and photographs converted on convrtr never touch a remote server. Everything executes locally within your browser tab using pure TypeScript, ensuring instantaneous performance and absolute privacy.
Related reading
Converting Radiance HDR (RGBE) to PNG: Floating-Point Tone Mapping Architecture
Explore Greg Ward's Radiance 32-bit RGBE (.hdr) architecture. Learn how shared exponents, adaptive RLE scanlines, Reinhard tone reproduction, and sRGB gamma curves decode in browser memory.
Converting Better Portable Graphics (BPG) to PNG: HEVC-Derived Image Decoding
Discover Fabrice Bellard's Better Portable Graphics (.bpg) format. Learn how HEVC intra-frame compression, LEB128 variable headers, and YCbCr color spaces convert to standard PNG.
Converting Blizzard BLP Textures to PNG: Warcraft III & WoW Asset Decoding
Decode Blizzard Entertainment's BLP1 and BLP2 texture formats from Warcraft III and World of Warcraft into transparent 32-bit RGBA PNG images 100% in your browser.
Converting Truevision VDA to PNG: Historical TARGA Video Graphics Decoding
Explore Truevision's original 1984 VDA (Video Display Adapter), ICB, and VST image formats. Learn how vintage TARGA rasters convert to transparent 32-bit RGBA PNG.
Converting Quake II WAL Textures to PNG: id Tech 2 Mipmapped Raster Decoding
Explore id Software's Quake II WAL texture format. Learn how 100-byte headers, 4-level precomputed mipmaps, and 256-color colormaps convert into 32-bit RGBA PNG graphics.
Converting MNG Animated Graphics to PNG: Unpacking Multi-Image PNG Containers
Explore Multiple-image Network Graphics (MNG), PNG's ambitious animated sibling. Learn how MHDR, IHDR, and IDAT chunk streams extract into standalone 32-bit RGBA PNGs.
Converting Kodak Photo CD PCD to PNG: Rescuing 1990s Film Scans
Learn how Kodak Photo CD (.pcd) Image Pac archives store multi-resolution 35mm film scans. Discover PhotoYCC color space decoding to 32-bit RGBA PNG.
Converting Camera RAW and DNG to PNG: Extracting Lossless Sensor Previews
Discover how digital camera RAW and Adobe DNG files encapsulate sensor data and high-resolution previews. Learn how to convert RAW to PNG directly in the browser.