woelper / oculante

A fast and simple image viewer / editor for many operating systems
https://github.com/woelper/oculante
MIT License
1.02k stars 45 forks source link

Color Management support #258

Open woelper opened 10 months ago

woelper commented 10 months ago

Oculante needs a common way to handle loading and displaying color management profiles. OpenColorIO and other alternatives could be explored.

Quackdoc commented 10 months ago

related to this, jxl-oxide recently landed support for colormanaged output, including tonemapping and gamut mapping

woelper commented 10 months ago

Thanks for the info! I did not know that. jxl-oxide certainly is an impressive project!

Quackdoc commented 9 months ago

as an appendage to above, it's hard to do a full blown CMS modules like lcms in rust entirely, however Firefox's qcms might be a viable option? https://github.com/FirefoxGraphics/qcms

woelper commented 8 months ago

Thanks for the recommendation!

UmeSiyah commented 8 months ago

Hi there,

I'm recommend (if I may ^^) for an OpenColorIO implementation, it's the standard in the VFX industry.

Quackdoc commented 8 months ago

While OpencolorIO would be great, It's important to keep in mind that it is A) not native rust, nor super simple to compile, it requires more then a couple deps (one of which is lcms2 anyways). B) has no currently existing bindings

It certainly would offer a lot over traditional image viewers, but it does come with it's own detriments and more then a little bit of work. That being said, If color management in occulante is designed in a way that could make swapping the CMS library/crate, it could be a really nice feature to have behind a non-default compile flag

woelper commented 8 months ago

Great discussion! Having this as a swappable option from the start is a great idea. In the end, this is just about transforming pixel colors, right? Maybe I should start with a "No-op" CMS and then add different methods, ranging from something simple to ocio?

Quackdoc commented 6 months ago

so I've done a bit of investigation, lcms2 based solution seems to be the best. it sucks to have a non native rust library, but lcms2-sys builds a vendored lcms2 so package management wont be an issue. but below I will try to keep some options somewhat updates as I find them.

woelper commented 6 months ago

Thanks for looking at it! I've seen that the image library is able to extract a color profile - with lcms2 i could probably piece that together.

I am currently thinking if I implement this as a regular edit operator that can also be removed / disabled - for now that would mean that the edit panel opens if a icc profile is found. The upside of this is that you could load any icc profile on any image manually as well and I could use existing tech. That could also be a good place to start this support I suppose as it allows us to test this without breaking the experience / refactoring too much.

woelper commented 6 months ago

I've started a icc_profiles branch. You can load icc profiles manually and transform them to a standard icc profile.

Am I right that the ideal scenario would be to load the ICC from the image and transform it to the one your system is currently using?

Quackdoc commented 6 months ago

for display mapping, Ideally you really need two do two or three things

1.) by default transform the image to sRGB. This is how all operating systems interpret windows with no tagged colorspace. 2.a) Map the image to the nearest "common" colorspace and tag the window colorspace. 2.b) Map to the displays native colorspace, tag the window colorspace.

  1. Should be the priority because this is what "every OS" will expect at a minimum. Even if your monitor is set for Display P3, your OS will typically perform sRGB -> P3 mapping when the window is untagged. unfortunately this isn't globally true (also some platforms like KDE interpret sRGB windows as gamma2.2 the application doesn't really need to care about that). OFC when you start to get to things like HDR you need to use 2.a

  2. A) Map to a default color space and tag the information. how to figure out the displays color space may actually be fairly difficult, however the super simple yet very reliable solution is to just hard code some defaults and let the user pick. Most monitors do adhere to proper color spaces, However some have minor derivatives IE. you may need to have both sRGB ~2.2 (Real sRGB), sRGB Pure 2.2. but having a default set of color spaces is probably good enough. In color managed setups, the platform may or may not do conversions (it's actually really inconsistent), so tagging the proper color space will prevent that from being an issue. But if not, it can still help under most scenarios. note most ICCs will go to one these colorspaces anyways so in some cases no mapping will be needed (there are exceptions). so for sure, for this it's easiest to let the user choose a color space to map to (thanks to some platforms this is actively necessary as they don't provide enough information to adequately figure this out)

  3. B) probably isn't different from 2.a as I mentioned. Most monitors do adhere to specific color spaces. In color managed workflows you may need to do a bit of modification to match the monitors specifics, but that is often done by the platforms color management system. However there are cases where the OS will perform no mapping at all and leave it to the application, Getting the specific information is platform specific. Wayland I don't think can specify this at all and you only have srgb (well some hacks exist to make it work), x11 relies on colord, osx and windows have their own method for doing this.

Also with PNG and AVIF you also have CICP for denoting color information. https://www.w3.org/TR/png-3/#cICP-chunk the table of which can be found for free in the av1 spec https://aomediacodec.github.io/av1-spec/#color-config-semantics

but the TLDR of it, is it's a very simple way to denote colorspace as it tells you the "Color Primaries, Transfer, Matrix Coefficients, and full/limited range". and I believe lcms2 can handle this without much issues.

Quackdoc commented 6 months ago

also I did try the icc_profiles branch but it seems to just close out without error when I try to load an icc file

EDIT: it worked with debug mode...

EDIT2: lto = true is causing it to crash for me, I'm wondering if lcms is crashing, I'll do some more testing tommorow i've run out of time tonight. Thin crashed on some images, but not others.

woelper commented 6 months ago

Thanks for the context and trying it out! I was indeed working in debug mode and was curious why it crashed since I had removed all unsafe handling. Thanks for looking at that, much appreciated! I'll take a look too, but I am short on time at the moment.

Right now all the operator does is transform the image from the loaded profile to a default sRGB profile, but I thought that is a good way to test it.