qoi2-bikeshed
qoi2-bikeshed copied to clipboard
There are a lot of unreachable combinations of bits and ways to copy the previous color to the current pixel
I believe QOI_RLE_8 is the best way to copy the previous pixel, but there are many other ways to do that.
QOI_INDEX always has the previous color, although we don't need it. Maybe we can put the colors in the table with a one chunk delay to fix this?
QOI_DIFF_8, QOI_DIFF_16 and QOI_DIFF_24 all have 000 diffs bit combinations. Maybe if 2 channels are equal to 0, we can expand the range of another one channel? For example, if channels g and b are 0, then we can change the range of channel r from [-8, 7] to [-8, 1]U[1, 8]. One of the problems is that we can't choose which channel we want to expand, so we need to choose a fixed one. I believe that channels r or g are more preferable to expand this way than channel b.
QOI_COLOR has a similar issue too, we can choose 0 channels to writte.
The expansion in QOI_DIFF_24 is a bit tricky, we can expand R if all the other channels are 0, but there are actually a more clever way to expand channels than just by checking if all the other channels are equal to zero.
For example, we have 544 RGB deltas in QOI_DIFF_16 and 5555 RGBA deltas in QOI_DIFF_24, and if A channel is 0 in QOI_DIFF_24, it doesn't make sense to store the G and B channels in the 4-bit range, since we could just use QOI_DIFF_16 for that. So this way we can extend one of the channels (R channel), but not only from [-16, 15] to [-16, 16]/{0}, if I'm right, we can extend it up to [-32, -17]U[16, 31]...
Oh god, I just get it, we can actually do the same trick in QOI_DIFF_16 if both channels R, G and B deltas are in 2-bit range... The expansion won't be so giant here, since we only have 2 bits, but we still can change the R channel range from [-16, 15] to [-18, -17]U[16, 17].
The downside of this idea is that it will be a non-negligable encoding and decoding slowdown. I think the easier approach is to use QOI_INDEX
to store runs of length 2, and shift the range of QOI_RLE
up by 1.
Hmm, to be honest, I thought an 8 bit rle with stacking would be enough... I mean, when you compress 65536 pixels, it doesn't matter if they end up in 1 or 2 bytes, it's a strong compression anyway.. To be honest, I don't think many images have such large areas of repeating color anyway.
The place where it's a bigger change is if we increase the tag size of QOI_RLE
(which might help fit other opcodes in). I think 4 bits for RLE is probably the sweet-spot, at which point the difference between 17 and 18 might be noticeable.
sorry lol
Actually the same thing exists in 16-bit QOI_COLOR too, but I can't find the proper way to use it.. I mean, we never use QOI_COLOR with an R, G or B channel when the delta with the previous color can be encoded in QOI_DIFF_16, so 32 or 16 values are unused in 16-bit QOI_COLOR channel, or 1 bit is not used. I was thinking about adding an alpha channel here, but 1 bit is just a joke, it's really useless. (upd: I was wrong, there is no that 1 bit)