ampas / aces-dev Goto Github PK
View Code? Open in Web Editor NEWAMPAS Academy Color Encoding System Developer Resources
Home Page: https://acescentral.com
License: Other
AMPAS Academy Color Encoding System Developer Resources
Home Page: https://acescentral.com
License: Other
Perhaps I'm misunderstanding how brew works, but it appears that the bottled ctl contains compiled libraries that reference obsolete compiled libraries, specifically libIex-2_1.11. Problem and workaround:
57 % brew install ctl
==> Installing dependencies for ctl: ilmbase, openexr
==> Installing ctl dependency: ilmbase
==> Downloading https://homebrew.bintray.com/bottles/ilmbase-2.2.0.yosemite.bottle.tar.gz
Already downloaded: /Library/Caches/Homebrew/ilmbase-2.2.0.yosemite.bottle.tar.gz
==> Pouring ilmbase-2.2.0.yosemite.bottle.tar.gz
🍺 /usr/local/Cellar/ilmbase/2.2.0: 347 files, 6.4M
==> Installing ctl dependency: openexr
==> Downloading https://homebrew.bintray.com/bottles/openexr-2.2.0.yosemite.bottle.tar.gz
Already downloaded: /Library/Caches/Homebrew/openexr-2.2.0.yosemite.bottle.tar.gz
==> Pouring openexr-2.2.0.yosemite.bottle.tar.gz
🍺 /usr/local/Cellar/openexr/2.2.0: 129 files, 12M
==> Installing ctl
==> Downloading https://homebrew.bintray.com/bottles/ctl-1.5.2.yosemite.bottle.tar.gz
Already downloaded: /Library/Caches/Homebrew/ctl-1.5.2.yosemite.bottle.tar.gz
==> Pouring ctl-1.5.2.yosemite.bottle.tar.gz
🍺 /usr/local/Cellar/ctl/1.5.2: 45 files, 3.9M
58 % otool -L /usr/local/lib/libIlmCtl.1.5.0.dylib
/usr/local/lib/libIlmCtl.1.5.0.dylib:
/usr/local/lib/libIlmCtl.1.5.0.dylib (compatibility version 1.5.0, current version 1.5.0)
/usr/local/lib/libIex-2_1.11.dylib (compatibility version 12.0.0, current version 12.0.0)
/usr/local/lib/libIlmThread-2_1.11.dylib (compatibility version 12.0.0, current version 12.0.0)
/usr/local/lib/libHalf.11.dylib (compatibility version 12.0.0, current version 12.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
59 % man brew
60 % brew uninstall ctl
Uninstalling /usr/local/Cellar/ctl/1.5.2... (45 files, 3.9M)
61 % brew install ctl --build-from-source
==> Downloading https://github.com/ampas/CTL/archive/ctl-1.5.2.tar.gz
==> cmake .. -DCMAKE_C_FLAGS_RELEASE= -DCMAKE_CXX_FLAGS_RELEASE= -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/ctl/1.5.2 -DCMAKE_BUILD_TYPE=Release -DCMAKE_FIND_FRAMEWORK=LAST -
==> make
==> make check
==> make install
🍺 /usr/local/Cellar/ctl/1.5.2: 47 files, 3.9M, built in 38 seconds
62 % !otool
otool -L /usr/local/lib/libIlmCtl.1.5.0.dylib
/usr/local/lib/libIlmCtl.1.5.0.dylib:
/usr/local/lib/libIlmCtl.1.5.0.dylib (compatibility version 1.5.0, current version 1.5.0)
/usr/local/lib/libIex-2_2.12.dylib (compatibility version 13.0.0, current version 13.0.0)
/usr/local/lib/libIlmThread-2_2.12.dylib (compatibility version 13.0.0, current version 13.0.0)
/usr/local/lib/libHalf.12.dylib (compatibility version 13.0.0, current version 13.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
63 %
When processing images through the CTL, occasional horizontal streaks appear in certain parts of certain images. Note that these artifacts are not reproducible.
Platform information:
Fedora 15 x86_64
CTL 1.4.2
ilmbase 1.0.2
Per Jim Houston:
So I took a look at the acesLog_to_lin function, and it pretty much blows up for any floating point input > 56.0. But also it also generates the maximum ACES half float value at only 1.46799639 as the ‘in’ value. So shouldn’t we have a input clip at one of those two values otherwise numerically it will blow up."
Definition of CONERESPMATBRADFORD
in utilities.ctl is incorrect.
Matrix should be changed to:
const float CONERESPMATBRADFORD[3][3] = {
{0.89510, -0.75020, 0.03890},
{0.26640, 1.71350, -0.06850},
{-0.16140, 0.03670, 1.02960}
};
NOTE: The erroneous matrix exists only in the dev
branch. If you are looking for this in your utilities.ctl
you will not see it on the master
.
At points in both the ODT and RRT code, tests are occasionally performed to avoid divide by zero or negative numbers. For example, in the ODT ratio preserving tonecurve, the function checks for normRGB equal to zero and sets to a small value (1e-12). These tests should check for less than the small value, since numbers between these and zero might underflow (and aren't lifted up to 1e-9 or 1e-12 respectively). As currently written, they also could pass negative numbers.
thus:
if (normRGB = 0.0) normRGB = TINY;
would become:
if (normRGB < TINY) normRGB = TINY;
and so on.
It's also not consistent how each instance is handled currently.
Examples:
if (normRGB <= 0.0) normRGB = TINY;
if (max_chan == 0.0) max_chan = 1e-9;
should be
if (normRGB < TINY) normRGB = TINY;
if (max_chan < 1e-9) max_chan = 1e-9;
Note: This has not manifested any visible errors to date, but should be cleaned up and addressed in a future update to the code to eliminate possible artifacts.
In actual use, both the unbuild and the ACESproxy10-to-ACES CTL files would take 10-bit-integer encoded values.
The unbuild code scales its input:
// Prepare input values based on application bit depth handling
float adx[3];
adx[0] = rIn * 1023.0;
adx[1] = gIn * 1023.0;
adx[2] = bIn * 1023.0;
However, the inverse ACESproxy transform does not.
As a result, one can use the supplied unbuild transform with ctlrender and 10-bit integral files as input straightforwardly. Not so with the ACESproxy10 conversion back to ACES.
The ACESproxy10 transform follows the formulae in S-2013-001 exactly and is a reference implementation of that transform, avoiding inclusion of any CTL lines that are application-specific to the behavior of ctlrender. On the other hand, the unbuild transform works well with ctlrender, but includes lines that if ported to another language as written could cause incorrect output because of confusion of being part of the reference transform.
These inconsistencies should be resolved.
Right now the various documents are all aggregated together in a zip file available as a link from this file in the repository: https://github.com/ampas/aces-dev/tree/master/documents
I think they should be directly in the repository and versioned like the code, their access would be easier and it would especially make citations a lot more easier.
From Doug Walker ...
I think I've encountered a bug in the CTL compiler where a variable is
incorrectly being classified as non-varying rather than varying. I'm
guessing the compiler makes some optimizations on non-varying variables
which are causing the error. I was wondering if you could take a quick look
at the enclosed script and offer any advice you may have? (It's only a page
of code.)
Through trial and error, I found that in order to make the script run
correctly, I need to add zero times a varying variable to another variable.
(I am using the print statement to tell whether the compiler has classified
variables as varying or non-varying.)
In the script invSeqLut.ctl, the variables in0 and in1 definitely need to be
varying but unless I do the aforementioned hack, they are apparently
classified as non-varying and as a result the first pixel evaluated is
correct but subsequent pixels are wrong. (The other script seq_lut.ctl is
just a LUT but I enclose it since the other script imports it.)
http://dl.dropbox.com/u/2184584/github_files/invSeqLut.ctl
http://dl.dropbox.com/u/2184584/github_files/seq_lut.ctl.zip
Here is some example output:
In the first run, do_hack = true. The output is correct.
ctl.eval(tmp[2:4,:])
in0 = [varying (0, 0.0109375) (1, 0.0109375)]
sol = [varying (0, 0.0316226) (1, 0.0562341)]
in0 = [varying (0, 0.0109375) (1, 0.0109375)]
sol = [varying (0, 0.0316227) (1, 0.0562341)]
in0 = [varying (0, 0.0109375) (1, 0.0109375)]
sol = [varying (0, 0.0316228) (1, 0.0562341)]
array([[ 0.0316, 0.0316, 0.0316],
[ 0.0562, 0.0562, 0.0562]], dtype=float32)
In this run, do_hack = false. Only the first value is correct.
ctl.load_module("invSeqLut")
ctl.eval(tmp[2:4,:])
ctl.load_module("invSeqLut")
ctl.eval(tmp[2:4,:])
in0 = 0.0109375
sol = [varying (0, 0.0316226) (1, 0.0502448)]
in0 = 0.0109375
sol = [varying (0, 0.0316227) (1, 0.049379)]
in0 = 0.0109375
sol = [varying (0, 0.0316228) (1, 0.0516209)]
array([[ 0.0316, 0.0316, 0.0316],
[ 0.0502, 0.0494, 0.0516]], dtype=float32)
(In the first run, in0 is the same for both pixels (as is in1) so it is
curious that the result of the second run would be wrong for these pixels,
but in general it is clear that in0 needs to be varying.)
The HDR ODTs seem to be producing NaNs. Example images are attached. The command lines used to generate the images are below.
ODT 4000 nits
Github doesn't seem to like attachments that aren't PNG, Gif, or JPG, so you can grab the example images here:
https://drive.google.com/file/d/0B9y8CcBvBvWoaHJvZ2xMbFBDNTA/view?usp=sharing
The link the the Canon IDTs in the README is dead and needs to be updated.
The HDR ODTs are using a luminance-to-CV scaling with CINEMA_BLACK and
CINEMA_WHITE. These are parameters for the "cinema" tonescale and should not be used in the HDR ODTs, which use PQ to encode luminance.
E.g. for documentation and images.
On linux, I'm trying to do a local installation, using the --prefix option to 'configure'.
Everything works cleanly, (all building / linking works!), except the final installation script assumes it can write to /ctl/modules. This should be fixed to obey the --prefix option. (probably added as the modules subdir)
make[3]: Entering directory /net/soft_scratch/users/jeremys/git/iif-dev/apps/ctlrender/src/openexr/CtlModules' make[3]: Nothing to be done for
install-exec-am'.
test -z "/ctl/modules" || /bin/mkdir -p "/ctl/modules"
/bin/mkdir: cannot create directory /ctl': Permission denied
My installation procedure:
`iif-dev/apps/ctlrender/prereqs/ilmbase-1.0.2
./bootstrap
./configure --prefix=/net/homedirs/jeremys/ctl
make
make install
iif-dev/apps/ctlrender/prereqs/openexr-1.7.0
./bootstrap
env PKG_CONFIG_PATH=/net/homedirs/jeremys/ctl/lib/pkgconfig/ ./configure --prefix=/net/homedirs/jeremys/ctl
make
make install
iif-dev/apps/ctlrender/prereqs/jpeg-6b
./configure --prefix=/net/homedirs/jeremys/ctl
make
make install
iif-dev/apps/ctlrender/prereqs/tiff-3.8.2
make
make install`
iif-dev/apps/ctlrender/src
env PKG_CONFIG_PATH=/net/homedirs/jeremys/ctl/lib/pkgconfig/ ./configure --prefix=/net/homedirs/jeremys/ctl
My apologies if this is a FAQ, but I searched and didn't find it addressed elsewhere.
I'm finding that the output of the ODT.Academy.Rec709_100nits_dim.a1.0.1.ctl, when displayed on a late-model consumer HDTV, is significantly different from the output of ODT.Academy.RGBmonitor_D60sim_100nits_dim.a1.0.1.ctl viewed on a PC monitor. I'm able to make them match very closely if I change the Rec709 ODT to encode using the Rec.709 OETF (item 1.2 in BT.709; also item 1.2 in Appendix 2 of BT.1886) instead of the inverse BT.1886 EOTF.
The attached images (which should be viewed on an sRGB PC monitor) are very good representations of what I'm seeing on the TV.
Based on this, it seems to me that the Rec709 ODT should be using the Rec709 OETF. I understand that the standards specify a different (non-inverse) EOTF, but perhaps in practice TV manufacturers have adopted an EOTF that is intended to reproduce Rec709-encoded content?
Thanks!
https://github.com/hpd/OpenColorIO-Configs/tree/master/aces_1.0.1
It strikes me that the luma coefficients should be updated to match the ACES primaries in the config.ocio file?
"acesLog_to_lin" and "lin_to_acesLog" transforms defined in ACESlib.Transform_Common.a1.0.0.ctl and referenced in ACEScsc.ACES_to_ACEScc.a1.0.0.ctl and ACEScsc.ACEScc_to_ACES.a1.0.0.ctl should be renamed "acesCc_to_lin" and "lin_to_acesCc". The transforms should also be updated to use the formula defined in the acesCc document including compression of subnormals.
I'm not following why this line is in the 709 ODT (I was using the "Full" one and noticed it there)
float linearCV[3] = bpc_cinema_fwd( rgbPost);
I would think it would be the video one so the right luminance defaults would be used.
float linearCV[3] = bpc_video_fwd( rgbPost);
Update: April 29, Appears same issue exists with 2020 ODTs. I think should be "bpc_video_fwd" not "bpc_cinema_fwd" so that the 709 or 2020 ODT uses the proper setting for the ODT tone curve.
Best Regards,
Bill M
// BUG 1:
// Uncommenting the following results in a compilation error of:
//ImportError: Reference-counted pointer assignment failed; the left-hand and right-hand side types are incompatible (PKN3Ctl8RcObjectE, N3Ctl16SimdBinaryOpNodeE).
// const float COEFSX[ 9] = {
// 5.6648, 5.3418, 4.3937, 3.1748, 1.9663, 0.95155, 0.22244, -0.22149, -0.47615
// };
// const float KNOT_DENSX[ 8] = {
// ( COEFSX[ 0] + COEFSX[ 1]) / 2.,
// ( COEFSX[ 1] + COEFSX[ 2]) / 2.,
// ( COEFSX[ 2] + COEFSX[ 3]) / 2.,
// ( COEFSX[ 3] + COEFSX[ 4]) / 2.,
// ( COEFSX[ 4] + COEFSX[ 5]) / 2.,
// ( COEFSX[ 5] + COEFSX[ 6]) / 2.,
// ( COEFSX[ 6] + COEFSX[ 7]) / 2.,
// ( COEFSX[ 7] + COEFSX[ 8]) / 2.
// };
const float COEFS0 = 5.6648;
const float COEFS1 = 5.3418;
const float COEFS2 = 4.3937;
const float COEFS3 = 3.1748;
const float COEFS4 = 1.9663;
const float COEFS5 = 0.95155;
const float COEFS6 = 0.22244;
const float COEFS7 = -0.22149;
const float COEFS8 = -0.47615;
const float COEFS[ 9] = { COEFS0, COEFS1, COEFS2, COEFS3, COEFS4, COEFS5, COEFS6,
COEFS7, COEFS8 };
const float KNOT_DENS[ 8] = {
( COEFS0 + COEFS1) / 2.,
( COEFS1 + COEFS2) / 2.,
( COEFS2 + COEFS3) / 2.,
( COEFS3 + COEFS4) / 2.,
( COEFS4 + COEFS5) / 2.,
( COEFS5 + COEFS6) / 2.,
( COEFS6 + COEFS7) / 2.,
( COEFS7 + COEFS8) / 2.
};
const float KNOTS[ 8] = { -3., -2.5, -2., -1.5, -1., -0.5, 0., 0.5 };
const float KNOT_DEL = 0.5;
const unsigned int LAST_KNOT = KNOTS.size - 1;
const float INDEX_MAP[ 8] = { 0., 1., 2., 3., 4., 5., 6., 7. };
const float NEG_SLOPE = 0.01;
const float HI_SLOPE = -0.5;
const float LO_SLOPE1 = 0.0254;
const float LO_BREAK1 = LO_SLOPE1 * 1e-5;
const float LO_SLOPE2 = ( -log10( LO_BREAK1) - KNOT_DENS[ 0]) / ( -5 - KNOTS[ 0]);
const float M[ 3][ 3] = {
{ 0.5, -1.0, 0.5 },
{ -1.0, 1.0, 0.0 },
{ 0.5, 0.5, 0.0 }
};
float rrt_shaper_fwd( float x)
{
float y;
if ( x <= 0.0)
y = x * NEG_SLOPE;
else if ( x <= 1e-5)
y = x * LO_SLOPE1;
else {
float logh = log10( x);
float dens;
if ( logh <= KNOTS[ 0])
dens = KNOT_DENS[ 0] - ( KNOTS[ 0] - logh) * LO_SLOPE2;
else if ( logh >= KNOTS[ LAST_KNOT])
dens = KNOT_DENS[ LAST_KNOT] + ( logh - KNOTS[ LAST_KNOT]) * HI_SLOPE;
else {
int j;
// BUG 2:
// This method will occasionally fail (apparently at random) with a message like:
// ./rrt_shaper_fwd.ctl:74: Array index out of range (index = -1291845632, array size = 8).
// but otherwise gives correct results.
if ( 0) {
j = 0;
while ( logh > KNOTS[ j + 1]) {
j = j + 1;
}
}
// This theoretically equivalent method always works.
else {
j = lookup1D( INDEX_MAP, KNOTS[ 0], KNOTS[ LAST_KNOT], logh);
}
float t = ( logh - KNOTS[ j]) / KNOT_DEL;
float monomials[ 3] = { t * t, t, 1. };
float coef_vec[ 3] = { COEFS[ j], COEFS[ j + 1], COEFS[ j + 2]};
dens = dot_f3_f3( coef_vec, mult_f3_f33( monomials, M));
}
y = pow10( -dens);
}
return y;
}
void main(
input varying float rIn,
input varying float gIn,
input varying float bIn,
input varying float aIn,
output varying float rOut,
output varying float gOut,
output varying float bOut,
output varying float aOut
)
{
rOut = rrt_shaper_fwd( rIn);
gOut = rrt_shaper_fwd( gIn);
bOut = rrt_shaper_fwd( bIn);
aOut = aIn;
}
I would love to see a DPX file within the ACES test file corpus containing ADX encoding with the constrained field values described in SMPTE ST 268:2014. I ask because several archives currently employ a two-step workflow in which a raw DPX file is created via film scanning, followed by an additional "restored DPX" for mastering (See: http://www.digitizationguidelines.gov/guidelines/FADGI_FilmScan_PWS-SOW_20150908.pdf).
Is anyone else getting negative values when rolling 0.0 footage through the ACES LMT Shaper to Linear?
Lowest value in the 1D LUT is 0.000175781256985, yet using ocioconvert on an EXR I see -0.01746?
Follow up on that conversation: https://groups.google.com/forum/#!topic/academyaces/i69NtrS7dEI
I should have probably read better, but I think it would be worth mentioning to account for flare in the Annex B computations.
The function should interpolate to find ZI, the values of the underlying 2-D function Z at the points XI and YI. Vectors X and Y specify the points at which the data Z is given.
Similarly to interpolate1D, this function should use linear interpolation.
Inputs: X,Y,Z,XI,YI
Outputs: ZI
Here is some rough code that should, I think, do the job. I'm not sure if the declaration, or later the calculation, of the size of the input vectors is valid.
float
interpolate2D
(const float X[],
const float Y[],
const float Z[],
float XI,
float YI)
{
// Check sizes of inputs
size_t n = sizeof(X);
size_t m = sizeof(Y);
size_t nZ = sizeof(Z[0]);
size_t mZ = sizeof(Z);
if (n != nZ)
return 0;
if (m != mZ)
return 0;
if ( (n < 1) || (m < 1) )
return 0;
// Find xLow and xHigh
float xMin = X[0]; float xMax = X[n-1];
int xLowIndex; int xHighIndex;
float xPercent;
if (XI > xMin && XI < xMax) // XI is within vector X
{
int j = 0;
while (XI > X[j])
{
j = j + 1;
xLowIndex = j-1;
xHighIndex = j;
}
xPercent = (XI - X[xLowIndex]) / (X[xHighIndex] - X[xLowIndex]);
}
else if (XI <= xMin) // XI is lower than minimum of vector X, use low edge
{
xLowIndex = 0;
xHighIndex = 0;
xPercent = 1.0;
}
else if (XI >= xMax) // XI higher than maximum of vector X, use high edge
{
xLowIndex = n-1;
xHighIndex = n-1;
xPercent = 1.0;
}
else // XI is a NaN
{
return 0;
}
float yMin = Y[0]; float yMax = Y[m-1];
int yLowIndex; int yHighIndex;
float yPercent;
if (YI > yMin && YI < yMax) // YI is within vector Y
{
int j = 0;
while (YI > Y[j])
{
j = j + 1;
yLowIndex = j-1;
yHighIndex = j;
}
yPercent = (YI - Y[yLowIndex]) / (Y[yHighIndex] - Y[yLowIndex]);
}
else if (YI <= yMin) // YI is lower than minimum of vector Y, use low edge
{
yLowIndex = 0;
yHighIndex = 0;
yPercent = 1.0;
}
else if (YI >= yMax) // YI higher than maximum of vector Y, use high edge
{
yLowIndex = m-1;
yHighIndex = m-1;
yPercent = 1.0;
}
else // YI is a NaN
{
return 0;
}
float val1 = (Z[yLowIndex][xHighIndex] - Z[yLowIndex][xLowIndex]) * xPercent + Z[yLowIndex][xLowIndex];
float val2 = (Z[yHighIndex][xHighIndex] - Z[yHighIndex][xLowIndex]) * xPercent + Z[yHighIndex][xLowIndex];
return (val2 - val1) * yPercent + val1;
}
Integrate code for loading CTL modules directory from memory.
Code provided by John Hurst.
diff -u -r ctl-1.4.1-orig/IlmCtl/CtlInterpreter.cpp ctl-1.4.1/IlmCtl/CtlInterpreter.cpp
--- ctl-1.4.1-orig/IlmCtl/CtlInterpreter.cpp 2006-12-14 14:43:55.000000000 -0800
+++ ctl-1.4.1/IlmCtl/CtlInterpreter.cpp 2011-11-26 15:42:19.000000000 -0800
@@ -235,17 +235,17 @@
void
-Interpreter::loadModule (const string &moduleName)
+Interpreter::loadModule (const string &moduleName, const string &fileName, const string &moduleSource)
{
debug ("Interpreter::loadModule (moduleName = " << moduleName << ")");
Lock lock (_data->mutex);
- loadModuleRecursive (moduleName);
+ loadModuleRecursive (moduleName, fileName, moduleSource);
}
void
-Interpreter::loadModuleRecursive (const string &moduleName)
+Interpreter::loadModuleRecursive (const string &moduleName, const string &fileName, const string &moduleSource)
{
debug ("Interpreter::loadModuleRecursive "
"(moduleName = " << moduleName << ")");
@@ -256,25 +256,45 @@
return;
}
+ Module *module = 0;
+ LContext *lcontext = 0;
+ istream *input = 0;
+ string realFileName = fileName.empty() ? findModule (moduleName) : fileName;
+
//
- // Using the module search path, locate the file that contains the
- // source code for the module. Open the file.
+ // set up the source code string for parsing.
//
- string fileName = findModule (moduleName);
- ifstream file (fileName.c_str());
-
- if (!file)
+ if (!moduleSource.empty())
{
- THROW_ERRNO ("Cannot load CTL module \"" << moduleName << "\". "
- "Opening file \"" << fileName << "\" for reading "
- "failed (%T).");
+ debug ("\tloading from source");
+
+ stringstream *tmp_strm = new stringstream;
+ (*tmp_strm) << moduleSource;
+ input = tmp_strm;
}
+ else
+ {
+ //
+ // Using the module search path, locate the file that contains the
+ // source code for the module. Open the file.
+ //
- debug ("\tloading from file \"" << fileName << "\"");
+ ifstream *tmp_strm = new ifstream;
+ tmp_strm->open (realFileName.c_str());
- Module *module = 0;
- LContext *lcontext = 0;
+ if (!*tmp_strm)
+ {
+ THROW_ERRNO ("Cannot load CTL module \"" << moduleName << "\". "
+ "Opening file \"" << realFileName << "\" for reading "
+ "failed (%T).");
+ }
+
+ debug ("\tloading from file \"" << realFileName << "\"");
+ input = tmp_strm;
+ }
+
+ assert(input);
try
{
@@ -282,9 +302,9 @@
// Create a Module, an Lcontext and a Parser
//
- module = newModule (moduleName, fileName);
+ module = newModule (moduleName, realFileName);
_data->moduleSet.addModule (module);
- lcontext = newLContext (file, module, _data->symtab);
+ lcontext = newLContext (*input, module, _data->symtab);
Parser parser (*lcontext, *this);
//
diff -u -r ctl-1.4.1-orig/IlmCtl/CtlInterpreter.h ctl-1.4.1/IlmCtl/CtlInterpreter.h
--- ctl-1.4.1-orig/IlmCtl/CtlInterpreter.h 2006-12-12 14:59:03.000000000 -0800
+++ ctl-1.4.1/IlmCtl/CtlInterpreter.h 2011-11-26 10:18:13.000000000 -0800
@@ -87,7 +87,9 @@
// Load a module, test if a given module has already been loaded
//--------------------------------------------------------------
- void loadModule (const std::string &moduleName);
+ void loadModule (const std::string &moduleName,
+ const std::string &fileName = "",
+ const std::string &moduleSource = "");
bool moduleIsLoaded (const std::string &moduleName) const;
@@ -159,7 +161,9 @@
const std::string &moduleName);
void loadModuleRecursive
- (const std::string &moduleName);
+ (const std::string &moduleName,
+ const std::string &fileName = "",
+ const std::string &moduleSource = "");
bool moduleIsLoadedInternal
(const std::string &moduleName) const;
We need to add the shaper transforms into the repo.
In the file “aces_to_acesProxy10.ctl” at line 50, it is currently:
aces[1] = CVmin;
but it should almost certainly be instead:
acesProxy[1] = CVmin;
The similar “aces_to_acesProxy12.ctl” file does not have this error.
The page http://www.oscars.org/science-technology/sci-tech-projects/aces has a dead link to the ACES 1.0 OpenColorIO links here https://github.com/hpd/OpenColorIO-Configs/tree/master/aces_1.0.0
All the video ODTs are using the CINEMA_BLACK and CINEMA_WHITE values in the Y_2_linCV conversion.
It has been suggested that the black value used for the video ODTs should be 0.0048 (for a 10000:1 dynamic range device) instead of the CINEMA_BLACK value of 0.02 (2400:1 dynamic range).
Email address in transforms/ctl/idt/vendorSupplied/README.md should be [email protected]
ctlrender -ctl rrt_ut11.ctl -ctl p3d60.ctl cmstestpattern_logallocation_input.exr /tmp/output_ncf.exr
There is obvious garbage in the frame, in the lower half of the image. Alex can repeat this issue.
exrimage is 32x32x32 lattice, as written out of nuke (using an inverse lg2 allocation from -8.5 to 5.0 stops)
file format version: 2, flags 0x0
channels (type chlist):
B, 32-bit floating-point, sampling 1 1
G, 32-bit floating-point, sampling 1 1
R, 32-bit floating-point, sampling 1 1
compression (type compression): zip, individual scanlines
dataWindow (type box2i): (0 0) - (1273 1266)
displayWindow (type box2i): (0 0) - (1273 1266)
HDR ODTs that had been named "P3D60_Xnits_PQ" should be renamed "P3D60_PQ_Xnits".
I've included Canon's EOS C300 IDT Ver 1.0 for reference:
https://www.dropbox.com/sh/gq9cbwtnwlah36n/HoTRTyKWYo
First of all, I realize that the C300's IDT is not maintained here but I still think it is worth discussing. In both CTLs, after converting the 0-1 RGB input values to RGB IRE values (iR
, iG
, and iB
), they convert the RGB IRE values using some sort of 3x19 matrix that they label ACES conversion matrix1 and then process those values through CanonLog_to_linear(float clog_ire);
. The last step is transforming the scene-linear RGB values with ACES conversion matrix2. Does anyone know what is going on with "ACES conversion matrix1" and is this an appropriate label for the matrix?
// CodeValue to IRE, ire = (cv-64)/(940-64)
float iR;
float iG;
float iB;
iR = (rIn*1023 - 64) / 876;
iG = (gIn*1023 - 64) / 876;
iB = (bIn*1023 - 64) / 876;
// ACES conversion matrix1 (3x19)
float pmtx[3];
pmtx[0] = 0.963803004454899 * iR -0.160722202570655 * iG +0.196919198115756 * iB
+2.03444685639819 * iR*iG -0.442676931451021 * iG*iB -0.407983781537509 * iB*iR
-0.640703323129254 * iR*iR -0.860242798247848 * iG*iG +0.317159977967446 * iB*iB
-4.80567080102966 * iR*iR*iG +0.27118370397567 * iR*iR*iB +5.1069005049557 * iR*iG*iG
+0.340895816920585 * iR*iG*iB -0.486941738507862 * iR*iB*iB -2.23737935753692 * iG*iG*iB +1.96647555251297 * iG*iB*iB
+1.30204051766243 * iR*iR*iR -1.06503117628554 * iG*iG*iG -0.392473022667378 * iB*iB*iB;
pmtx[1] = -0.0421935892309314 * iR +1.04845959175183 * iG -0.00626600252090315 * iB
-0.106438896887216 * iR*iG +0.362908621470781 * iG*iB +0.118070700472261 * iB*iR
+0.0193542539838734 * iR*iR -0.156083029543267 * iG*iG -0.237811649496433 * iB*iB
+1.67916420582198 * iR*iR*iG -0.632835327167897 * iR*iR*iB -1.95984471387461 * iR*iG*iG
+0.953221464562814 * iR*iG*iB +0.0599085176294623 * iR*iB*iB -1.66452046236246 * iG*iG*iB +1.14041188349761 * iG*iB*iB
-0.387552623550308 * iR*iR*iR +1.14820099685512 * iG*iG*iG -0.336153941411709 * iB*iB*iB;
pmtx[2] = 0.170295033135028 * iR -0.0682984448537245 * iG +0.898003411718697 * iB
+1.22106821992399 * iR*iG +1.60194865922925 * iG*iB +0.377599191137124 * iB*iR
-0.825781428487531 * iR*iR -1.44590868076749 * iG*iG -0.928925961035344 * iB*iB
-0.838548997455852 * iR*iR*iG +0.75809397217116 * iR*iR*iB +1.32966795243196 * iR*iG*iG
-1.20021905668355 * iR*iG*iB -0.254838995845129 * iR*iB*iB +2.33232411639308 * iG*iG*iB -1.86381505762773 * iG*iB*iB
+0.111576038956423 * iR*iR*iR -1.12593315849766 * iG*iG*iG +0.751693186157287 * iB*iB*iB;
// Canonlog to linear
float lin[3];
lin[0] = CanonLog_to_linear( pmtx[0]);
lin[1] = CanonLog_to_linear( pmtx[1]);
lin[2] = CanonLog_to_linear( pmtx[2]);
// ACES conversion matrix2
float aces[3];
aces[0] = Clip(0.566996399 * lin[0] +0.365079418 * lin[1] + 0.067924183 * lin[2]);
aces[1] = Clip(0.070901044 * lin[0] +0.880331008 * lin[1] + 0.048767948 * lin[2]);
aces[2] = Clip(0.073013542 * lin[0] -0.066540862 * lin[1] + 0.99352732 * lin[2]);
rOut = aces[0];
gOut = aces[1];
bOut = aces[2];
aOut = aIn;
Currently there is no officially supported build mechanism for MS Windows
I has been suggested the using cmake might be an appropriate strategy for simplifying cross platform compiling.
This issue was originally submitted by Jon McElvain.
Split from another issue for tracking purposes.
When processing a large sequence of images, available memory is slowly consumed until zero resources are available.
This is suggestive of a low level memory leak.
rdt_dcdm.ctl currently clips XYZ values to 0-1 range.
// Clip data to range zero to one
XYZ[0] = clip_0_to_1( XYZ[0] );
XYZ[1] = clip_0_to_1( XYZ[1] );
XYZ[2] = clip_0_to_1( XYZ[2] );
This is incorrect as XYZ values should be allowed to range over 1.0.
The XYZ values less than 0 should be clipped to 0.
The current Rec709 ODT crushes blacks. The Rec709 ODT was intended to target the recommendation in Appendix 1 of ITU-R BT.1886.
Currently this code reads:
// ITU Proposal EOTF
const float gamma = 2.4;
float aa = pow( 1.0, ( 1.0 / gamma)) - pow( 0.0005, ( 1.0 / gamma));
float bb = pow( 0.0005, ( 1.0 / gamma));
The screen luminance for black should be set to 0.0 to target a CRT with a contrast ratio of ~2000:1. The code is also unclear because screen luminance for black and white are not defined as constants. I recommend the proposed code below:
// Per ITU-R BT.1886 EOTF
const float GAMMA = 2.4;
const float L_B = 0.000; // screen luminance for black
const float L_W = 1.0; // screen luminance for white
// Note: L_B and L_W may be modified to luminance of an actual CRT.
// Per RECOMMENDATION ITU-R BT.1886 - Appendix 1. L_B has been set to 0.0
// targeting a CRT with a contrast ratio of 2000:1.
const float A = pow( pow( L_W, ( 1.0 / GAMMA)) - pow( L_B, ( 1.0 / GAMMA)), GAMMA);
const float B = pow( L_B, ( 1.0 / GAMMA)) / ( pow( L_W, ( 1.0 / GAMMA)) - pow( L_B, (1.0/GAMMA)));
The follow examples cause a segmentation fault
/* ============ CONSTANTS ============ */
const Chromaticities ACESChromaticities =
{
{ 0.73470, 0.26530},
{ 0.00000, 1.00000},
{ 0.00010, -0.07700},
{ 0.32168, 0.33767}
};
// Declare a const - No Seg Fault
// const float WHITE[3] = {0.32168, 0.33767, 1.0};
// Declare a const using values from Chromaticities data type and a float - Seg Fault
const float WHITE[3] = {ACESChromaticities.white[0], ACESChromaticities.white[1], 1.0};
// Declare a const using values pulled from Chromaticities data type without an additional float - Seg Fault
// const float WHITE[2] = {ACESChromaticities.white[0], ACESChromaticities.white[1]};
// Declare a const from floats pulled from Chromaticities placed into a float before the creation of the final array - Seg Fault
// const float WHITE_x = ACESChromaticities.white[0];
// const float WHITE_y = ACESChromaticities.white[1];
// const float WHITE[2] = {WHITE_x, WHITE_y};
/* ============ ODT - Main Algorithm ============ */
void main
(
input varying float rIn,
input varying float gIn,
input varying float bIn,
input varying float aIn,
output varying float rOut,
output varying float gOut,
output varying float bOut,
output varying float aOut)
{
// Do the same things here and no seg fault
// float WHITE[3] = {0.32168, 0.33767, 1.0};
// float WHITE[3] = {ACESChromaticities.white[0], ACESChromaticities.white[1], 1.0};
// float WHITE[2] = {ACESChromaticities.white[0], ACESChromaticities.white[1]};
// float WHITE_x = ACESChromaticities.white[0];
// float WHITE_y = ACESChromaticities.white[1];
// float WHITE[2] = {WHITE_x, WHITE_y};
print(WHITE[0], WHITE[1]);
}
The version of CTL used within ctlrender may not be in synchronization with the official CTL libraries. These differences should be reconciled pushing useful new features back to the main CTL source.
// BUG 1:
// Uncommenting the following results in a compilation error of:
//ImportError: Reference-counted pointer assignment failed; the left-hand and right-hand side types are incompatible (PKN3Ctl8RcObjectE, N3Ctl16SimdBinaryOpNodeE).
// const float COEFSX[ 9] = {
// 5.6648, 5.3418, 4.3937, 3.1748, 1.9663, 0.95155, 0.22244, -0.22149, -0.47615
// };
// const float KNOT_DENSX[ 8] = {
// ( COEFSX[ 0] + COEFSX[ 1]) / 2.,
// ( COEFSX[ 1] + COEFSX[ 2]) / 2.,
// ( COEFSX[ 2] + COEFSX[ 3]) / 2.,
// ( COEFSX[ 3] + COEFSX[ 4]) / 2.,
// ( COEFSX[ 4] + COEFSX[ 5]) / 2.,
// ( COEFSX[ 5] + COEFSX[ 6]) / 2.,
// ( COEFSX[ 6] + COEFSX[ 7]) / 2.,
// ( COEFSX[ 7] + COEFSX[ 8]) / 2.
// };
const float COEFS0 = 5.6648;
const float COEFS1 = 5.3418;
const float COEFS2 = 4.3937;
const float COEFS3 = 3.1748;
const float COEFS4 = 1.9663;
const float COEFS5 = 0.95155;
const float COEFS6 = 0.22244;
const float COEFS7 = -0.22149;
const float COEFS8 = -0.47615;
const float COEFS[ 9] = { COEFS0, COEFS1, COEFS2, COEFS3, COEFS4, COEFS5, COEFS6,
COEFS7, COEFS8 };
const float KNOT_DENS[ 8] = {
( COEFS0 + COEFS1) / 2.,
( COEFS1 + COEFS2) / 2.,
( COEFS2 + COEFS3) / 2.,
( COEFS3 + COEFS4) / 2.,
( COEFS4 + COEFS5) / 2.,
( COEFS5 + COEFS6) / 2.,
( COEFS6 + COEFS7) / 2.,
( COEFS7 + COEFS8) / 2.
};
const float KNOTS[ 8] = { -3., -2.5, -2., -1.5, -1., -0.5, 0., 0.5 };
const float KNOT_DEL = 0.5;
const unsigned int LAST_KNOT = KNOTS.size - 1;
const float INDEX_MAP[ 8] = { 0., 1., 2., 3., 4., 5., 6., 7. };
const float NEG_SLOPE = 0.01;
const float HI_SLOPE = -0.5;
const float LO_SLOPE1 = 0.0254;
const float LO_BREAK1 = LO_SLOPE1 * 1e-5;
const float LO_SLOPE2 = ( -log10( LO_BREAK1) - KNOT_DENS[ 0]) / ( -5 - KNOTS[ 0]);
const float M[ 3][ 3] = {
{ 0.5, -1.0, 0.5 },
{ -1.0, 1.0, 0.0 },
{ 0.5, 0.5, 0.0 }
};
float rrt_shaper_fwd( float x)
{
float y;
if ( x <= 0.0)
y = x * NEG_SLOPE;
else if ( x <= 1e-5)
y = x * LO_SLOPE1;
else {
float logh = log10( x);
float dens;
if ( logh <= KNOTS[ 0])
dens = KNOT_DENS[ 0] - ( KNOTS[ 0] - logh) * LO_SLOPE2;
else if ( logh >= KNOTS[ LAST_KNOT])
dens = KNOT_DENS[ LAST_KNOT] + ( logh - KNOTS[ LAST_KNOT]) * HI_SLOPE;
else {
int j;
// BUG 2:
// This method will occasionally fail (apparently at random) with a message like:
// ./rrt_shaper_fwd.ctl:74: Array index out of range (index = -1291845632, array size = 8).
// but otherwise gives correct results.
if ( 0) {
j = 0;
while ( logh > KNOTS[ j + 1]) {
j = j + 1;
}
}
// This theoretically equivalent method always works.
else {
j = lookup1D( INDEX_MAP, KNOTS[ 0], KNOTS[ LAST_KNOT], logh);
}
float t = ( logh - KNOTS[ j]) / KNOT_DEL;
float monomials[ 3] = { t * t, t, 1. };
float coef_vec[ 3] = { COEFS[ j], COEFS[ j + 1], COEFS[ j + 2]};
dens = dot_f3_f3( coef_vec, mult_f3_f33( monomials, M));
}
y = pow10( -dens);
}
return y;
}
void main(
input varying float rIn,
input varying float gIn,
input varying float bIn,
input varying float aIn,
output varying float rOut,
output varying float gOut,
output varying float bOut,
output varying float aOut
)
{
rOut = rrt_shaper_fwd( rIn);
gOut = rrt_shaper_fwd( gIn);
bOut = rrt_shaper_fwd( bIn);
aOut = aIn;
}
It doesn't seem that there is an Adobe RGB 1998 transfer curve LUT defined in the configurations. Is it by design that the 2 51/256 curve was left out for loading Adobe RGB encoded imagery @hpd?
The link for reference images found at https://www.dropbox.com/sh/lj9x6cyd5t56tha/AACmQNROIc2kNIg5e1snnhg2a?dl=0 is 404 / not found.
The dropbox link to reference images in the master/images/README.md is broken. The dev branch one works though.
Sony IDTs tagged with the camera name should be renamed as SLog1 SGamut, SLog2 SGamut
It seems like there may be benefit to attaching the source code for ctlrender dependancies to their source repositories. This may be doable with git submodules. We should consider the pros and cons of this approach in implement in appropriate.
I'd like to use portions of the Python configuration builders in the OpenColorIO ACES configurations repository, but there is no attached license for this.
Confirmation that the broad license in this parent repository applies to @hpd's ACES official configurations?
While playing with some acesLog transformations I found a problem acesLog16i_to_aces and aces_to_acesLog16i ctl files. The last converts aces to logarithmic values in the range of 0.0 to 1.0 which seem reasonable for me when looking at the way 16 bit tiffs are written. However the reverse transform (acesLog16i_to_aces) expects values in the range 0 to 65535 (max for 16 bit integer).
More analysis on this on the Google group: https://groups.google.com/forum/#!topic/academyaces/VD7Yd0Yh7Sg
Typos in all references to SMPTE ST2084, including HDR transform directory name, filenames, and header comments.
This is a nitpick, but the reference images zip file that's hosted on Dropbox contains some lowercase folder names: "aces", "lmt", "oces", "odt", "rrt". These don't match the uppercase Dropbox folders, which are also listed in images/README.md.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.