Hi, So what you really are asking for is a way to input out of gamut values to a profile. The answer is "not directly, but may be other ways". Please note this limitation comes from ICC spec, not because the CMM. Usual profiles are limited to 16 bits, and despite there is a floating point extension, there is no guarantee that a given profile would implement that. Up to date I've seen no single commercial profile supporting this, only prototypes.
At that point, I wonder why you want the Rec709 primaries. If you are coming from a wider space, why not to use a profile from original space and avoid all the out of gamut issue completely? Ok, I understand there are reasons to use such space, maybe you want to use Rec709 as a working space to do blending etc. My recommendation would be to use a wider space for input, forcing all values to be in-gamut of this space. XYZ would be a nice choice, its gamut is practically infinite in the ICC encoding. You could just apply a 3x3 matrix to go from your Rec709 space to XYZ, and then feed the XYZ values to a cmsCreateXYZProfile() builtin. You need no tone curves, just a 3x3 matrix. If you don't like the 3x3 matrix multiplication, LittleCMS has an extension (the "unbounded mode") that allows those negative numbers on certain profiles. The built-ins, for example. In 2.4 a linear profile would allow this as well. But anyway this is an extension of lcms and it would not work if you change the CMM. I wrote a paper about those issues at the color imaging conference couple of years ago CIC, see the paper here: http://www.littlecms.com/CIC18_UnboundedCMM.pdf Hope this helps Regards Matri El 09/09/2012 4:37, Wenzel Jakob escribió: > Hello, > > thank you for the clarification. > > I agree that "linear sRGB" is completely made-up. Nonetheless, in 3D > rendering applications, this space is used very often. When the goal > is to get sRGB output, the "linearized" version of sRGB is a quite > convenient space for performing inter-reflection computations (as > opposed to e.g. XYZ, xyY, CIELab, ..). > > I am thus interested in the answer to the following question: > > Given an out-of-gamut floating point RGB value (i.e. at least one of > the components is > 1) that is defined in a sRGB color space with a > linearized response, is it possible to use lcms2 to map it onto an > in-gamut sRGB value in a way that is smarter than just clipping the > individual components? (which causes hue shifts) > > I modified the snippet from the last email by replacing > "cmsCreate_sRGBProfile" with a call that loads the v4 preference > profile you suggested -- but still using the custom linear sRGB input > profile. As you already hinted, this still does not work -- the value > gets clipped before ever reaching the profile. Is there a way to avoid > this, or am I asking for something unreasonable? > > Thanks! > Wenzel > > > On 09/07/2012 05:09 PM, Marti Maria wrote: >> Hi, >> >> At first I have to clarify a very common misconception: there is no such >> thing like a "linear" sRGB. >> sRGB is a color space very precisely defined. >> >> See >> http://www.color.org/chardata/rgb/srgb.pdf >> http://www.color.org/chardata/rgb/srgb.xalter >> >> If you define a colorspace that has transfer functions of gamma 1.0, >> primaries Rec709 and D65 as >> white point you cannot call it "sRGB", just because this is not sRGB >> but something close but not >> sRGB. >> >> At that point, lcms2, as most of the modern CMM, uses what ICC describe >> as "smart profiles, >> dumb CMM". In this approach the profiles instructs the CMM how to do the >> gamut remapping >> and the CMM blindly obeys what the profile says. >> >> Then, looking at your code, you instruct the CMM to do exactly what you >> get: to apply a tone >> curves and to remain inside a set of primaries. So, it comes at no >> surprise you get no gamut >> mapping, it is just that you didn't tell the CMM how to do it. >> >> Let me show an example of what cold be done with a proper profile with >> embedded gamut >> mapping. Instead of using the simple cmsCreateRGBProfile () built-in, >> please download and >> try a real profile. You got some good sRGB ones from here: >> >> http://www.color.org/srgbprofiles.xalter#v4pref >> >> Please try the preference sRGB. With ICC trans you can check the profile >> without any coding. >> BTW, obviously you cannot use the same sRGB as the input, that would >> make impossible to >> encode out of gamut colors, and doing (0.5, 0.5, 1000) clips the value >> on the input - it >> doesn't even reach the profile. >> >> transicc -i*Lab -o sRGB_v4_ICC_preference.icc >> LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.04] >> >> Enter values, 'q' to quit >> L*? 50 >> a*? -128 >> b*? 23 >> >> R=0.0000 G=198.5075 B=124.5013 >> >> I'm converting an extremely saturated green to a in-gamut sRGB value by >> using gamut >> remapping. If I try the same by using just plain conversion: >> >> transicc -i*Lab -o *sRGB >> LittleCMS ColorSpace conversion calculator - 4.2 [LittleCMS 2.04] >> >> Enter values, 'q' to quit >> L*? 50 >> a*? -125 >> b*? 3 >> >> R=-900.4487 G=154.3234 B=109.4446 >> >> Quite different green! lcms2 unbounded mode gives you the RGB without >> clipping, please note the R=-900!! >> >> Please compare (0,154, 109) with (0, 199, 125). It would be nice if you >> get a chance to see >> the original Lab=(50, -128, 23) but I'm afraid no device can reproduce >> it because its extreme saturation. >> >> Hope that helps >> Regards >> Marti Maria >> The LittleCMS Project >> http://www.littlecms.com >> >> >> El 07/09/2012 2:15, Wenzel Jakob escribió: >>> Hello, >>> >>> I'm trying to use lcms2 to convert sRGB values from a linear double >>> precision representation into a gamma-corrected 8-bit representation >>> (using the sRGB-specific gamma correction curve). For in-gamut values, >>> that is a basic operation that doesn't really require a CMS. >>> >>> I'm more interested in how out-of-gamut values are treated (e.g. when >>> one of the double precision values is greater than one). >>> >>> Can lcms be configured to handle this using one of the the four intent >>> modes, for instance to desaturate the color instead of just clamping >>> each component separately? >>> >>> I've played around a bit (source attached) but was unable to produce >>> such behaviour. In all cases, lcms2 just clamped the individual >>> components without showing signs of doing some kind of more >>> sophisticated projection onto the gamut. This can be a problem because >>> clamping the components will lead to a hue shift, which may be >>> unintended. Is it just a problem of my setup, or am I expecting >>> something that lcms2 does not currently do? >>> >>> I've never used this library before, so any advice would be much >>> appreciated! >>> >>> Thank you very much, >>> Wenzel >>> >>> ===================== >>> >>> #include <lcms2.h> >>> #include <stdio.h> >>> #include <stdint.h> >>> >>> /* Create a linear sRGB profile (based on cmsCreate_sRGBProfile)*/ >>> cmsHPROFILE create_sRGBProfileLinear() { >>> cmsCIExyY D65; >>> cmsCIExyYTRIPLE Rec709Primaries = { >>> {0.6400, 0.3300, 1.0}, >>> {0.3000, 0.6000, 1.0}, >>> {0.1500, 0.0600, 1.0} >>> }; >>> >>> cmsWhitePointFromTemp(&D65, 6504); >>> >>> cmsToneCurve* gamma = cmsBuildGamma(NULL, 1.0); >>> cmsToneCurve* gamma3[] = { gamma, gamma, gamma }; >>> >>> return cmsCreateRGBProfile(&D65, &Rec709Primaries, gamma3); >>> } >>> >>> int main(void) { >>> cmsHPROFILE profile_sRGB = cmsCreate_sRGBProfile(); >>> cmsHPROFILE profile_sRGB_linear = create_sRGBProfileLinear(); >>> >>> cmsHTRANSFORM transform = cmsCreateTransform( >>> profile_sRGB, TYPE_RGB_DBL, profile_sRGB, TYPE_RGB_8, >>> INTENT_RELATIVE_COLORIMETRIC, 0); >>> >>> { >>> /* Inside of gamut: prints "188 188 188" -- that looks >>> good. */ >>> double a[] = {0.5, 0.5, 0.5}; >>> uint8_t out[3]; >>> cmsDoTransform(transform, a, out, 1); >>> printf("%i %i %i\n", (int) out[0], (int) out[1], (int) >>> out[2]); >>> } >>> >>> { >>> /* Outside of gamut: prints "188 188 255" ?? -- I would have >>> expected that the other channels would be scaled down due >>> to gamut mapping. */ >>> double a[] = {0.5, 0.5, 1000}; >>> uint8_t out[3]; >>> cmsDoTransform(transform, a, out, 1); >>> printf("%i %i %i\n", (int) out[0], (int) out[1], (int) >>> out[2]); >>> } >>> >>> cmsDeleteTransform(transform); >>> cmsCloseProfile(profile_sRGB); >>> cmsCloseProfile(profile_sRGB_linear); >>> } >>> >>> ------------------------------------------------------------------------------ >>> >>> >>> Live Security Virtual Conference >>> Exclusive live event will cover all the ways today's security and >>> threat landscape has changed and how IT managers can respond. >>> Discussions >>> will include endpoint security, mobile security and the latest in >>> malware >>> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >>> _______________________________________________ >>> Lcms-user mailing list >>> Lcms-user@lists.sourceforge.net >>> https://lists.sourceforge.net/lists/listinfo/lcms-user >>> > > ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ Lcms-user mailing list Lcms-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lcms-user