-
Notifications
You must be signed in to change notification settings - Fork 178
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
Possible bug in parametric curve handling inside cmsPipeline? #301
Comments
UPD: I worked around it by replacing the parametric curve by a tabulated version, e.g. Exampleauto trc = [ctx, baseProfile]() {
auto trc = reinterpret_cast<cmsToneCurve *>(cmsReadTag(baseProfile, cmsSigRedTRCTag));
std::array<cmsFloat32Number, 1024> test{};
for (auto i = 0; i < 1024; i++) {
cmsFloat32Number x = 1.0f/ 1024.0f * (cmsFloat32Number)i;
test[i] = cmsEvalToneCurveFloat(trc, x);
}
return cmsBuildTabulatedToneCurveFloat(ctx, test.size(), test.data());
}(); I believe this is definitely a bug, though not sure where inside LCMS. |
A quite complicated code, I see. May I ask for a small snippet that demonstrates the issue? |
Based on my workaround, this issue seems to happen only in conjunction with a complete pipeline. I tried keeping only the gamma-RGB-XYZ part and the result's gamut is correct, though. |
@mm2 I generated two separate profiles; one with the parametric curve swapped for the tabulated version, the other without. I sampled both pipelines with a 24x24x24 CLUT on both 16bit and floating point. The first diverging point I found was:
YCbCr For 16-bit, the first diverging point is also [0, 0, 0]:
Let me know if you need the complete profile generation code for each instance. |
Not sure about which code are debugging. Anyway if you compare 3D LUT interpolation versus a math expression, the results hardly depends on how you build the LUT. Keep in mind LUT's are interpolated linearly (tetrahedral or trilinear) and that means the indexing space should be as much linear as possible and the domain should be as wide as possible. Linear because the output will be linearly interpolated inside the cube of near nodes, and wide domain because you need to use as many nodes as possible. This is the reason of pre and post linearization tables, to provide linear space for 3D LUT. Example: a function f(x) = 2x -3 works fine in a 3D LUT, a function f(x) = 2x^2 does not because is is not linear, but using a linearization table t(x) = x^2 things got simplified, |
Not further comments so I close the issue |
Hi @mm2, I did not comment further because I don't know how else to demonstrate that there is a bug with how LittleCMS processes parametric curves as part of V2 pipelines. I already attached how to generate a profile demonstrating the bug, and how to work around it. |
OK let's reopen it |
Hi again,
I'm writing some code to generate an YCbCr ICC profile. For V2, in the YCbCr -> XYZ direction, I need to pack the full transformation in the LUT, as follows:
Demo
However, doing so completely breaks the gamut of the profile as viewed in Krita's Color Space Selector. I've narrowed it down to the type 4 parametric curve I use for the linearization step after the YCbCr conversion; if I replace it by another type, e.g.
cmsBuildGamma(ctx, 2.2)
, the problem disappears. This also doesn't occur in V4 profiles, where this step can be stored explicitly in the M curves of the AtoB0 tag.@mm2 I'm not sure what is going on here, would you take a look?
The text was updated successfully, but these errors were encountered: