I should maybe set the properties to be private and accessible strictly
through accessor methods. That way nobody can accidentally write into
the values. Oh well, that's a thing for later.
The other magic constructors were no longer valid because of the added
struct members. The calls to `new()` have been reattached to
`new_with_no_metadata()`. Tests pass, still!
The old `Decoder::new()` method would not pull the image header out of
the iterator. This was fine for the design then, but I've just decided
that I want to collect this info and store it in the Decoder struct.
I've moved the old method down into the test module so that I can still
use it to test the decoder parts alone. Same philosophy as the
`new_with_previous_pixel()` and `new_with_backbuffer()` methods.
The qoi_header is specified as knowing the width, height, channels, and
colorspace. I figure this information would be captured by the decoder,
if anywhere. I've added more properties to the struct, and created a
new, fallible construction function.
I'm saving this to the repo so I can possibly come back and fix it up
correctly.
A major API change is going to be attempted. The iterator-based stream
processing has proven to be fiddly and annoying, so I'm going to switch
to a processing the complete image.
Wow, what a mess. Why was I making one giant file to contain everything?
I'm splitting it out into several files and taking another crack at
completing the decoder.
The previous pixel needs to be captured before the iterator is advanced.
Otherwise it's just getting the same pixel back out, and all that's
tested is the assignment operator.
The expected alpha value for the first OP_RGBA was set wrong.
The OP_LUMA was missing whole bits. SMH my head.
After changing the prev-pixel check order, the final OP_RGBA *is*
required. Include that in the expected output.
The backbuffer indices were all kinds of wrong, and there was even a
state corruption bug.
Hash values were simply done wrong. I've added some value delta notes
to the compressed byte array, and then tracked all the state changes
next to the expected indices array. The last RGBA value also needed to
be included. Off by one, oops.
The state corruption exists as a side effect of malformed OP_INDEXs.
This is actually a bigger issue, and I'll need to add a new test for it.
Basically: A pixel produced by an OP_INDEX will hash to that index.
That's the definition of an OP_INDEX. What happens if an OP_INDEX picks
up a pixel that hashes to a different index? Because an OP_INDEX is
reading from the backbuffer array without modification, it doesn't need
to write. An otherwise valid encoder can then skip the write step. This
causes a missing buffer update when the pixel should land on another
index. The decoder is now in a corrupted state.
The wrapping wasn't working properly, clearly, but I forgot about the
previous pixel entirely.
I'll add some more explicit tests for the previous pixel behavior. I
think it's still broken for RGB and RGBA, because I'm dumb.
The op codes are now being recognized properly. I just gotta decode them
the right way. I fixed an error where I was bitwise-or -ing the values
instead of bitwise-and -ing them. Small brain up in here.
The run length can simply be extracted and stored as part of the
iterator state. For each iteration, check if the length is > 0, and emit
more pixels until it isn't. Then continue the normal decode process.
I was going to try to match over the op codes, but that isn't possible.
Most of the decoders are done, too, but I'm quite sure that the delta
operations will encounter a wrap around and then panic. The OP_RUN is a
problem, as well. I think I'm going to cheat this problem by holding a
counter. This way I can see if I'm in a run, and then emit another pixel
copy until counter == 0.
I want to iterate over the input elements, and I couldn't figure out how
to get the slice lifetime to be specified properly. I've swapped the
slice for any Iterator that emits u8's.
These tests can be used to verify the fundamentals of the decoder: That
individual instructions are parsed correctly and converted back into
the correct pixel values.