Giter Club home page Giter Club logo

aces-dev's Introduction

Academy Color Encoding System Developer Resources

The Academy Color Encoding System (ACES) is a set of components that facilitates a wide range of motion picture and television workflows while eliminating the ambiguity of legacy file formats. The system is designed to support both all-digital and hybrid film-digital motion picture workflows.

The basic ACES components are:

  • Color encoding and metric specifications, file format specifications, color transformations, and an open source reference implementation
  • A set of reference images and calibration targets for film scanners and recorders
  • Documentation on the system and software tools can be found in 'aces-docs'

This toolkit is intended to serve as a distribution mechanism for key components of the system, including the reference implementation transforms, reference images, and documentation.

Package Contents

  • formats/ - ACES file formats code and examples
  • images/ - "golden" images created using the reference implementation transforms
  • transforms/ - ACES reference implementation transforms

Changes from Previous Release

Though the "master" branch is 1.3, the current major version of ACES remains 1. The 1.3 update adds transforms but does not change the look or modify the existing core transforms (beyond addressing reported bugs and/or inconsequential formatting/whitespace changes).

The dev branch always reflects the "bleeding edge" and indicates new features or updates that will ultimately be rolled into a future release version of ACES. Improvements are staged on the dev branch for testing as they become available.

Included in ACES 1.3:

  • New Features:
    • Add gamut compression transform to assist with remapping problematic colorimetry into AP1
    • Update AMF schema with refinements by the AMF Implementation Working Group
    • Add CSC transforms for Sony Venice
  • Bug fixes:
    • Remove clamp in ACES to ACEScg conversion transform
    • Correct typos in the TransformIDs of CSC files added in v1.2
  • Other:
    • Relocate ACES documentation to its own repository
    • Rename outputTransforms directory to outputTransform (singular)
    • Add color primary subdirectories to outputTransform directory to be consistent with the odt directory
    • Update reference images

For a more detailed list of changes see the CHANGELOG and the commit history.

Notes on the gamut compression transform

The gamut compression transform is the result of the work of the Gamut Mapping Working Group, to create a more robust solution to issues with out of gamut colors and the resulting artifacts (loss of texture, intensification of color fringes). The delivered gamut compression transform performs well with wide gamut, high dynamic range, scene referred content and is robust and invertible.

The gamut compression replaces the simple and less robust LMT.Academy.BlueLightArtifactFix.ctl. The ACES gamut compression transform has numerous advantages over the BlueLightArtifactFix LMT. In particular, the gamut compression transform avoids changing colors that are well inside the destination gamut. Only colors that are out of gamut or very near the gamut boundary are affected.

As of this release, the Gamut Compression Implementation Working Group is working to provide recommendations and guidance to vendors to implement this transform directly their in products.

For those looking for more detail, the Gamut Mapping Working Group delivered a report to accompany the technical deliverable.

Notes on the updated AMF specification

ACES 1.2 included the release of the Academy Metadata Format (AMF) specification. Since that time a working group has been formed to provide guidance to vendors on the implementation of AMF into products and end-user guidance on production usage. In the process of testing and working with the initial specification, the group suggested extensions to the AMF specification to make it more useful in meeting specific use cases. ACES 1.3 includes an updated AMF specification and associated schema that allow all transforms to now be referenced by UUID, relative file path, or TransformID.

Versioning

The links to the current and all past versions of the ACES Developer Resources can be found at https://github.com/ampas/aces-dev/releases.

Source code is version controlled using the git version control system and hosted on GitHub at https://github.com/ampas/aces-dev/.

File names conform to the ACES System Versioning Specification. Details can be found in the Academy Specification "S-2014-002 - Academy Color Encoding System - Versioning System" included in documents/

Branch Structure

Master Branch

The current official release version of ACES can always be found at the HEAD of the master branch. The master branch contains no intermediate commits and all commits on the master branch are tagged to represent a release of ACES.

Dev Branch

Intermediate commits between releases are staged on the dev branch. Commits staged on the dev branch, but not yet merged into the master, should be considered as "planned for inclusion" in the next release version. These represent the "bleeding edge" and development and, in turn, pull requests should be based against the dev branch.

Hotfixes Branch

In some instances it may be necessary to create a hotfixes branch. The hotfixes branch will include critical fixes for bugs found in a particular release. Hotfixes should only be implemented by developers if the bug they are intending to correct is encountered in the course of production and is deemed to be a barrier to using a particular ACES release. Hotfixes, once fully tested, will be merged into the dev branch, and ultimately the master.

Prerequisites

Color Transformation Language

Color Transformation Language (CTL) can be downloaded from https://github.com/ampas/CTL

License Terms for Academy Color Encoding System Components

