Skip to content
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f38f3ae
Hue Curve Transform GPU
larochj Jun 6, 2024
225e064
Review Fixes P1
larochj Jun 7, 2024
ccddff6
Review Fixes P2
larochj Jun 10, 2024
41cdac2
Review Fixes P3
larochj Jun 13, 2024
3801f47
Review Fixes P4
larochj Jun 17, 2024
d5d9713
GradingHueCurveOpData_tests
larochj Jun 17, 2024
d50f76f
Review Fix, ChannelCrosstalk
larochj Jun 18, 2024
873982e
Review Fix, missing fixed function enums in switch cases
larochj Jun 18, 2024
8f54436
Review Fix, Missing comment on unused test parameters
larochj Jun 18, 2024
d01a753
CI Fix, removing multi-line comment
larochj Jun 18, 2024
2abeb38
Fixes for Test 2: test_cpu
larochj Jun 18, 2024
c8263fa
Fix Windows CI
larochj Jun 25, 2024
3504fe4
Fix for missing slopes on periodic curves
larochj Jun 26, 2024
ffcffe9
Remove leftover #include from debuging
larochj Jun 27, 2024
06def95
Enable to draw the curve eval only for a specific hue curve. (#11)
larochj Jul 18, 2024
e12f248
RGB to HSY fixed functions using CPU (#17)
larochj Jul 26, 2024
5626e75
Fix identity hue curve draw only (#20)
larochj Aug 7, 2024
587d486
<<Operator upgrade for list of floats (#23)
larochj Sep 26, 2024
5f223f3
Fix unit tests
doug-walker Oct 12, 2024
ad92002
Fix hue curve unit tests
doug-walker Oct 26, 2024
c71da0b
Comment out OSL tests
doug-walker Oct 26, 2024
a915b2d
Finish the implementation
doug-walker Jul 26, 2025
43df683
Improve interface, add tests
doug-walker Jul 28, 2025
a5bb65f
Minor clean-up
doug-walker Jul 29, 2025
ac8a1bf
Op<< should contain slopes
doug-walker Jul 30, 2025
5403b55
Fix python doc line
doug-walker Jul 30, 2025
62a75d8
Improve validation of control points
doug-walker Sep 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 187 additions & 1 deletion include/OpenColorIO/OpenColorTransforms.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,10 +513,15 @@ class OCIOEXPORT GradingBSplineCurve
public:
/// Create a BSpline curve with a specified number of control points.
static GradingBSplineCurveRcPtr Create(size_t size);
static GradingBSplineCurveRcPtr Create(size_t size, BSplineType splineType);
static GradingBSplineCurveRcPtr Create(size_t size, HueCurveType curveType);
/// Create a BSpline curve with a list of control points.
static GradingBSplineCurveRcPtr Create(std::initializer_list<GradingControlPoint> values);
static GradingBSplineCurveRcPtr Create(std::initializer_list<GradingControlPoint> values, BSplineType splineType);
static GradingBSplineCurveRcPtr Create(std::initializer_list<GradingControlPoint> values, HueCurveType curveType);

virtual GradingBSplineCurveRcPtr createEditableCopy() const = 0;
/// Get the number of ControlPoint objects (and the number of slopes).
virtual size_t getNumControlPoints() const noexcept = 0;
virtual void setNumControlPoints(size_t size) = 0;
virtual const GradingControlPoint & getControlPoint(size_t index) const = 0;
Expand All @@ -525,6 +530,8 @@ class OCIOEXPORT GradingBSplineCurve
virtual void setSlope(size_t index, float slope) = 0;
virtual bool slopesAreDefault() const = 0;
virtual void validate() const = 0;
virtual BSplineType getSplineType() const = 0;
virtual void setSplineType(BSplineType splineType) = 0;

GradingBSplineCurve(const GradingBSplineCurve &) = delete;
GradingBSplineCurve & operator= (const GradingBSplineCurve &) = delete;
Expand All @@ -547,6 +554,8 @@ extern OCIOEXPORT std::ostream & operator<<(std::ostream &, const GradingBSpline
class OCIOEXPORT GradingRGBCurve
{
public:
/// Create a GradingRGBCurve. (The style argument is not part of the object, it is simply
/// used to initialize the proper default curves.)
static GradingRGBCurveRcPtr Create(GradingStyle style);
static GradingRGBCurveRcPtr Create(const ConstGradingRGBCurveRcPtr & rhs);
static GradingRGBCurveRcPtr Create(const ConstGradingBSplineCurveRcPtr & red,
Expand All @@ -571,6 +580,58 @@ extern OCIOEXPORT bool operator==(const GradingRGBCurve & lhs, const GradingRGBC
extern OCIOEXPORT bool operator!=(const GradingRGBCurve & lhs, const GradingRGBCurve & rhs);
extern OCIOEXPORT std::ostream & operator<<(std::ostream &, const GradingRGBCurve &);

/**
* A set of HUE/SAT/LUM curves. It is used by GradingHueCurveTransform and can be used as
* a dynamic property (see \ref DynamicPropertyGradingHueCurve).
*/
class OCIOEXPORT GradingHueCurve
{
public:
/// Create a GradingHueCurve. (The style argument is not part of the object, it is simply
/// used to initialize the proper default curves.)
static GradingHueCurveRcPtr Create(GradingStyle style);
static GradingHueCurveRcPtr Create(const ConstGradingHueCurveRcPtr & rhs);
static GradingHueCurveRcPtr Create(
ConstGradingBSplineCurveRcPtr hueHue,
ConstGradingBSplineCurveRcPtr hueSat,
ConstGradingBSplineCurveRcPtr hueLum,
ConstGradingBSplineCurveRcPtr lumSat,
ConstGradingBSplineCurveRcPtr satSat,
ConstGradingBSplineCurveRcPtr lumLum,
ConstGradingBSplineCurveRcPtr satLum,
ConstGradingBSplineCurveRcPtr hueFx);

static BSplineType GetBSplineTypeForHueCurveType(HueCurveType curveType);

virtual GradingHueCurveRcPtr createEditableCopy() const = 0;
virtual void validate() const = 0;
virtual bool isIdentity() const = 0;
/**
* Enable drawCurveOnly mode to return the output value of a spline curve without any of the
* other associated processing of the RGB values. This is useful when the curves need to be
* graphed independently in a user interface. To use this, set the curve parameters on the
* Hue-Sat curve. The R, G, and B values will be sent through that curve with the interpretation
* that they are the input axis to the curve (which would be hue, sat, or luma) rather than RGB.
* This mode does not apply the RGB-to-HSY or Lin-to-Log, so for scene-linear curves the luma
* values are interpreted as already being in the logarithmic (f-stop) space. The forward curve
* evaluation is done regardless of the transform direction.
*/
virtual bool getDrawCurveOnly() const = 0;
virtual void setDrawCurveOnly(bool drawCurveOnly) = 0;
virtual ConstGradingBSplineCurveRcPtr getCurve(HueCurveType c) const = 0;
virtual GradingBSplineCurveRcPtr getCurve(HueCurveType c) = 0;

/// Do not use (needed only for pybind11).
virtual ~GradingHueCurve() = default;

protected:
GradingHueCurve() = default;
};

extern OCIOEXPORT bool operator==(const GradingHueCurve & lhs, const GradingHueCurve & rhs);
extern OCIOEXPORT bool operator!=(const GradingHueCurve & lhs, const GradingHueCurve & rhs);
extern OCIOEXPORT std::ostream & operator<<(std::ostream &, const GradingHueCurve &);

/**
* Used by the grading tone transforms to hold the red, green, blue, master, start,
* and width components of a single parameter. The master component affects all three channels
Expand Down Expand Up @@ -734,6 +795,11 @@ extern OCIOEXPORT DynamicPropertyGradingPrimaryRcPtr AsGradingPrimary(DynamicPro
* value. Will throw if property type is not DYNAMIC_PROPERTY_GRADING_RGBCURVE.
*/
extern OCIOEXPORT DynamicPropertyGradingRGBCurveRcPtr AsGradingRGBCurve(DynamicPropertyRcPtr & prop);
/**
* Get the property as DynamicPropertyGradingHueCurveRcPtr to access the GradingHueCurveRcPtr
* value. Will throw if property type is not DYNAMIC_PROPERTY_GRADING_HUECURVE.
*/
extern OCIOEXPORT DynamicPropertyGradingHueCurveRcPtr AsGradingHueCurve(DynamicPropertyRcPtr & prop);
/**
* Get the property as DynamicPropertyGradingToneRcPtr to access the GradingTone value. Will throw
* if property type is not DYNAMIC_PROPERTY_GRADING_TONE.
Expand Down Expand Up @@ -791,6 +857,23 @@ class OCIOEXPORT DynamicPropertyGradingRGBCurve
DynamicPropertyGradingRGBCurve() = default;
};

/// Interface used to access dynamic property ConstGradingHueCurveRcPtr value.
class OCIOEXPORT DynamicPropertyGradingHueCurve
{
public:
virtual const ConstGradingHueCurveRcPtr & getValue() const = 0;
/// Will throw if value is not valid.
virtual void setValue(const ConstGradingHueCurveRcPtr & value) = 0;

DynamicPropertyGradingHueCurve(const DynamicPropertyGradingHueCurve &) = delete;
DynamicPropertyGradingHueCurve & operator=(const DynamicPropertyGradingHueCurve &) = delete;
/// Do not use (needed only for pybind11).
virtual ~DynamicPropertyGradingHueCurve() = default;

protected:
DynamicPropertyGradingHueCurve() = default;
};

/// Interface used to access dynamic property GradingTone value.
class OCIOEXPORT DynamicPropertyGradingTone
{
Expand Down Expand Up @@ -1196,13 +1279,116 @@ class OCIOEXPORT GradingPrimaryTransform : public Transform

extern OCIOEXPORT std::ostream & operator<<(std::ostream &, const GradingPrimaryTransform &) noexcept;

/**
* Hue curve color correction controls.
*
* This transform provides eight spline curves to make the following adjustments:
*
* - Hue-Hue: Map input hue to output hue (where a diagonal line is the identity).
* - Hue-Sat: Adjust saturation as a function of hue (a value of 1.0 is the identity).
* - Hue-Lum: Adjust luma as a function of hue (a value of 1.0 is the identity).
* - Lum-Sat: Adjust saturation as a function of luma (a value of 1.0 is the identity).
* - Sat-Sat: Adjust saturation as a function of saturation (a diagonal is the identity).
* - Lum-Lum: Adjust luma as a function of luma, maintaining hue & sat (diagonal is identity).
* - Sat-Lum: Adjust luma as a function of saturation (a value of 1.0 is the identity).
* - Hue-FX : Map input hue to delta output hue (a value of 0.0 is the identity).
*
* The algorithm is different for scene-linear, logarithmic, and video color spaces, so
* initialize the style argument appropriately before setting the curves.
*
* An RGB-to-HSY FixedFunction is used to convert RGB into a hue, saturation, luma color
* space. However, there is an option to bypass that conversion to use an outboard transform.
*
* Like the GradingRGBCurveTransform, the curves are defined by the x and y coordinates of a
* set of control points. A spline will be fit to the control points. Monotonicity is preserved
* for curves where the diagonal is the identity. For curves that take luma as input, if the
* style is scene-linear, the units are in photographic stops relative to 0.18. For log and
* video, the luma is scaled the same as the input RGB.
*
* The hue variable is [0,1] and is periodic. For example, -0.2, 0.8, and 1.8 are equivalent.
* The domain of the curves is [0,1] and control points outside that domain are mapped into it.
* A hue of 0 or 1 corresponds to a magenta hue.
*
* The transform is invertible as long as the curves allow it. For example, if saturation is
* mapped to zero, obviously that cannot be resaturated. Care should be taken with the Hue-FX
* curve because it is possible to fold hues over on themselves, which also cannot be inverted.
* In most cases the Hue-FX curve is not necessary since the Hue-Hue curve provides similar
* functionality with the added benefit of being strictly invertible.
*
* The control points are dynamic, so they may be adjusted even after the Transform is included
* in a Processor.
*/
class OCIOEXPORT GradingHueCurveTransform : public Transform
{
public:
/// Creates an instance of GradingHueCurveTransform.
static GradingHueCurveTransformRcPtr Create(GradingStyle style);

TransformType getTransformType() const noexcept override { return TRANSFORM_TYPE_GRADING_HUE_CURVE; }

virtual const FormatMetadata & getFormatMetadata() const noexcept = 0;
virtual FormatMetadata & getFormatMetadata() noexcept = 0;

/// Checks if this equals other.
virtual bool equals(const GradingHueCurveTransform & other) const noexcept = 0;

/// Adjusts the behavior of the transform for log, linear, or video color space encodings.
virtual GradingStyle getStyle() const noexcept = 0;

/// Will reset value to style's defaults if style is not the current style.
virtual void setStyle(GradingStyle style) noexcept = 0;

virtual const ConstGradingHueCurveRcPtr getValue() const = 0;

/// Throws if value is not valid.
virtual void setValue(const ConstGradingHueCurveRcPtr & value) = 0;

/**
* It is possible to provide a desired slope value for each control point. The number of slopes is
* always the same as the number of control points and so the control points must be set before
* setting the slopes. The slopes are primarily intended for use by config authors looking to match
* a specific shape with as few control points as possible, they are not intended to be exposed to
* a user interface for direct manipulation. When a curve is being generated for creative purposes
* it is better to let OCIO calculate the slopes automatically.
*/
virtual float getSlope(HueCurveType c, size_t index) const = 0;
virtual void setSlope(HueCurveType c, size_t index, float slope) = 0;
virtual bool slopesAreDefault(HueCurveType c) const = 0;

/**
* By default, the input is transformed into HSY space to apply the hue curves and then the result is
* transformed back to RGB. However, this may be bypassed to use other hue/sat/luma type transforms
* applied separately before and after this transform.
*/
virtual bool getBypassRGBToHSY() const = 0;
virtual void setBypassRGBToHSY(bool bypass) = 0;

///**
// * Parameters can be made dynamic so the values can be changed through the CPU or GPU processor,
// * but if there are several GradingHueCurveTransform only one can have dynamic parameters.
// */
virtual bool isDynamic() const noexcept = 0;
virtual void makeDynamic() noexcept = 0;
virtual void makeNonDynamic() noexcept = 0;

GradingHueCurveTransform(const GradingHueCurveTransform &) = delete;
GradingHueCurveTransform & operator= (const GradingHueCurveTransform &) = delete;

/// Do not use (needed only for pybind11).
virtual ~GradingHueCurveTransform() = default;

protected:
GradingHueCurveTransform() = default;
};

extern OCIOEXPORT std::ostream & operator<<(std::ostream &, const GradingHueCurveTransform &) noexcept;

/**
* RGB curve color correction controls.
*
* This transform allows for modifying tone reproduction via B-spline curves.
*
* There is an R, G, and B curve along with a Master curve (that applies to R, G, and B). Each
* There is an R, G, and B curve followed by a Master curve (that applies to R, G, and B). Each
* curve is specified via the x and y coordinates of its control points. A monotonic spline is
* fit to the control points. The x coordinates must be non-decreasing. When the grading style
* is linear, the units for the control points are photographic stops relative to 0.18.
Expand Down
45 changes: 43 additions & 2 deletions include/OpenColorIO/OpenColorTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ class OCIOEXPORT GradingRGBCurve;
typedef OCIO_SHARED_PTR<const GradingRGBCurve> ConstGradingRGBCurveRcPtr;
typedef OCIO_SHARED_PTR<GradingRGBCurve> GradingRGBCurveRcPtr;

class OCIOEXPORT GradingHueCurve;
typedef OCIO_SHARED_PTR<const GradingHueCurve> ConstGradingHueCurveRcPtr;
typedef OCIO_SHARED_PTR<GradingHueCurve> GradingHueCurveRcPtr;

class OCIOEXPORT ConfigIOProxy;
typedef OCIO_SHARED_PTR<const ConfigIOProxy> ConstConfigIOProxyRcPtr;
typedef OCIO_SHARED_PTR<ConfigIOProxy> ConfigIOProxyRcPtr;
Expand Down Expand Up @@ -163,6 +167,10 @@ class OCIOEXPORT DynamicPropertyGradingRGBCurve;
typedef OCIO_SHARED_PTR<const DynamicPropertyGradingRGBCurve> ConstDynamicPropertyGradingRGBCurveRcPtr;
typedef OCIO_SHARED_PTR<DynamicPropertyGradingRGBCurve> DynamicPropertyGradingRGBCurveRcPtr;

class OCIOEXPORT DynamicPropertyGradingHueCurve;
typedef OCIO_SHARED_PTR<const DynamicPropertyGradingHueCurve> ConstDynamicPropertyGradingHueCurveRcPtr;
typedef OCIO_SHARED_PTR<DynamicPropertyGradingHueCurve> DynamicPropertyGradingHueCurveRcPtr;

class OCIOEXPORT DynamicPropertyGradingTone;
typedef OCIO_SHARED_PTR<const DynamicPropertyGradingTone> ConstDynamicPropertyGradingToneRcPtr;
typedef OCIO_SHARED_PTR<DynamicPropertyGradingTone> DynamicPropertyGradingToneRcPtr;
Expand Down Expand Up @@ -191,6 +199,10 @@ class OCIOEXPORT GradingPrimaryTransform;
typedef OCIO_SHARED_PTR<const GradingPrimaryTransform> ConstGradingPrimaryTransformRcPtr;
typedef OCIO_SHARED_PTR<GradingPrimaryTransform> GradingPrimaryTransformRcPtr;

class OCIOEXPORT GradingHueCurveTransform;
typedef OCIO_SHARED_PTR<const GradingHueCurveTransform> ConstGradingHueCurveTransformRcPtr;
typedef OCIO_SHARED_PTR<GradingHueCurveTransform> GradingHueCurveTransformRcPtr;

class OCIOEXPORT GradingRGBCurveTransform;
typedef OCIO_SHARED_PTR<const GradingRGBCurveTransform> ConstGradingRGBCurveTransformRcPtr;
typedef OCIO_SHARED_PTR<GradingRGBCurveTransform> GradingRGBCurveTransformRcPtr;
Expand Down Expand Up @@ -351,6 +363,7 @@ enum TransformType
TRANSFORM_TYPE_EXPOSURE_CONTRAST,
TRANSFORM_TYPE_FILE,
TRANSFORM_TYPE_FIXED_FUNCTION,
TRANSFORM_TYPE_GRADING_HUE_CURVE,
TRANSFORM_TYPE_GRADING_PRIMARY,
TRANSFORM_TYPE_GRADING_RGB_CURVE,
TRANSFORM_TYPE_GRADING_TONE,
Expand Down Expand Up @@ -496,7 +509,10 @@ enum FixedFunctionStyle
FIXED_FUNCTION_ACES_OUTPUT_TRANSFORM_20, ///< ACES 2.0 Display Rendering -- EXPERIMENTAL
FIXED_FUNCTION_ACES_RGB_TO_JMH_20, ///< ACES 2.0 RGB to JMh -- EXPERIMENTAL
FIXED_FUNCTION_ACES_TONESCALE_COMPRESS_20, ///< ACES 2.0 Tonescale and chroma compression -- EXPERIMENTAL
FIXED_FUNCTION_ACES_GAMUT_COMPRESS_20 ///< ACES 2.0 Gamut compression -- EXPERIMENTAL
FIXED_FUNCTION_ACES_GAMUT_COMPRESS_20, ///< ACES 2.0 Gamut compression -- EXPERIMENTAL
FIXED_FUNCTION_RGB_TO_HSY_LIN, ///< RGB to HSY (Hue, Saturation, Luminance) for linear spaces
FIXED_FUNCTION_RGB_TO_HSY_LOG, ///< RGB to HSY (Hue, Saturation, Luma) for log spaces
FIXED_FUNCTION_RGB_TO_HSY_VID, ///< RGB to HSY (Hue, Saturation, Luma) for video spaces
};

/// Enumeration of the :cpp:class:`ExposureContrastTransform` transform algorithms.
Expand Down Expand Up @@ -549,7 +565,8 @@ enum DynamicPropertyType
DYNAMIC_PROPERTY_GAMMA, ///< Image gamma value (double floating point value)
DYNAMIC_PROPERTY_GRADING_PRIMARY, ///< Used by GradingPrimaryTransform
DYNAMIC_PROPERTY_GRADING_RGBCURVE, ///< Used by GradingRGBCurveTransform
DYNAMIC_PROPERTY_GRADING_TONE ///< Used by GradingToneTransform
DYNAMIC_PROPERTY_GRADING_TONE, ///< Used by GradingToneTransform
DYNAMIC_PROPERTY_GRADING_HUECURVE ///< Used by GradingHueCurveTransform
};

/// Types for GradingRGBCurve.
Expand All @@ -562,6 +579,30 @@ enum RGBCurveType
RGB_NUM_CURVES
};

/// Types for GradingHueCurve.
enum HueCurveType
{
HUE_HUE = 0,
HUE_SAT,
HUE_LUM,
LUM_SAT,
SAT_SAT,
LUM_LUM,
SAT_LUM,
HUE_FX,
HUE_NUM_CURVES
};

enum BSplineType
{
B_SPLINE = 0, //!< Monotonic quadratic B-spline used for the RGBM curves.
DIAGONAL_B_SPLINE, //!< Monotonic quadratic B-spline for the sat-sat and lum-lum curves.
HUE_HUE_B_SPLINE, //!< Monotonic and periodic B-spline used for the hue-hue curve.
PERIODIC_1_B_SPLINE, //!< Periodic, horizontal (at 1) B-spline for hue-sat and hue-lum curves.
PERIODIC_0_B_SPLINE, //!< Periodic, horizontal (at 0) B-spline used for the hue-fx curve.
HORIZONTAL1_B_SPLINE, //!< Horizontal (at 1) B-spline used for the lum-sat and sat-lum curves.
};

/// Types for uniform data.
enum UniformDataType
{
Expand Down
6 changes: 6 additions & 0 deletions src/OpenColorIO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ set(SOURCES
ops/gamma/GammaOpGPU.cpp
ops/gamma/GammaOpUtils.cpp
ops/gamma/GammaOp.cpp
ops/gradinghuecurve/GradingHueCurve.cpp
ops/gradinghuecurve/GradingHueCurveOpCPU.cpp
ops/gradinghuecurve/GradingHueCurveOpData.cpp
ops/gradinghuecurve/GradingHueCurveOpGPU.cpp
ops/gradinghuecurve/GradingHueCurveOp.cpp
ops/gradingprimary/GradingPrimary.cpp
ops/gradingprimary/GradingPrimaryOpCPU.cpp
ops/gradingprimary/GradingPrimaryOpData.cpp
Expand Down Expand Up @@ -169,6 +174,7 @@ set(SOURCES
transforms/ExposureContrastTransform.cpp
transforms/FileTransform.cpp
transforms/FixedFunctionTransform.cpp
transforms/GradingHueCurveTransform.cpp
transforms/GradingPrimaryTransform.cpp
transforms/GradingRGBCurveTransform.cpp
transforms/GradingToneTransform.cpp
Expand Down
Loading
Loading