[v4,10/23] libcamera: shaders: Add support for contrast
diff mbox series

Message ID 20251120233347.5046-11-bryan.odonoghue@linaro.org
State New
Headers show
Series
  • Add GLES 2.0 GPUISP to libcamera
Related show

Commit Message

Bryan O'Donoghue Nov. 20, 2025, 11:33 p.m. UTC
Apply contrast after black-level and CCM operations.

Suggested-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

33905b0b43c989c89a177c0e27dcd1acc80e750a

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 .../internal/shaders/bayer_1x_packed.frag     | 19 +++++++++++++++++++
 .../internal/shaders/bayer_unpacked.frag      | 19 +++++++++++++++++++
 2 files changed, 38 insertions(+)

Patch
diff mbox series

diff --git a/include/libcamera/internal/shaders/bayer_1x_packed.frag b/include/libcamera/internal/shaders/bayer_1x_packed.frag
index 069b880ff..741896d01 100644
--- a/include/libcamera/internal/shaders/bayer_1x_packed.frag
+++ b/include/libcamera/internal/shaders/bayer_1x_packed.frag
@@ -71,6 +71,19 @@  uniform sampler2D blue_param;
 uniform mat3 ccm;
 uniform vec3 blacklevel;
 uniform float gamma;
+uniform float contrast;
+
+float apply_contrast(float normalise, float contrast_in)
+{
+	// Convert 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2)
+	float contrastExp = tan(clamp(contrast_in * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001));
+
+	// Apply simple S-curve
+	if (normalise < 0.5)
+		return 0.5 * pow(normalise / 0.5, contrastExp);
+	else
+		return 1.0 - 0.5 * pow((1.0 - normalise) / 0.5, contrastExp);
+}
 
 void main(void)
 {
@@ -266,6 +279,12 @@  void main(void)
 	rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]);
 	rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]);
 
+	/* Contrast */
+	rgb = clamp(rgb, 0.0, 1.0);
+	rgb.r = apply_contrast(rgb.r, contrast);
+	rgb.g = apply_contrast(rgb.g, contrast);
+	rgb.b = apply_contrast(rgb.b, contrast);
+
 	/* Apply gamma after colour correction */
 	rgb = pow(rgb, vec3(gamma));
 
diff --git a/include/libcamera/internal/shaders/bayer_unpacked.frag b/include/libcamera/internal/shaders/bayer_unpacked.frag
index 950a4733e..16262feb2 100644
--- a/include/libcamera/internal/shaders/bayer_unpacked.frag
+++ b/include/libcamera/internal/shaders/bayer_unpacked.frag
@@ -30,6 +30,19 @@  varying vec4            xCoord;
 uniform mat3		ccm;
 uniform vec3		blacklevel;
 uniform float		gamma;
+uniform float contrast;
+
+float apply_contrast(float normalise, float contrast_in)
+{
+	// Convert 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2)
+	float contrastExp = tan(clamp(contrast_in * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001));
+
+	// Apply simple S-curve
+	if (normalise < 0.5)
+		return 0.5 * pow(normalise / 0.5, contrastExp);
+	else
+		return 1.0 - 0.5 * pow((1.0 - normalise) / 0.5, contrastExp);
+}
 
 void main(void) {
     vec3 rgb;
@@ -161,6 +174,12 @@  void main(void) {
 	rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]);
 	rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]);
 
+	/* Contrast */
+	rgb = clamp(rgb, 0.0, 1.0);
+	rgb.r = apply_contrast(rgb.r, contrast);
+	rgb.g = apply_contrast(rgb.g, contrast);
+	rgb.b = apply_contrast(rgb.b, contrast);
+
 	/* Apply gamma after colour correction */
 	rgb = pow(rgb, vec3(gamma));