jsummers / bmpsuite

A set of Windows BMP image files, for testing purposes
https://entropymine.com/jason/bmpsuite/
GNU General Public License v3.0
55 stars 16 forks source link

How are gamma & endpoints supposed to be handled? #15

Open ColinPitrat opened 3 years ago

ColinPitrat commented 3 years ago

Sorry for what follows, this is not really a bug, this is a cry for help. Note that I knew nothing about colorimetry a few days ago, so I'm probably saying stupid things.

I started to write a BMP parser in Rust, just to play with nom: https://github.com/ColinPitrat/RustMisc/tree/master/bmp. And I bumped into pal8v4.bmp which got me down a deep rabbit hole.

All the documentation I found says that the endpoints contain the XYZ coordinates of red, green & blue: https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-ciexyztriple

And there are also the per-color gamma.

So my understanding is that, when handling a color, I should:

But when I do this, this gives me a weird result, way to red. I tried removing/modifying gamma & endpoins in the file to see what it would give in other viewers. Most keep displaying the same thing (the "correct" display, although it's obviously not correct anymore as I messed with the colorimetry).

The exceptions are firefox & chrome. I therefore assume they support gamma & endpoints. But looking at firefox code: https://dxr.mozilla.org/mozilla-central/source/image/decoders/nsBMPDecoder.cpp#906

It builds a xyY endpoint and assumes a white point that is not provided by the BMP. My understanding is that no white point should be needed with XYZ endpoints. I also found this post where the author explains that they use your image suite to code it: https://blog.mozilla.org/nnethercote/2015/11/06/i-rewrote-firefoxs-bmp-decoder/ There are also comments in the code suggesting there has been exchanges between chrome & firefox codes.

So at this point I'm starting to wonder:

For the record, the way I modified gamma & endpoints (although modifying bmpsuite code would actually be easier):

$ xxd pal8v4.bmp pal8v4.hex
$ vi pal8v4.hex
# Either 0 out, rotate or modify values
# Typically rotating the endpoints (put green values for red, blue values for green and red values for blue)
$ xxd -r pal8v4.hex pal8v4_mod.bmp
jsummers commented 3 years ago

Sorry, but this is beyond my knowledge of both BMP and XYZ. I'm willing to change the sample file if presented with convincing evidence that it ought to be changed. And I'd consider adding one or two more files for colorimetry sanity tests.

ColinPitrat commented 3 years ago

What I did is that I patched your file and created the ones attached. I tested it on all the software I could think of:

I don't have access to a windows machine currently. Would you have access to any software using WIC (typically Windows Explorer or Photo Gallery)? I'd expect it to properly decode the image and I'd be interested to see if it's the same rendering as Firefox & Chrome.

bmp_gamma.zip

ColinPitrat commented 3 years ago

I asked a friend on Windows to check and it seems all files are displayed the same in Explorer & Photo Gallery, suggesting that even WIC doesn't support gamma & endpoints ...

And as your example is the only one I found, I guess I'll call it a day and ignore this functionality.

I'm interested if you ever come across other examples or implementations, or if you clarify this mystery.

pkasting commented 1 year ago

I wrote the Chrome decoder, and I couldn't find much useful documentation on how things were supposed to work, nor do I have a solid grasp of different color spaces, or Skia's color management functions. So I wouldn't be surprised if Chrome is doing the wrong thing.

The relevant code is at https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=356;drc=040667a8d3c4caf8ffbc1f4d6299a8bfe00fee13 . If you come up with what you believe is a more correct algorithm, feel free to send me a PR. Or even just a note. :)