Decode QOI
nigeltao opened this issue · comments
There should be a std/qoi
package.
I am working on this, but there are quite a few concepts in Wuffs which are difficult for me to understand. I would appreciate if you could look at what I'm doing and see if I'm making any mistakes or poor design choices.
You can just look at qoi.wuffs, the other files are forked from phoboslab/qoi but I imagine only the qoi.wuffs
would need to be added to std/qoi
.
Some questions I have:
- where do I learn what methods image_decoder requires? I suppose I should be only implementing those functions as public-facing, so you can drop-in replace
wuffs/qoi
forwuffs/png
or any other image format thatwuffs
supports? - should there be a way to get QOI's own header information struct, or should I remove that and just use whatever standard an image_decoder provides?
- Is there a standard
pixel
struct? - If I uncomment
head
indecoder
, why doesn't it compile? I thought it might need topkgname.header
from whatever I compile the package with inwuffs-c
but that doesn't seem to be the case. But it saysheader
is a 0-value type, even though I define it above.
Also, once I finish, I can write some documentation about the process of writing the parser. I think this might be a good middle ground between the current packages, which I have a hard time reading or understanding because their file formats aren't known to me, and the hello-wuffs-c
example which is very simple.
I would appreciate if you could look at what I'm doing
I will be offline for the next week or so. Please keep asking questions. I'll reply when I get back.
- where do I learn what methods image_decoder requires? I suppose I should be only implementing those functions as public-facing, so you can drop-in replace
wuffs/qoi
forwuffs/png
or any other image format thatwuffs
supports?
The canonical list is at https://github.com/google/wuffs/blob/dda01f1a/lang/builtin/builtin.go#L882-L895
It might be easiest to copy/paste the std/nie/decode_nie.wuffs
or std/wbmp/decode_wbmp.wuffs
to get an image_decoder
up and running. (As you guessed, you should only need the pub
functions.) For more sample code, the std/bmp
decoder is probably the next one in std
to look at, for ease of understanding. std/gif
and std/png
are more complicated, both of them having to deal with animation, metadata and fancier compression.
For manual testing, you might want to patch the example/imageviewer/imageviewer.cc
program. If so, you'll have to update its MyDecodeImageCallbacks
class to override SelectDecoder
to slot in your QOI decoder. The internal/cgen/auxiliary/image.cc
file has the default implementation, DecodeImageCallbacks::SelectDecoder
. Sync your wuffs tools past commit dda01f1 to pick up the WUFFS_BASE__FOURCC__QOI
definition.
There's also the https://github.com/google/wuffs/blob/dda01f1a/doc/std/image-decoders.md page but it needs updating (#60).
- should there be a way to get QOI's own header information struct, or should I remove that and just use whatever standard an image_decoder provides?
Long term, you should be able to define your own header information struct but that would require some compiler work. (It's not complicated compiler work, but there just hasn't been a high-priority need for it and there's always many other things to do.) For now, do like all the other std
image decoders and keep those fields in the decoder struct.
But, yeah, if you want your QOI decoder to have the same API as all of the other Wuffs std
image decoders, then you should implement a decode_image_config
method that fills in a base.image_config
. Having a uniform API means that the example/imageviewer
program can decode a variety of image formats without having code specifically for a GIF header struct, a PNG header struct, etc.
- Is there a standard
pixel
struct?
There's not really a struct for a pixel, other than wuffs_base__color_u32_argb_premul
, but the std
image decoders don't use that. They use base.pixel_buffer
, a struct for a 2-D array of pixels, instead.
Read https://github.com/google/wuffs/blob/dda01f1a/doc/note/pixel-formats.md and https://github.com/google/wuffs/blob/dda01f1a/internal/cgen/base/image-public.h, and the previously mentioned std/nie
and std/wbmp
decoders.
- If I uncomment
head
indecoder
, why doesn't it compile? I thought it might need topkgname.header
from whatever I compile the package with inwuffs-c
but that doesn't seem to be the case. But it saysheader
is a 0-value type, even though I define it above.
As above, it's a bug in the compiler, but it's been low priority because we haven't needed support yet. Just put the fields in the decoder struct and implement a decode_image_config
method that fills in a base.image_config
.
Also, once I finish, I can write some documentation about the process of writing the parser. I think this might be a good middle ground between the current packages, which I have a hard time reading or understanding because their file formats aren't known to me, and the
hello-wuffs-c
example which is very simple.
Sounds good.
As for unknown file formats, the std/nie
file format is even simpler than QOI: https://github.com/google/wuffs/blob/dda01f1a/doc/spec/nie-spec.md
WBMP is a "1 bit per pixel, black or white, rows are padded to byte boundaries" image format. I'm not sure if there's good documentation on the file format anywhere, but it's also pretty simple (and arguably simpler than QOI).