phoboslab / qoi

The “Quite OK Image Format” for fast, lossless image compression
MIT License
6.85k stars 327 forks source link

Add a high-dynamic range support? #229

Closed MaGetzUb closed 1 year ago

MaGetzUb commented 2 years ago

So add a high-dynamic range support by using the idea from radiance image format. Store the exponent in the alpha channel, and the floating point significands into the r, g and b channels. Naturally the HDR image would be therefore just RGB. The HDR images are useful in 3D graphics, especially with IBL (image based lighting.)

Technically nothing has to be changed in QOI format itself, except maybe add some sort of implication to the header that the image is HDR type, like QOI_FORMAT_RGBE (E stand for exponent, and implies high dynamic range). Only thing that is needed is RGB32F -> RGBE8 preprocessing and RGBE8 -> RGB32F post processing steps after the data is stored / loaded. I'm not sure how this sort of data storing will effect the compression rates, but there's only one way to find out.

Pseudo code for RGB32F to RGBE8 processing:

void RGB32F_RGBE8(const RGB32F* pixel, RGBE8* result) {

      float maximum = float_max(pixel->red, float_max(pixel->green, pixel->blue));

      if(maximum < 1-e32f) {
           result->red = result->green = result->blue = result->exponent = 0;
      } else {

           int32_t expo;
           float mantissa = frexpf(maximum, &exponent) * 256.0f / maximum;
           pixel->red = (uint8_t)(pixel->red * mantissa);
           pixel->green = (uint8_t)(pixel->green * mantissa);
           pixel->blue = (uint8_t)(pixel->blue * mantissa);
           result->exponent = (128 + expo);
      }

} 

And pseudocode for the same other way around:

void RGBE8_RGB32F(const RGBE8* pixel, RGB32F* result) {

    int32_t exponent = pixel->exponent - 128;

    float multiplier = powf(2.f, exponent);

    result->red = ((float)pixel->red) * multiplier / 256.0f);
    result->green = ((float)pixel->green) * multiplier / 256.0f);
    result->blue = ((float)pixel->blue) * multiplier / 256.0f);

}

That's how radiance / .hdr images basically do the conversion.

phoboslab commented 1 year ago

QOI's compression scheme relies on an alpha value that stays mostly constant. Wouldn't this then result in terrible compression?