Awesome
QOI - The “Quite OK Image Format” for fast, lossless image compression.
More info at https://qoiformat.org.
QOI targeted to FPGAs
Verilog
Fully featured encoder and decoder, all QOI_OPs supported according to the spec.
Testing
Verilator is able to emulate the fpga logic on a computer and is embeddable in C, enough for it to be a drop in qoi_{encode,decode} replacement for some of the reference implementation.
Run make VERILATED=1 test_encode
, it will convert an image to qoi and then use the
system converter to convert back (both ours and the reference .qoi). The
md5sums of the resulting png files should match (it should mean all pixels
survived being encoded), the md5sums of the .qoi files should also match if
it's a full featured encoder.
Run make VERILATED=1 test_decode
for a similar test exercising the decoding.
LiteX
Coming soon!
Connections
Encoder
Input
The rgba
pixel data with a clk
.
If image is in 3 channel mode, an alpha of 0xff
must still be provided as
encoder is always in 4 channel mode. Though if the alpha does not change from
0xff
as it's encoding, it will produce only 3 channel QOI_OPs.
On the next clock after the last pixel please send a high finish
so the
encoder can immediatelly commit any QOI_OP_RUN that are in progress.
Output
The encoder will usually output a whole QOI chunk
(1-5 bytes), though delayed
by one clock cycle (to account for any QOI_OP_RUN). If Alpha is not needed
the max chunk size is 4 bytes, which might fit in a single memory transaction.
chunk_len
specifies how many bytes the current chunk
contains, could be
0 bytes in case of QOI_OP_RUN for many pixels, could be as high as 5 when
we have a fresh RGBA pixel.
This will eventually need to connect to some kind of bus like AXI or Avalon. Not really sure how to deal with the variable length output from the encoder yet.
Decoder
Input
A way to peek at the next chunk
(5 bytes if RGBA, or 4 for just RGB).
For every clock the decoder will output how many bytes it "ate" via
chunk_len_consumed
,
This value can be used to advance the peek pointer (or sometimes even stay in the same spot for a while in case of QOI_OP_RUN).
Output
One RGBA pixel per clock.