====== RGB UVC Gamma Adjustment ======
At this stage of the imaging pipeline the pixel data is represented in
full-range RGB color space with 12-bit precision per component, as produced by
the CMX stage ([[isp:gen5-cmx]]).
The purpose of this block is to apply **UVC gamma adjustment** in **RGB space**
by applying the **same LUT** to all three channels (baseline implementation).
This avoids the undesired desaturation artifacts caused by applying a nonlinear
transfer function to luma-only in YCbCr.
This block is intended to be implemented in FPGA logic and therefore avoids
runtime floating-point arithmetic.
After this stage completes, the next pipeline stage is the RGB-to-YCbCr
conversion stage ([[isp:gen5-rgb-to-yuv]]).
===== Input format =====
The input consists of RGB pixels with the following properties:
\[
R12 \in [0..4095]\\
G12 \in [0..4095]\\
B12 \in [0..4095]
\]
All values are unsigned 12-bit integers.
===== Output format =====
The output format is identical to the input format:
\[
R12^{\gamma} \in [0..4095]\\
G12^{\gamma} \in [0..4095]\\
B12^{\gamma} \in [0..4095]
\]
All three channels are modified by the gamma adjustment stage.
===== Step 1: UVC gamma transfer function =====
Gamma adjustment is applied **independently** to each RGB channel \(R12\),
\(G12\), and \(B12\) using the **same** transfer function / LUT.
The UVC gamma transfer function is defined in the following document:
[[https://wiki.sub2r.com/doku.php/isp:gamma|UVC Gamma Correction Specification]]
No additional interpretation or modification of the transfer function is
performed at this stage.
===== Step 2: LUT-based FPGA implementation =====
For FPGA implementation, the UVC gamma adjustment shall be realized using a
LUT with **4096 entries**, indexed by the 12-bit channel value.
Each LUT entry maps a 12-bit input channel value to a 12-bit output channel
value:
X_in = i // i in range [0..4095]
X_out = LUT[i] // gamma-adjusted channel value
The same LUT instance (same contents) is used for all channels.
===== Step 3: LUT generation tool =====
To simplify and standardize LUT generation, the following online tool may be
used:
[[https://toolbox.sub2r.com/sub2r-tb-gamma.html|Sub2r Gamma LUT Generator]]
The tool generates FPGA-ready gamma tables compatible with a 12-bit input and
12-bit output pipeline.
===== Step 4: pixel reconstruction =====
For each pixel, the output components are constructed as:
\[
R12^{\gamma} = LUT[R12]\\
G12^{\gamma} = LUT[G12]\\
B12^{\gamma} = LUT[B12]
\]
No additional scaling, offsetting, or clamping is required beyond the LUT
bounds.
===== Integration notes =====
This block is placed as follows:
... -> CMX -> RGB UVC Gamma -> RGB-to-YCbCr -> ...
The downstream RGB-to-YCbCr block consumes \(R12^{\gamma}\), \(G12^{\gamma}\),
and \(B12^{\gamma}\) as its inputs.
{{:isp:screenshot_2026-01-27_063531.png?400|}}
===== Expected results =====
* Gamma \(1.0\) is an identity gamma, that produces a LUT of a linear set of incremental values with one-to-one correspondence between input and output
* Image doesn't get washed out too much when Gamma is increased (within the \(1.0\)-\(2.5\) range)
* Slight hue drift is expected, but not to be an excessive one at extreme Gamma values
* LUT table for a given Gamma should match the one produced by the [[https://toolbox.sub2r.com/sub2r-tb-gamma.html|online tool]]
===== Notes =====
* This block operates entirely in **RGB space**.
* Gamma adjustment is applied independently to **all three channels** using the **same** LUT (baseline implementation).
* This stage assumes **full-range (computer-range) 12-bit RGB** coding.