Thread: [Lcms-user] Building a profile with a Rec 709 transfer curve
An ICC-based CMM for color management
Brought to you by:
mm2
From: Richard H. <hug...@gm...> - 2012-12-21 17:15:39
|
Hi all, I'm trying to build a profile with a Rec. 709 transfer curve. I thought I could do something like this: cmsFloat64Number params[7]; params[0] = 0.45; /* y */ params[1] = 1.099; /* a */ params[2] = 0.0; /* b */ params[3] = 4.5; /* c */ params[4] = 0.018; /* d */ params[5] = -0.099; /* e */ params[6] = 0.0; /* f */ return cmsBuildParametricToneCurve (NULL, 5, params); i.e. from the table here: https://en.wikipedia.org/wiki/Rec._709#Transfer_characteristics ...but that gives me very much the wrong looking curves. Thanks for any help. Richard. |
From: Marti M. <mar...@li...> - 2012-12-24 16:57:43
|
El 21/12/2012 18:15, Richard Hughes escribió: > cmsFloat64Number params[7]; > params[0] = 0.45; /* y */ > params[1] = 1.099; /* a */ > params[2] = 0.0; /* b */ > params[3] = 4.5; /* c */ > params[4] = 0.018; /* d */ > params[5] = -0.099; /* e */ > params[6] = 0.0; /* f */ > return cmsBuildParametricToneCurve (NULL, 5, params); Hi Richard, I think you have e and f swapped, this is from the documentation (Table 52) Y = (aX + b)^Gamma + e | X >= d Y = cX + f | X < d And this is Rec709 Image Regards & merry xmas Marti |
From: Marti M. <mar...@li...> - 2012-12-24 17:38:44
|
> Hi Richard, > > I think you have e and f swapped, this is from the documentation > (Table 52) > > Y = (aX + b)^Gamma + e | X >= d > Y = cX + f | X < d > > And this is Rec709 > > Image > Obviously this is not the case. What really happens is parametric curve type 5 has aX raised to gamma, whilst in Rec709 only L is raised to the 0.45 exponent. Sorry about the confusion Regards & merry xmas Marti |
From: Richard H. <hug...@gm...> - 2012-12-26 11:01:59
Attachments:
colord-rec709-plugin-fail.patch
|
On 24 December 2012 17:38, Marti Maria <mar...@li...> wrote: > Obviously this is not the case. What really happens is > parametric curve type 5 has aX raised to gamma, whilst > in Rec709 only L is raised to the 0.45 exponent. Right. I couldn't find any of the pre-supplied parametric curves that would work. I did find some commented out code in testbed/testcms2.c for a custom Rec. 709 curve. I've tried to use the modified code in colord, but it threw some errors: LCMS error 8: Unsupported parametric curve LCMS error 7: Couldn't write type 'para' LCMS error 8: Unsupported parametric curve LCMS error 7: Couldn't write type 'para' I've attached the patch for colord that I've tried. I *think* I'm registering the plugin correctly, but I've never done an lcms plugin before. It might be I'm doing something batshit-insane, in which case I'd appreciate some clue. :) Thanks, Richard. |
From: Richard H. <hug...@gm...> - 2012-12-29 10:22:28
|
On 26 December 2012 11:01, Richard Hughes <hug...@gm...> wrote: > LCMS error 8: Unsupported parametric curve > LCMS error 7: Couldn't write type 'para' > LCMS error 8: Unsupported parametric curve > LCMS error 7: Couldn't write type 'para' So I poked a bit more at this. Type_ParametricCurve_Write in src/cmstypes.c is unable to write the curve to the tag: if (typen > 5) { cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported parametric curve"); return FALSE; } This is because we're trying to write a ICCv4 cmsSigParametricCurveType when it's a custom plugin type that should be written as a table-based cmsSigCurveType. I've attached a patch which fixes the issue for me. I don't think it's possible for a plugin to create a new cmsSigParametricCurveType without this patch applied. Please review. Thanks, Richard |
From: Richard H. <hug...@gm...> - 2013-01-01 17:14:45
|
On 29 December 2012 10:22, Richard Hughes <hug...@gm...> wrote: > I've attached a patch which fixes the issue for me. And another patch attached: commit 17e2e35829993b7f7cbbf7ffe81859ee2f816f80 Author: Richard Hughes <ri...@hu...> Date: Tue Jan 1 17:13:10 2013 +0000 Fix the Rec. 709 parametric curve type example in the test program The code is commented out, but it stops someone trying to do the same as me making the same mistake. I spent a good couple of hours looking at the maths before the mistake popped out at me. I had to manually invert the formula and plot the graph in OpenOffice to verify the sign was indeed wrong. It's up to you if you just want to remove the #ifdef0 code, but having a wrong example is probably a bad thing :) I've added a a Rec. 709 profile to shared-color-profiles now. Thanks. :) Richard. |
From: Marti M. <mar...@li...> - 2013-01-07 17:57:06
|
Hi Richard, Back from holidays. I realize this message is quite old, so I apologize... Ok, There was a reason to limit the tone curve plug-in and disallow the file IO. It happens that the file format is defined by the ICC (and only by the ICC!), so any addition made by anyone else would turn the profile in not compliant, and I'm afraid many CCM will just discard it. So the plug-in feature allows you to create new tone curves and play with those tone curves in pipelines, evaluators, etc. but keeping in mind this is only for data handling and not to be saved as a profile. An example would be to create a special tone curve for a profiler to be used to compute LUT points, the points then are meant be saved as a CLUT in the final profile but the math curve is not. But anyway, I think there is a clean way to do what you wish, and this needs only a few math. It seems to me the issue comes because parametric 5 is in the form (a*x)^g and you need a*(x)^g But nothing prevents you to compute a new a' instead a'=a^(1/g) See below the parameters disposition params[0] = 0.45; /* y */ params[1] = pow(1.099, 1.0 / 0.45); /* a' */ params[2] = 0.0; /* b */ params[3] = 4.5; /* c */ params[4] = 0.018; /* d */ params[5] = -0.099; /* e */ params[6] = 0.0; /* f */ I've checked this against the "normal" Rec709, and it works at 16 bits precision. See the testing code below. Sorry again for the delay Regards Marti ----- static double Rec709(double L) { if (L <0.018) return 4.5*L; else { double a = 1.099* pow(L, 0.45); a = a - 0.099; return a; } } static cmsInt32Number CheckParametricRec709(void) { cmsFloat64Number params[7]; cmsToneCurve* t; int i; params[0] = 0.45; /* y */ params[1] = pow(1.099, 1.0 / 0.45); /* a */ params[2] = 0.0; /* b */ params[3] = 4.5; /* c */ params[4] = 0.018; /* d */ params[5] = -0.099; /* e */ params[6] = 0.0; /* f */ t = cmsBuildParametricToneCurve (NULL, 5, params); for (i=0; i < 256; i++) { cmsUInt16Number f1 = floor(255.0*cmsEvalToneCurveFloat(t, i / 255.0) + 0.5); cmsUInt16Number f2 = floor(255.0*Rec709((double) i / 255.0) + 0.5); if (f1 != f2) { return 0; } } return 1; } |
From: Richard H. <hug...@gm...> - 2013-01-07 20:57:12
Attachments:
Rec709.icc
|
On 7 January 2013 17:57, Marti Maria <mar...@li...> wrote: > Ok, There was a reason to limit the tone curve plug-in and disallow the file > IO. It happens that the file format is defined by the ICC (and only by the > ICC!), so any addition made by anyone else would turn the profile in not > compliant, and I'm afraid many CCM will just discard it. Sure, agreed, but.. > An example would be to create a > special tone curve for a profiler to be used to compute LUT points, the > points then are meant be saved as a CLUT in the final profile but the math > curve is not. Right, but that's what my patch does -- it doesn't write the parametric curve, but the 4096 'curv' table data. I've attached the profile for you to see. Richard. |
From: Marti M. <mar...@li...> - 2013-01-07 23:04:31
|
Ah, ok I see. So, with your modification any new curves defined by a external plug-in got serialized as a table instead of giving error. Cool, this is an interesting addition. Thanks! Regards Marti El 07/01/2013 21:57, Richard Hughes escribió: > On 7 January 2013 17:57, Marti Maria <mar...@li...> wrote: >> Ok, There was a reason to limit the tone curve plug-in and disallow the file >> IO. It happens that the file format is defined by the ICC (and only by the >> ICC!), so any addition made by anyone else would turn the profile in not >> compliant, and I'm afraid many CCM will just discard it. > Sure, agreed, but.. > >> An example would be to create a >> special tone curve for a profiler to be used to compute LUT points, the >> points then are meant be saved as a CLUT in the final profile but the math >> curve is not. > Right, but that's what my patch does -- it doesn't write the > parametric curve, but the 4096 'curv' table data. I've attached the > profile for you to see. > > Richard. |
From: Richard H. <hug...@gm...> - 2013-01-08 09:05:19
Attachments:
Rec709.icc
|
On 7 January 2013 17:57, Marti Maria <mar...@li...> wrote: > But anyway, I think there is a clean way to do what you wish, and this needs > only a few math. > It seems to me the issue comes because parametric 5 is in the form > (a*x)^g > See below the parameters disposition Unless I'm mistaken (and that's entirely plausible) we want the TRC to be the inverse of the Rec. 709 curve, rather than the power curve of that type. I've attached the ICC profile generated from your type 5 parametric curve which to me seems the "wrong way around". Using the inverse method gives me a profile that matches the rawtherapee Rec. 709 profile exactly. I don't know if it's possible to do an inverse Rec. 709 profile with an existing parametric curve type. If it is, the profile size would be substantially smaller so still might be worth looking into. Richard. |
From: Florian H. <lis...@ho...> - 2013-01-08 16:07:52
|
Am 08.01.2013 10:05, schrieb Richard Hughes: > On 7 January 2013 17:57, Marti Maria <mar...@li...> wrote: >> But anyway, I think there is a clean way to do what you wish, and this needs >> only a few math. >> It seems to me the issue comes because parametric 5 is in the form >> (a*x)^g >> See below the parameters disposition > > Unless I'm mistaken (and that's entirely plausible) we want the TRC to > be the inverse of the Rec. 709 curve, rather than the power curve of > that type. I've attached the ICC profile generated from your type 5 > parametric curve which to me seems the "wrong way around". Agreed, the curves from the attached profile look very steep. The curves from the profile attached to your earlier message look alright to me (and closer inspection confirms that they indeed follow the Rec. 709 transfer function). -- Florian |
From: Mark <de...@ci...> - 2013-04-15 09:10:38
|
Hello, this is somewhat outdated… I did look at the two profiles that where posted to the list, and I was wondering if the whitepoint (wptp) is not wrong. It is set to D50, but Rec 709 specifies D6 - or? On 08.01.2013, at 16:42, Florian Höch <lis...@ho...> wrote: > Am 08.01.2013 10:05, schrieb Richard Hughes: >> On 7 January 2013 17:57, Marti Maria <mar...@li...> wrote: >>> But anyway, I think there is a clean way to do what you wish, and this needs >>> only a few math. >>> It seems to me the issue comes because parametric 5 is in the form >>> (a*x)^g >>> See below the parameters disposition >> >> Unless I'm mistaken (and that's entirely plausible) we want the TRC to >> be the inverse of the Rec. 709 curve, rather than the power curve of >> that type. I've attached the ICC profile generated from your type 5 >> parametric curve which to me seems the "wrong way around". > > Agreed, the curves from the attached profile look very steep. The curves > from the profile attached to your earlier message look alright to me > (and closer inspection confirms that they indeed follow the Rec. 709 > transfer function). > > -- > Florian > > ------------------------------------------------------------------------------ > Master SQL Server Development, Administration, T-SQL, SSAS, SSIS, SSRS > and more. Get SQL Server skills now (including 2012) with LearnDevNow - > 200+ hours of step-by-step video tutorials by Microsoft MVPs and experts. > SALE $99.99 this month only - learn more at: > http://p.sf.net/sfu/learnmore_122512 > _______________________________________________ > Lcms-user mailing list > Lcm...@li... > https://lists.sourceforge.net/lists/listinfo/lcms-user |
From: Richard H. <hug...@gm...> - 2013-04-15 09:14:47
|
On 15 April 2013 09:57, Mark <de...@ci...> wrote: > this is somewhat outdated… I did look at the two profiles that where posted to the list, and I was wondering if the whitepoint (wptp) is not wrong. It is set to D50, but Rec 709 specifies D6 - or? According to http://en.wikipedia.org/wiki/Rec._709, Rec. 709 uses Illuminant D65. As I generated a v4 profile, the wptp has to be D50, and there's a chad to adapt this to D65. Richard. |
From: Mark <de...@ci...> - 2013-04-15 09:55:45
Attachments:
Rec709-QuickTime.icc
|
Thanks for the clarification. I noted that comparing your profile to the one used by Apple (CoreVideo API) to display Rec 709 QuickTime movies. Apples profile is V2, and uses D65. |
From: Mark <de...@ci...> - 2013-04-15 11:04:02
|
Hello, if I'm reading the code correctly, LCMS defaults to using Tetrahedral interpolation unless CMS_LERP_FLAGS_TRILINEAR is specified as flag when creating a transform. Is there any study, how much "better" tethrahedral is compared to trilinear? How many gridpoints more are required for trillinear clut, so it matches a tethrahedral clut? Ultimately, I'm trying to apply the CLUT on the GPU, and I'm thinking if it is worth implementing tethrahedral in a shader, or better to just stick to trilliniar, which is built in already. PS: does CMS_LERP_FLAGS_TRILINEAR affect how the CLUT in built in any way? Or is this just a flag for the interpolator? Regards mark |
From: Richard H. <hug...@gm...> - 2013-04-15 11:09:28
|
On 15 April 2013 12:03, Mark <de...@ci...> wrote: > Ultimately, I'm trying to apply the CLUT on the GPU, and I'm thinking if it is worth implementing tethrahedral in a shader, or better to just stick to trilliniar, which is built in already. I don't know if it's helpful, I was playing with doing the transform in a shader using cogl and clutter a few months ago: https://github.com/hughsie/colord-playground/blob/master/src/cd-icc-effect.c Richard |
From: Graeme G. <gr...@ar...> - 2013-04-15 15:10:38
|
Mark wrote: > Is there any study, how much "better" tethrahedral is compared to trilinear? How many gridpoints > more are required for trillinear clut, so it matches a tethrahedral clut? There's been quite a bit of research into different formulations of 3D and N-D interpolation. There are multiple forms of tetrahedral interpolation, since a cube can be divided up into tetrahedrons in multiple different ways. Even sticking to the usual diagonal tetrahedral decomposition, it's possible to choose which diagonal so as to minimise interpolation error. There are hybrid schemes such as prism interpolation. Sticking to the major two you mention, diagonal tetrahedral interpolation is typically used for "device like" spaces, where the input diagonal is in the neutral axis direction (ie. RGB, CMY etc.), while trilinear is typically used for Luminance + color input spaces such as L*a*b* input etc. icclib (from ArgyllCMS) makes this distinction, although imdi/cctiff does not. Another quite important aspect is the application of 1D curves to the input and output. The 3D part is the coarsest part of the interpolation, so it's important to make the 3D part operate in a roughly perceptually uniform space, so that quantisation errors are uniformly distributed. The 1D curves give you scope to manage this. A reference that may be interesting is: "Interpolation errors on gray gradations caused by three-dimensional lookup table method", Katsuhiro Kanamori, Journal of Electronic Imaging, April 2001, Vol 10(2), pp 431 > Ultimately, I'm trying to apply the CLUT on the GPU, and I'm thinking if it is worth > implementing tethrahedral in a shader, or better to just stick to trilliniar, which is built in > already. If you're using hardware and the interpolation is relatively cheap, then you are probably better off trading finer resolution against a different interpolation algorithm. ie. If ideally you want tri-linear, but all you've got is tetrahedral, you may be better off using tetrahedral at twice the grid resolution instead. My impression from "Using Lookup Tables to Accelerate Color Transformations", Jeremy Selan, GPU Gems 2, pp 381 was that by default texture lookups are tri-linear. Graeme Gill. |