Skip to content

Commit aefcff8

Browse files
garyoclaude
andcommitted
Add contrib/colour header-only colour-conversion library (#158)
Add ofxColourConvert.h, a small, dependency-free, header-only C++17 library that converts RGB triplets between the OFX native colourspaces and ACES2065-1, for plug-in and host authors who want exact conversions without a full OpenColorIO dependency. It is not a replacement for OCIO: display rendering and the display-referred/ADX/basic spaces are out of scope. Layout and integration: - contrib/colour/ofxColourConvert.h - the library, with README. - contrib/colour/tests/ - validation suite comparing every supported colourspace against OpenColorIO in both directions, plus round-trip and name-lookup checks. - CMake/Conan package just the header: an INTERFACE target OpenFX::ColourConvert that installs it, plus a ColourConvert Conan component. No test dependencies leak into the core package. - CI ships the header in the release tarball alongside include/, Support/, and HostSupport/ (under openfx/contrib/colour/). - The tests are built and run by pcons (which fetches OpenColorIO and GoogleTest via Conan). They are gated behind OFX_BUILD_COLOUR_TESTS (default OFF); when on, a CTest fixture delegates to pcons via uvx, so `ctest` runs them with zero install and no impact on the main build. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Gary Oberbrunner <garyo@darkstarsystems.com>
1 parent 9943cdf commit aefcff8

11 files changed

Lines changed: 1294 additions & 1 deletion

File tree

.github/workflows/build.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ jobs:
420420
# openfx/*.h
421421
# Support/*.h
422422
# HostSupport/*.h
423+
# contrib/colour/*.h
423424
# so e.g `#include <openfx/Support/foo.h>` works with `-I.../OpenFX/include`
424425
run: |
425426
mkdir -p Install/OpenFX/include/openfx
@@ -441,6 +442,10 @@ jobs:
441442
-cf - . \
442443
| tar -xf - -C Install/OpenFX/include/openfx/HostSupport/
443444
445+
# Header-only contrib library (header only; not the tests or build files)
446+
mkdir -p Install/OpenFX/include/openfx/contrib/colour
447+
cp contrib/colour/*.h Install/OpenFX/include/openfx/contrib/colour/
448+
444449
mkdir -p Install/OpenFX/lib
445450
find build -name 'lib*' -type f -exec cp {} Install/OpenFX/lib/ \;
446451

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,10 @@ if(OFX_SUPPORTS_OPENGLRENDER)
7878
endif()
7979

8080
# Build
81+
enable_testing()
8182
add_subdirectory(HostSupport)
8283
add_subdirectory(Support)
84+
add_subdirectory(contrib/colour)
8385
if(BUILD_EXAMPLE_PLUGINS)
8486
add_subdirectory(Examples)
8587
endif()

conanfile.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class openfx(ConanFile):
1414

1515
exports_sources = (
1616
"cmake/*",
17+
"contrib/*",
1718
"Examples/*",
1819
"HostSupport/*",
1920
"include/*",
@@ -33,7 +34,7 @@ class openfx(ConanFile):
3334
"spdlog/*:header_only": True,
3435
"fmt/*:header_only": True
3536
}
36-
37+
3738
def requirements(self):
3839
if self.options.use_opencl: # for OpenCL examples
3940
self.requires("opencl-icd-loader/2023.12.14")
@@ -62,6 +63,7 @@ def package(self):
6263
copy(self, "cmake/*", src=self.source_folder, dst=self.package_folder)
6364
copy(self, "LICENSE, README.md, INSTALL.md", src=self.source_folder, dst=self.package_folder)
6465
copy(self, "include/*.h", src=self.source_folder, dst=self.package_folder)
66+
copy(self,"contrib/colour/*.h", src=self.source_folder, dst=self.package_folder)
6567
copy(self,"HostSupport/include/*.h", src=self.source_folder, dst=self.package_folder)
6668
copy(self,"Support/*.h", src=self.source_folder, dst=self.package_folder)
6769
copy(self,"Support/Plugins/include/*.h", src=self.source_folder, dst=self.package_folder)
@@ -76,6 +78,8 @@ def package_info(self):
7678

7779
self.cpp_info.set_property("cmake_build_modules", [os.path.join("cmake", "OpenFX.cmake")])
7880
self.cpp_info.components["Api"].includedirs = ["include"]
81+
# Header-only colour-conversion convenience library (contrib/colour).
82+
self.cpp_info.components["ColourConvert"].includedirs = ["contrib/colour"]
7983
self.cpp_info.components["HostSupport"].libs = [i for i in libs if "OfxHost" in i]
8084
self.cpp_info.components["HostSupport"].includedirs = ["HostSupport/include"]
8185
self.cpp_info.components["HostSupport"].requires = ["expat::expat"]

contrib/colour/CMakeLists.txt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Copyright OpenFX and contributors to the OpenFX project.
2+
# SPDX-License-Identifier: BSD-3-Clause
3+
#
4+
# ofxColourConvert: a small, dependency-free, header-only C++17 library for
5+
# converting RGB triplets between the OFX native colourspaces and ACES2065-1.
6+
# It is a convenience for plug-in and host authors and is NOT a replacement
7+
# for OpenColorIO (see ofxColourConvert.h and README.md).
8+
9+
add_library(OfxColourConvert INTERFACE)
10+
add_library(OpenFX::ColourConvert ALIAS OfxColourConvert)
11+
12+
target_compile_features(OfxColourConvert INTERFACE cxx_std_17)
13+
target_include_directories(
14+
OfxColourConvert
15+
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
16+
$<INSTALL_INTERFACE:contrib/colour>)
17+
18+
# Header-only: install just the header alongside the rest of the OFX headers.
19+
install(FILES ofxColourConvert.h DESTINATION contrib/colour)
20+
21+
# The validation tests compare against OpenColorIO (heavy to build) and are
22+
# driven by pcons, which fetches OpenColorIO and GoogleTest via Conan. They are
23+
# off by default; enable with -DOFX_BUILD_COLOUR_TESTS=ON. The CTest entry just
24+
# delegates to pcons (run via uvx, so no install needed); see tests/README.md.
25+
option(OFX_BUILD_COLOUR_TESTS
26+
"Enable the contrib/colour OpenColorIO validation tests (run via pcons)" OFF)
27+
if(OFX_BUILD_COLOUR_TESTS)
28+
# A fixture builds the test with pcons (which fetches OpenColorIO + GoogleTest
29+
# via Conan); the test itself then just runs it. CTest runs the setup first.
30+
add_test(NAME colour_convert_build
31+
COMMAND uvx pcons
32+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
33+
set_tests_properties(colour_convert_build PROPERTIES FIXTURES_SETUP colour_convert)
34+
add_test(NAME colour_convert_vs_ocio
35+
COMMAND uvx pcons test
36+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
37+
set_tests_properties(colour_convert_vs_ocio PROPERTIES FIXTURES_REQUIRED colour_convert)
38+
endif()

contrib/colour/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
2+
<!-- Copyright OpenFX and contributors to the OpenFX project. -->
3+
# ofxColourConvert — header-only colour conversion
4+
5+
`ofxColourConvert.h` is a small, dependency-free, header-only C++17 library
6+
that converts RGB triplets between the OFX native colourspaces (see
7+
[`include/ofxColour.h`](../../include/ofxColour.h)) and the ACES2065-1 (AP0)
8+
reference colourspace.
9+
10+
It is a convenience for plug-in and host authors who want simple, exact colour
11+
conversions without taking on a full [OpenColorIO](https://opencolorio.org/)
12+
dependency. It is **not** a replacement for OCIO.
13+
14+
## Scope
15+
16+
Every supported space reduces to:
17+
18+
```
19+
code value --(transfer function)--> linear RGB --(3x3 matrix)--> AP0
20+
```
21+
22+
and back, so each conversion is colorimetrically exact and round-trips to
23+
ACES2065-1. The gamut matrices are derived at compile time from the published
24+
primaries using the Normalized Primaries Matrix plus a von Kries chromatic
25+
adaptation, matching the OCIO ACES config the OFX native colourspaces are based
26+
on.
27+
28+
Covered: the scene-referred working spaces (ACES2065-1, ACEScg, ACEScc/cct,
29+
linear Rec.709/Rec.2020/P3-D65) and the camera/texture encodings (ARRI, Sony,
30+
Canon, Panasonic, RED, Blackmagic, DaVinci, sRGB and pure-gamma texture
31+
spaces).
32+
33+
Out of scope (these need OCIO): display rendering (the ACES Output Transform /
34+
RRT+ODT), the display-referred `*_display` spaces, the ADX film-density
35+
encodings, and the abstract "basic" `ofx_*` spaces.
36+
37+
## Usage
38+
39+
It is header-only — just include it (C++17 or later required):
40+
41+
```cpp
42+
#include "ofxColourConvert.h"
43+
44+
using namespace ofx::colour;
45+
RGB c = { 0.2, 0.5, 0.8 }; // an S-Log3/S-Gamut3 pixel
46+
RGB aces = toACES2065_1(c, Colourspace::slog3_sgamut3);
47+
RGB out = fromACES2065_1(aces, Colourspace::lin_rec709_srgb);
48+
// or directly:
49+
RGB out2 = convert(c, Colourspace::slog3_sgamut3, Colourspace::lin_rec709_srgb);
50+
```
51+
52+
`colourspaceFromName()` maps the OFX colourspace identifier strings (e.g.
53+
`"slog3_sgamut3"`) to the `Colourspace` enum.
54+
55+
### CMake
56+
57+
The header is exposed as an `INTERFACE` target:
58+
59+
```cmake
60+
target_link_libraries(my_plugin PRIVATE OpenFX::ColourConvert)
61+
```
62+
63+
### Conan
64+
65+
The OpenFX package exposes it as the `ColourConvert` component
66+
(`openfx::ColourConvert`), header-only.
67+
68+
## Tests
69+
70+
The [`tests/`](tests) directory validates the header against OpenColorIO in
71+
both directions for every supported colourspace. They are off by default
72+
(OCIO is heavy to build); enable with `-DOFX_BUILD_COLOUR_TESTS=ON`. See
73+
[`tests/README.md`](tests/README.md).

0 commit comments

Comments
 (0)