Decode QOI
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/qoiforwuffs/pngor any other image format thatwuffssupports? - 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
pixelstruct? - If I uncomment
headindecoder, why doesn't it compile? I thought it might need topkgname.headerfrom whatever I compile the package with inwuffs-cbut that doesn't seem to be the case. But it saysheaderis 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/qoiforwuffs/pngor any other image format thatwuffssupports?
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 dda01f1a 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
pixelstruct?
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
headindecoder, why doesn't it compile? I thought it might need topkgname.headerfrom whatever I compile the package with inwuffs-cbut that doesn't seem to be the case. But it saysheaderis 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-cexample 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).
If you're still interested in doing this, there's a bunch of commits hanging off #67 that shows what was needed to add a new std/tga package for decoding the relatively simple TARGA image file format.