-
-
Notifications
You must be signed in to change notification settings - Fork 851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Color conversion with ICC profiles #1567
base: main
Are you sure you want to change the base?
Conversation
I wonder why the test |
@brianpopow It'll be an accuracy issue most likely. (I hope it's not a JIT issue). It should be possible to inspect the result and see. |
Codecov Report
@@ Coverage Diff @@
## main #1567 +/- ##
======================================
Coverage ? 87%
======================================
Files ? 1023
Lines ? 55212
Branches ? 7052
======================================
Hits ? 48227
Misses ? 5768
Partials ? 1217
Flags with carried forward coverage won't be shown. Click here to find out more. 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
The issue only happens with a Release build. I think i found the reason, but it seems very weird. This can be seen with the testoutput:
|
@brianpopow Woah! That's bonkers! |
I have reported this issue: dotnet/runtime#55623 They confirmed the issue, but they say its unlikely to be fixed because netcore2.1 is out of support in august. |
@JimBobSquarePants It would be really nice, if we could bring this PR forward. This would be a good addition to ImageSharp. I thought, I may ask you, if you know what the PR needs (besides tests) to be finished? What would be the right way to apply an embedded color profile? My first attempt was:
Here is an example image with adobe rgb color profile: This does not seems to work, the colors seem to be wrong. Here are more example images |
@brianpopow Honestly..... I don't know. I was hoping the OP would come back to finish things off. I've just kept things updated over the years and hadn't gotten involved at all in the implementation as yet. Judging from the old comments in the previous PR I believe the code is based somewhat based on the following https://github.com/InternationalColorConsortium/DemoIccMAX/tree/master/IccProfLib As for accuracy. That result looks like it's just spitting out the sRGB values again. I do agree that it would be an awesome addition to the library and would save a ton of headaches. I hoped we'd get it in V3 but that's a mighty big ask. |
I think we definitely need a reference implementation to compare the results against. I tried BABL which gnome is using, but i could not get it to work on windows. I will take a look at DemoIccMAX |
@brianpopow @saucecontrol I've been trying to debug the port of the Clut 4d interpolator but I'm drawing a blank because I have no idea how to run DemoIccMAX IccProfLib to do a comparison. Any hints? My money is on the port being sound but I'm doing something stupid porting the pcs to CIELab to convert via the color converter in |
@JimBobSquarePants I struggle myself to understand how DemoIccMAX is supposed to work. I would suggest trying to understand how Little-CMS does it. There are alot of tests included in Little-CMS, maybe we can try to replicate one of them (maybe
edit: There is no need to generate the visual studio project files, there are already ones in the repo: https://github.com/mm2/Little-CMS/tree/master/Projects/VC2022 |
Thanks @brianpopow I can't find anything useful there unfortunately. |
I added some code and notes to the converter to help debugging. What I'm seeing is the results of the lut transform result in very minor differences to the output value for each pixel 1e05. I'm wondering if somehow, we have a scaling problem. |
What is the state of this? Lack of ICC support is a major blocker for us. |
The state is as discussed in the various comments above, without contribution this PR will not be completed. We support ICC profile preservation but not transformation during decode. |
Hello, I would be interested in looking into this, I spent some time trying to understand ICC Profiles already. I started looking into this PR but I'm having hard time figuring out the exact state of the PR and what is missing. From what my quick overview most (all ?) of the pieces are already there, and we just need to test this / fix bugs found during testing ? For the tests, would it be valid to take random image (or the same for all the test) embed various profile we can find, convert them with a reference implementation (Little CMS or library like Skia or Gid+ ?) and the validate that the implementation here is giving the exact same results ? |
Thanks @Socolin any assistance would be useful. I also believe that most of the pieces are also there and with some rough initial testing accuracy for the working parts. However we have an issue with Multi LUT profiles. There's some sort of scaling issue there that I haven't been able to debug as I am not able to get any reference implementations running. I have wondered also, once we get things working whether we can use instances of |
I've updated this with the latest codebase from |
I still plan to investigate this, I was busy last few weeks, I should find some time for this again in few weeks |
I'm slowly piecing together ICC colour conversion for my own C# library, specifically targeting output "prtr" class profiles + LAB PCS + 16-bit and 8-bit LUT - so basically only version 2 CMYK currently. Gotta start small, the ICC spec is too overwhelming otherwise! Anyway, I'm 99% sure I've got that use case implemented with input curves > n-dimensional CLUT interpolation > output curves (for example, getting expected values from 7D CMYKOGV). If your issues lie in this area, I'd be happy to try and help out once I've wrapped up my changes? I also plan to support "A to B" type LUT (i.e. version 4 CMYK profiles) - if that's the problem area, it'll be a bit longer before I've tackled that. Apologies if I'm way off, it's quite a dense thread to follow 😅 |
@waacton It's a very hard thread to follow!! It reads to me like you've made progress in the specific areas that we don't currently have working. I'd be overjoyed if you were able to contribute code to get this working, obviously anything here is also up-for-grabs in your separate implementation. BTW Unicolour is a very intriguing library, I plan to have a good dig around there! I've recently reimplemented the color space conversion APIs in ImageSharp for V4 #2739 and am always keen to learn. |
Wonderful, I'll try to find time soon to see if/how our implementations differ. Even if there's something I can do to get it working, I doubt any code I write will meet your performance criteria 😅 so I expect someone might need step in for optimisation. And fingers crossed Unicolour is useful for someone other than me! If it doesn't give the right answers after the absolute battering it's taken from the unit tests, then... 🫠 but feel free to ask questions or highlight anything suspicious or questionable, I'm still learning as I go. |
Just a quick update: some initial testing suggests that the core LUT functionality is working, at least for 4D CMYK device to LAB PCS, with respect to DemoIccMAX. For example, with some careful handling of numeric types, this Fogra39 profile with hardcoded relative intent (an easier intent to test, no need for PCS adjustment) gives exactly the same LAB values. var bytes = File.ReadAllBytes("./Coated_Fogra39L_VIGC_300.icc");
var converter = new IccDataToPcsConverter(new IccProfile(bytes));
var pcs = converter.Calculate(new Vector4(0.8f, 0.6f, 0.4f, 0.2f));
var iccLab = Vector4.Multiply(pcs, 65535f / 65280f); // Lab2 to Lab4
var l = iccLab[0] * 100; // 37.8027306
var a = (float)(iccLab[1] * 255.0 - 128.0); // -3.48995304
var b = (float)(iccLab[2] * 255.0 - 128.0); // -15.3412971 For what it's worth, my library uses doubles and different CLUT implementation and gets the result Given that the CLUT calculator is a direct port of the DemoIccMAX code, it's no real surprise that everything looks to work sensibly, but there are 5 different interpolation functions there; I only tested one usage of the 4D interpolation, plenty of room for bugs elsewhere! Finally, the failing tests in
Sadly I don't know anything about how images actually encode CMYK data, so I'm not sure there's anything I can contribute in code just yet 😥. Happy to help get to the bottom of any other specific ICC conversion concerns! |
Apologies for the slow response and thank you for your investigation. Yes...That makes perfect sense.... 😞 Our code is assuming that the converters are operating in a manner that can handle the input Vector using an RGBA layout with values ranging from 0-1. Of course, this isn't the case and is a huge bug. When converting from a This is going to get messy given that our color-space converter expects a generic type. |
The fix for this (dear reader) will be to update If anyone has time to make a start on the first part I can run with the second. |
This sounds like something I'm conceptually familiar with so I'll aim to find some time over the holidays (though if anyone else is keen, please go ahead) |
@waacton if you can please do. 👍 |
@JimBobSquarePants I've been exploring the The kind of things lurking in my mind are:
|
Prerequisites
Description
Note: This is a replacement for the original PR #273 from @JBildstein that was automatically closed by our Git LFS history rewrite. Individual commits have unfortunately been lost in the process. Help is very much needed to complete the work.
As the title says, this adds methods for converting colors with an ICC profile.
Architecturally, the idea is that the profile is checked once for available and appropriate conversion methods and a then a delegate is stored that only takes the color values to convert and returns the calculated values. The possible performance penalty for using a delegate is far smaller than searching through the profile for every conversion. I'm open for other suggestions though.
There are classes to convert from the profile connection space (=PCS, can be XYZ or Lab) to the data space (RGB, CMYK, etc.) and vice versa. There are also classes to convert from PCS to PCS and Data to Data but they are only used for special profiles and are not important for us now but I still added them for completeness sake.
A challenge here is writing tests for this because of the complexity of the calculations and the big amount of different possible conversion paths. This is a rough list of the paths that exist:
The three main approaches in that list are
The most used approaches are Color Trc for RGB profiles and LutAToB/LutBToA for CMYK profiles.
Todo list:
Help and suggestions are very welcome.