UVC Hue rotation (YCbCr 4:4:4)
This block applies UVC Hue adjustment by rotating the chroma vector \((C_b, C_r)\) around the neutral point, while leaving luma \(Y\) unchanged.
This block does not clamp the output values. Chroma values outside the nominal 12-bit full-range are allowed and are expected to be handled later in the pipeline.
This block takes as input 12-bit per-channel YCbCr 4:4:4 of the following format: \[ Y12 \in [0..4095]\\ C_b12 \in [0..4095]\text{, neutral at }2048\\ C_r12 \in [0..4095]\text{, neutral at }2048 \]
Control input
Hue control value is a signed integer \(H\) in degrees \(\times 100\): \[ H \in [-18000..+18000]\text{, default }0 \]
Rotation angle (in degrees): \[ \theta = H / 100 \]
Step 1: calculate chroma deltas
Convert chroma channels into signed deltas around neutral: \[ \Delta C_b = C_b12 - 2048\\ \Delta C_r = C_r12 - 2048 \]
Step 2: rotate chroma vector
Apply 2D rotation: \[ \Delta C_b' = \Delta C_b \cdot \cos(\theta) - \Delta C_r \cdot \sin(\theta)\\ \Delta C_r' = \Delta C_b \cdot \sin(\theta) + \Delta C_r \cdot \cos(\theta) \]
Step 3: re-center chroma
Re-apply neutral offset: \[ C_b^{out} = 2048 + \Delta C_b'\\ C_r^{out} = 2048 + \Delta C_r'\\ Y^{out} = Y12 \]
No clamping or range limiting is performed in this block.
Fixed-point implementation
Trigonometric coefficients (MCU)
The microcontroller computes \(\sin(\theta)\) and \(\cos(\theta)\) and writes them as signed Q18 fixed-point values: \[ \sin_q = \mathrm{round}(\sin(\theta) \cdot 2^{18})\\ \cos_q = \mathrm{round}(\cos(\theta) \cdot 2^{18}) \]
FPGA math (signed Q18)
Chroma deltas are treated as signed values: \[ \Delta C_b, \Delta C_r \in [-2048..+2047] \]
Multiply-accumulate: \[ T_b = \Delta C_b \cdot \cos_q - \Delta C_r \cdot \sin_q\\ T_r = \Delta C_b \cdot \sin_q + \Delta C_r \cdot \cos_q \]
Convert back from Q18 using rounding-to-nearest: \[ \Delta C_b' = (T_b + 131072) >> 18\\ \Delta C_r' = (T_r + 131072) >> 18 \]
All operations use signed arithmetic with arithmetic right shift.
Bit width after hue rotation
Input deltas: \[ \Delta C_b, \Delta C_r \in [-2048..+2047] \]
Maximum chroma vector magnitude: \[ r_{max} = \sqrt{2048^2 + 2048^2} \approx 2896 \]
Maximum rotated deltas: \[ \Delta C_b', \Delta C_r' \in [-2896..+2896] \]
After re-centering: \[ C_b^{out}, C_r^{out} \in [-848..+4944] \]
13-bit signed storage is insufficient.
Minimum safe width is 14-bit signed. Recommended internal chroma width is 15–16 bits signed to allow margin for rounding and subsequent chroma-domain adjustments.