289 lines
12 KiB
C
289 lines
12 KiB
C
|
/* SPDX-License-Identifier: MIT */
|
||
|
/**
|
||
|
@file ntv2cscmatrix.h
|
||
|
@brief Declares the utility class for abstract color space matrix operations.
|
||
|
@copyright 2004-2021 AJA Video Systems, Inc. All rights reserved.
|
||
|
**/
|
||
|
|
||
|
#ifndef NTV2_CSCMATRIX_H
|
||
|
#define NTV2_CSCMATRIX_H
|
||
|
|
||
|
|
||
|
#include "ajatypes.h"
|
||
|
#include "ajaexport.h"
|
||
|
#include "ntv2enums.h"
|
||
|
#include "ntv2card.h"
|
||
|
|
||
|
|
||
|
const int16_t NTV2_CSCMatrix_ZeroOffset = 0x0000;
|
||
|
const int16_t NTV2_CSCMatrix_SMPTEYOffset = 0x0800; // 0x10 with added ms sign bit and ls-padded to 16 bits
|
||
|
const int16_t NTV2_CSCMatrix_SMPTECOffset = 0x4000; // 0x80 with added ms sign bit and ls-padded to 16 bits
|
||
|
|
||
|
|
||
|
typedef enum NTV2CSCCoeff
|
||
|
{
|
||
|
NTV2CSCCoeffIndex_A0, ///< @brief Proportion of input component 0 applied to A output
|
||
|
NTV2CSCCoeffIndex_A1, ///< @brief Proportion of input component 1 applied to A output
|
||
|
NTV2CSCCoeffIndex_A2, ///< @brief Proportion of input component 2 applied to A output
|
||
|
|
||
|
NTV2CSCCoeffIndex_B0, ///< @brief Proportion of input component 0 applied to B output
|
||
|
NTV2CSCCoeffIndex_B1, ///< @brief Proportion of input component 1 applied to B output
|
||
|
NTV2CSCCoeffIndex_B2, ///< @brief Proportion of input component 2 applied to B output
|
||
|
|
||
|
NTV2CSCCoeffIndex_C0, ///< @brief Proportion of input component 0 applied to C output
|
||
|
NTV2CSCCoeffIndex_C1, ///< @brief Proportion of input component 1 applied to C output
|
||
|
NTV2CSCCoeffIndex_C2 ///< @brief Proportion of input component 2 applied to C output
|
||
|
} NTV2CSCCoeffIndex;
|
||
|
|
||
|
|
||
|
typedef enum NTV2CSCOffset
|
||
|
{
|
||
|
NTV2CSCOffsetIndex_Pre0,
|
||
|
NTV2CSCOffsetIndex_Pre1,
|
||
|
NTV2CSCOffsetIndex_Pre2,
|
||
|
|
||
|
NTV2CSCOffsetIndex_PostA,
|
||
|
NTV2CSCOffsetIndex_PostB,
|
||
|
NTV2CSCOffsetIndex_PostC
|
||
|
} NTV2CSCOffsetIndex;
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief This is used to compare CSC Matrix coefficients -- the default amount by which
|
||
|
they can differ and still be considered "equal".
|
||
|
**/
|
||
|
const double NTV2CSCMatrix_MaxCoeffDiff = (1.0 / 4096.0);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief This class supports the color space conversion matrix described below.
|
||
|
|
||
|
@details The CSC matrix consists of a pre-subtractor, a 3x3 matrix multiplier,
|
||
|
and a post-adder. It receives up to three components as input (labeled
|
||
|
Input0, Input1, and Input2), cross-processes them, and outputs them as
|
||
|
OutputA, OutputB, OutputC. The standard component assignment for GBR
|
||
|
and YCbCr video is:
|
||
|
YCbCr RGB
|
||
|
Input0 / OutputA = Y G
|
||
|
Input1 / OutputB = Cb B
|
||
|
Input2 / OutputC = Cr R
|
||
|
|
||
|
The basic purpose of the pre-subtractor is to remove any DC bias(es) that
|
||
|
may be on the input video prior to the matrix multiply. For example, YCbCr
|
||
|
video typically has a "black" offset of 0x10 for luminance (Y) and 0x80
|
||
|
for chrominance (Cb/Cr - values given for 8-bit video). In general, these
|
||
|
offsets must be subtracted from the video before using the 3x3 matrix.
|
||
|
|
||
|
Similarly, the post-adder is typically used to re-add "black" biases to
|
||
|
the output video. Note that both pre- and post-offsets are typically "positive"
|
||
|
values, and assume a left-justified representation within a 16-bit integer.
|
||
|
In the above example, Y Black offset would be 0x0800 (i.e. 0x10 with an added
|
||
|
sign bit and ls-padded to 16 bits). Similarly, C Black Offset is 0x4000
|
||
|
(0x80 with a sign bit and ls-padded to 16 bits).
|
||
|
|
||
|
The 3x3 matrix coefficients are labeled according to the input (0, 1, or 2)
|
||
|
and output (A, B, or C) they affect. For example, coefficient "A0" determines
|
||
|
the amount of Input0 that is applied to OutputA. The matrix form of the
|
||
|
equation can be represented as:
|
||
|
|
||
|
[OutA OutB OutC] = [In0 In1 In2] [ A0 B0 C0
|
||
|
A1 B1 C1
|
||
|
A2 B2 C2 ]
|
||
|
|
||
|
This class has methods for presetting known matrix values (for "typical"
|
||
|
RGB <=> YUV conversions), as well as some typical "gain" and "hue rotation"
|
||
|
matrices. It also includes methods for combining matrices for more complex
|
||
|
effects, including matrix multiplication.
|
||
|
**/
|
||
|
class AJAExport CNTV2CSCMatrix
|
||
|
{
|
||
|
public:
|
||
|
/**
|
||
|
@brief Instantiates and initializes the instance with a known set of coefficients.
|
||
|
@param[in] inPreset Specifies an initial setting for the matrix coefficients.
|
||
|
**/
|
||
|
explicit CNTV2CSCMatrix (const NTV2ColorSpaceMatrixType inPreset = NTV2_Unity_Matrix);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief My destructor.
|
||
|
**/
|
||
|
virtual inline ~CNTV2CSCMatrix () {};
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Replace the current matrix coefficients with a known set of coefficients.
|
||
|
@param[in] inPreset Specifies a new setting for the matrix coefficients.
|
||
|
**/
|
||
|
virtual void InitMatrix (const NTV2ColorSpaceMatrixType inPreset);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Returns the value of a requested matrix coefficient.
|
||
|
@param[in] inCoeffIndex Specifies which matrix coefficient to return.
|
||
|
@return The value of the requested coefficient.
|
||
|
**/
|
||
|
virtual double GetCoefficient (const NTV2CSCCoeffIndex inCoeffIndex) const;
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Changes the specified matrix coefficient to the given value.
|
||
|
@param[in] inCoeffIndex Specifies which matrix coefficient to change.
|
||
|
@param[in] inCoefficient Specifies the new matrix coefficient value.
|
||
|
**/
|
||
|
virtual void SetCoefficient (const NTV2CSCCoeffIndex inCoeffIndex, const double inCoefficient);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Returns the value of a requested offset.
|
||
|
@param[in] inOffsetIndex Specifies which offset to return.
|
||
|
@return The value of the requested offset.
|
||
|
**/
|
||
|
virtual int16_t GetOffset (const NTV2CSCOffsetIndex inOffsetIndex) const;
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Changes the specified offset to the given value.
|
||
|
@param[in] inOffsetIndex Specifies which offset to change.
|
||
|
@param[in] inOffset Specifies the new offset value.
|
||
|
**/
|
||
|
virtual void SetOffset (const NTV2CSCOffsetIndex inOffsetIndex, const int16_t inOffset);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Pre-multiply the current 3x3 matrix by the matrix of the given instance.
|
||
|
@param[in] inPreInstance Specifies a reference to a CNTV2CSCMatrix instance.
|
||
|
**/
|
||
|
virtual void PreMultiply (const CNTV2CSCMatrix & inPreInstance);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Post-multiply the current 3x3 matrix by the matrix of the given instance.
|
||
|
* @param[in] inPostInstance Specifies a reference to a CNTV2CSCMatrix instance.
|
||
|
*/
|
||
|
virtual void PostMultiply (const CNTV2CSCMatrix & inPostInstance);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Set the matrix diagonals (gains).
|
||
|
@param[in] inGain0 Specifies the amount of gain to be applied to the 1st channel (unity = 1.0)
|
||
|
@param[in] inGain1 Specifies the amount of gain to be applied to the 2nd channel
|
||
|
@param[in] inGain2 Specifies the amount of gain to be applied to the 3rd channel
|
||
|
**/
|
||
|
virtual void SetGain (const double inGain0, const double inGain1, const double inGain2);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Set matrix for hue rotation.
|
||
|
@param[in] inDegrees Amount of Cb/Cr "rotation" (in degrees)
|
||
|
@note Assumes chroma channels in In 1/Out B, In 2/Out C. This will not work for RGB.
|
||
|
**/
|
||
|
virtual void SetHueRotate (const double inDegrees);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Set pre-offsets.
|
||
|
@param[in] inOffset0 The zero, or "black" level of the 1st input channel
|
||
|
@param[in] inOffset1 The zero, or "black" level of the 2nd input channel
|
||
|
@param[in] inOffset2 The zero, or "black" level of the 3rd input channel
|
||
|
**/
|
||
|
virtual void SetPreOffsets (const int16_t inOffset0, const int16_t inOffset1, const int16_t inOffset2);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Add pre-offsets.
|
||
|
@param[in] inIncrement0 The amount to be added to the existing preOffset0
|
||
|
@param[in] inIncrement1 The amount to be added to the existing preOffset1
|
||
|
@param[in] inIncrement2 The amount to be added to the existing preOffset2
|
||
|
**/
|
||
|
virtual void AddPreOffsets (const int16_t inIncrement0, const int16_t inIncrement1, const int16_t inIncrement2);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Set post-offsets.
|
||
|
@param[in] inOffsetA The zero, or "black" level of the 1st output channel
|
||
|
@param[in] inOffsetB The zero, or "black" level of the 2nd output channel
|
||
|
@param[in] inOffsetC The zero, or "black" level of the 3rd output channel
|
||
|
**/
|
||
|
virtual void SetPostOffsets (const int16_t inOffsetA, const int16_t inOffsetB, const int16_t inOffsetC);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Add post-offsets.
|
||
|
@param[in] inIncrementA The amount to be added to the existing postOffsetA
|
||
|
@param[in] inIncrementB The amount to be added to the existing postOffsetB
|
||
|
@param[in] inIncrementC The amount to be added to the existing postOffsetC
|
||
|
**/
|
||
|
virtual void AddPostOffsets (const int16_t inIncrementA, const int16_t inIncrementB, const int16_t inIncrementC);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Returns 'true' if this CSC Matrix has unity matrix coefficients.
|
||
|
@return True if the matrix is a unity matrix; otherwise false
|
||
|
@note ONLY compares matrix coefficients, NOT offsets.
|
||
|
**/
|
||
|
virtual bool IsUnityMatrix (void);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Returns true if the matrix coefficients and offsets EXACTLY match those of the specified instance.
|
||
|
@note Compares matrix coefficients and offsets.
|
||
|
**/
|
||
|
virtual bool operator == (const CNTV2CSCMatrix & rhs) const;
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Returns true if the matrix coefficients and offsets differ from those of the specified instance.
|
||
|
@note Compares matrix coefficients and offsets.
|
||
|
**/
|
||
|
virtual inline bool operator != (const CNTV2CSCMatrix & rhs) const {return !(*this == rhs);}
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Tests if the matrix coefficients can all be considered equal to those of the specified instance,
|
||
|
@param[in] inCSCMatrix Specifies a reference to a CNTV2CSCMatrix instance.
|
||
|
@param[in] inMaxDiff Specifies the amount by which two coefficients can differ and still be considered "equal"
|
||
|
@return True if all the matrix coefficients differ by an amount less than the tolerance; otherwise false
|
||
|
@note ONLY compares matrix coefficients, NOT offsets.
|
||
|
**/
|
||
|
virtual bool IsEqual (const CNTV2CSCMatrix & inCSCMatrix, const double inMaxDiff = NTV2CSCMatrix_MaxCoeffDiff);
|
||
|
|
||
|
|
||
|
/**
|
||
|
@brief Tests if two coefficients differ by less than the fiven tolerance.
|
||
|
@param[in] inCoeff1 Specifies the first coefficient to be compared
|
||
|
@param[in] inCoeff2 Specifies the second coefficient to be compared
|
||
|
@param[in] inMaxDiff Specifies the amount by which two coefficients can differ and still be considered "equal"
|
||
|
@return True if the the two oefficients differ by an amount less than the tolerance; otherwise false
|
||
|
**/
|
||
|
virtual bool CoeffEqual (const double inCoeff1, const double inCoeff2, const double inMaxDiff);
|
||
|
|
||
|
|
||
|
// Instance Data
|
||
|
private:
|
||
|
double mA0; ///< @brief Specifies the amount of Input 0 to be applied to Output A
|
||
|
double mA1; ///< @brief Specifies the amount of Input 1 to be applied to Output A
|
||
|
double mA2; ///< @brief Specifies the amount of Input 2 to be applied to Output A
|
||
|
|
||
|
double mB0; ///< @brief Specifies the amount of Input 0 to be applied to Output B
|
||
|
double mB1; ///< @brief Specifies the amount of Input 1 to be applied to Output B
|
||
|
double mB2; ///< @brief Specifies the amount of Input 2 to be applied to Output B
|
||
|
|
||
|
double mC0; ///< @brief Specifies the amount of Input 0 to be applied to Output C
|
||
|
double mC1; ///< @brief Specifies the amount of Input 1 to be applied to Output C
|
||
|
double mC2; ///< @brief Specifies the amount of Input 2 to be applied to Output C
|
||
|
|
||
|
int16_t mPreOffset0; ///< @brief Specifies Input 0's offset from zero
|
||
|
int16_t mPreOffset1; ///< @brief Specifies Input 1's offset from zero
|
||
|
int16_t mPreOffset2; ///< @brief Specifies Input 2's offset from zero
|
||
|
|
||
|
int16_t mPostOffsetA; ///< @brief Specifies Output A's offset from zero
|
||
|
int16_t mPostOffsetB; ///< @brief Specifies Output B's offset from zero
|
||
|
int16_t mPostOffsetC; ///< @brief Specifies Output C's offset from zero
|
||
|
|
||
|
NTV2ColorSpaceMatrixType mPreset; ///< @brief Specifies if the matrix coefficients correspond to preset values
|
||
|
|
||
|
}; // CNTV2CSCMatrix
|
||
|
|
||
|
#endif // NTV2_CSCMATRIX_H
|