Hacker News new | ask | show | jobs
by nightcracker 1662 days ago

    QOI_DIFF24 {
        u8 tag  :  4;   // b1110
        u8 dr   :  5;   // 5-bit   red channel difference: -15..16
        u8 dg   :  5;   // 5-bit green channel difference: -15..16
        u8 db   :  5;   // 5-bit  blue channel difference: -15..16
        u8 da   :  5;   // 5-bit alpha channel difference: -15..16
    }
It bothers me more than it should that the 5-bit signed differences aren't -16..15 matching two's complement but -15..16 instead.
3 comments

I should probably fix that. Is there a clever way to unpack a 5bit signed int other than treating it as unsigned and subtracting 16?
You'll have to shift the values around anyway, so:

int intermediate = byte_or_word << N; // N chosen to put the five bits in the highest positions in the int.

int value = intermediate >> bits_per_int - 5;

Instead of masking rely on arithmetic shift right to keep the sign bit.

That seems easiest.
Especially since your compiler will make it a super magical optimised version.
Who knows? Maybe it's the result of a heuristic that achieves a slightly better compression ratio.
Yes, this is baffling. Wonder if the format could still be amended to fix this?