Hue rotation

“Hue rotation” is a global (every pixel) shift of the image's color spectrum by a given radial offset (considering the color wheel).

In RGB color space

To rotate the color vector by an angle \(\Theta\) is to rotate the RGB cube around the \((0,0,0)-(1,1,)\) diagonal axis, for which the rotation matrix looks like the following:

\[ cos_1 = cos(\Theta) \\ cos_2 = \frac{1 - cos_1}{3} \\ sin_1 = sin(\Theta)\sqrt{1/3} \\ \begin{bmatrix} cos_1 + cos_2 & cos_2 - sin_1 & cos_2 + sin_1 \\ cos_2 + sin_1 & cos_1 + cos_2 & cos_2 - sin_1 \\ cos_2 - sin_1 & cos_2 + sin_1 & cos_1 + cos_2 \end{bmatrix} \]

In our codebase the Hue adjustment is a 14-bit signed integer in range \([-8192..8191]\) that corresponds to \([-180°..+180°)\).

M.B. this does not take into account the fact that different chroma components contribute differently to the luma of the pixel. A more correct implementation must first separate luma and chroma, perform rotation on chroma, and then convert back to RGB triplet, but that is way too expensive to perform in-line during video transmission.

In HSL color space

Really, no magic here, once you process the image in HSL color space. The operation is as trivial as adding or subtracting a specified value from the pixel's \(H\) component:

// pseudo-code
void hue_rotation(/*array of pixels*/image, double _hue){
  for(const & pixel: image){
    pixel.hue = std::clamp(pixel.hue + _hue, 0., 360.); // hue is in range [0..360]°
  }
}