Academy Color Encoding System (ACES) software and tools are provided by the Academy under the following terms and conditions: A worldwide, royalty-free, non-exclusive right to copy, modify, create derivatives, and use, in source and binary forms, is hereby granted, subject to acceptance of this license.

Copyright 2019 Academy of Motion Picture Arts and Sciences (A.M.P.A.S.). Portions contributed by others as indicated. All rights reserved.

Performance of any of the aforementioned acts indicates acceptance to be bound by the following terms and conditions:

  • Copies of source code, in whole or in part, must retain the above copyright notice, this list of conditions and the Disclaimer of Warranty.

  • Use in binary form must retain the above copyright notice, this list of conditions and the Disclaimer of Warranty in the documentation and/or other materials provided with the distribution.

  • Nothing in this license shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of A.M.P.A.S. or any contributors, except as expressly stated herein.

  • Neither the name "A.M.P.A.S." nor the name of any other contributors to this software may be used to endorse or promote products derivative of or based on this software without express prior written permission of A.M.P.A.S. or the contributors, as appropriate.

This license shall be construed pursuant to the laws of the State of California, and any disputes related thereto shall be subject to the jurisdiction of the courts therein.

Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER THAN A.M.P.A.S.,WHETHER DISCLOSED OR UNDISCLOSED.

aces-dev's People

Contributors

aforsythe avatar balazer avatar jgoldstone avatar kelsolaar avatar kgboreham avatar nick-shaw avatar scoopxyz avatar scottdyer avatar selfshadow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aces-dev's Issues

DCDM RDT Clips XYZ values incorrectly

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.

Homebrew's bottled CTL 1.5.2 links against non-current IlmBase (Iex)

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

################################################################## 100.0%

==> 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 %

Typo in aces_to_acesProxy10 transform

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.

Segmentation Fault from declaration of a const using values from chromaticities data type

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]);

}

Potential for underflow and negatives in logical tests

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.

Rec709 ODT EOTF error

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))); 

Integrate code for loading CTL modules directly from memory

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;

Variable incorrectly being classified as non-varying rather than varying

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.)

ACES Shaper LMT negative values via OCIO?

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?

Cannot do a local install

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 forinstall-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

"Video" ODTs might be using incorrect assumed black luminance

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).

CTL version synchronization

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.

Rename Sony IDTs

Sony IDTs tagged with the camera name should be renamed as SLog1 SGamut, SLog2 SGamut

Should bpc_video_fwd be used with 709 ODT not (bpc_cinema_fwd)?

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

Incorrect matrix in utilities.ctl

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.

Rec.709 ODT looks incorrect on consumer HDTVs

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.

bt1886_on_tv
rec709_on_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!

correctness bug in ctl render

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)

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).

// 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;
}

Attach ctlrender prereqs to their source using submodules?

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.

HDR ODTs producing NaNs

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

  1. Convert lutimage to log2 shaper space
    ctlrender -ctl wgr9/aces-dev/transforms/ctl/logShaper/logShaper16i_to_aces_param.ctl -force -input_scale 1.0 -output_scale 1.0 -global_param1 aIn 1.0 -global_param1 middleGrey 0.18 -global_param1 minExposure -6.0 -global_param1 maxExposure 6.5 lutimage_33.uint16.tiff log2shaper.exr
  2. Apply RRT to log2 shaper lut image
    ctlrender -ctl wgr9/aces-dev/transforms/ctl/rrt/RRT.a1.0.0.ctl -force -input_scale 1.0 -output_scale 1.0 -global_param1 aIn 1.0 log2shaper.exr rrt.exr
  3. Apply the ODT to the log2 + RRT image
    ctlrender -ctl wgr9/aces-dev/transforms/ctl/odt/hdr_pq/ODT.Academy.P3D60_4000nits_PQ.a1.0.0.ctl -force -input_scale 1.0 -output_scale 1.0 -global_param1 aIn 1.0 rrt.exr log2Shaper.RRT.a1.0.0.Academy.P3D60_4000nits_PQ.a1.0.0.transformed.odt.exr

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

ACEScc transforms can produce NaNs

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."

Reference images folders are lowercase in Dropbox zip file

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.

ImportError: Reference-counted pointer assignment failed; the left-hand and right-hand side types are incompatible (PKN3Ctl8RcObjectE, N3Ctl16SimdBinaryOpNodeE).

// 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;
}

HDR ODTs improperly use cinema scaling

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.

Canon C300 IDT misunderstanding

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;

Broken relation between aces_to_acesLog16i output and acesLog16i_to_aces input

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

Add interpolate2D to CtlLookupTable.cpp

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;

}

Rename and update acesLog_to_lin and lin_to_acesLog transforms

"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.

Inconsistency in handling of 10-bit DPX/ADX data

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.

License Confirmation?

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.