Hello,
the following used sRGB_linear.icc uses a single value gamma of
1.0 inside a version 2.x ICC profile.
$ transicc -i *xyz -o sRGB_linear.icc
LittleCMS ColorSpace conversion calculator - 4.1 [LittleCMS 2.03]
Enter values, 'q' to quit
X? -10
Y? -10
Z? -10
R=0.0000 G=0.0000 B=0.0000
The expected negative values where simply clipped.
The clipping happens in DefaultEvalParametricFn():
https://github.com/mm2/Little-CMS/blob/master/src/cmsgamma.c#L243
if (R < 0)
Val = 0;
Use case:
The graphics community discusses to use traditional sRGB primaries and use
floating point values to preserve wide gamut values as negative numbers.
(The above observed clipping effectively prevents that.)
Solution:
check for gamma of 1.0 and allow for negatives.
A first proof of concept patch is attached.
Would that approach integrate reasonable?
kind regards
Kai-Uwe Behrmann
--
www.oyranos.org
diff --git a/src/cmsgamma.c b/src/cmsgamma.c
index 02dc910..cb2fa76 100644
--- a/src/cmsgamma.c
+++ b/src/cmsgamma.c
@@ -250,16 +250,24 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// X = Y ^ Gamma
case 1:
- if (R < 0)
- Val = 0;
+ if (R < 0) {
+ if (Params[0] == 1.0)
+ Val = R;
+ else
+ Val = 0;
+ }
else
Val = pow(R, Params[0]);
break;
// Type 1 Reversed: X = Y ^1/gamma
case -1:
- if (R < 0)
- Val = 0;
+ if (R < 0) {
+ if (Params[0] == 1.0)
+ Val = R;
+ else
+ Val = 0;
+ }
else
Val = pow(R, 1/Params[0]);
break;
@@ -276,8 +284,12 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
if (e > 0)
Val = pow(e, Params[0]);
- else
- Val = 0;
+ else {
+ if (Params[0] == 1.0)
+ Val = e;
+ else
+ Val = 0;
+ }
}
else
Val = 0;
@@ -286,13 +298,14 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// Type 2 Reversed
// X = (Y ^1/g - b) / a
case -2:
- if (R < 0)
- Val = 0;
+ if (R < 0) {
+ if (Params[0] == 1.0)
+ Val = R;
+ else
+ Val = 0;
+ }
else
Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1];
-
- if (Val < 0)
- Val = 0;
break;
@@ -301,8 +314,6 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// Y = c | else
case 3:
disc = -Params[2] / Params[1];
- if (disc < 0)
- disc = 0;
if (R >= disc) {
@@ -310,8 +321,12 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
if (e > 0)
Val = pow(e, Params[0]) + Params[3];
- else
- Val = 0;
+ else {
+ if (Params[0] == 1.0)
+ Val = pow(e, Params[0]) + Params[3];
+ else
+ Val = 0;
+ }
}
else
Val = Params[3];
@@ -328,8 +343,12 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
if (e > 0)
Val = (pow(e, 1/Params[0]) - Params[2]) / Params[1];
- else
- Val = 0;
+ else {
+ if (Params[0] == 1.0)
+ Val = (pow(e, 1/Params[0]) - Params[2]) / Params[1];
+ else
+ Val = 0;
+ }
}
else {
Val = -Params[2] / Params[1];
------------------------------------------------------------------------------
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
Lcms-user mailing list
Lcms-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lcms-user