[v11,11/24] libcamera: shaders: Add support for contrast
diff mbox series

Message ID 20260106170059.56193-12-bryan.odonoghue@linaro.org
State Accepted
Commit e4effc1e3010211ea5f815f17ebac45b0dbdbd42
Headers show
Series
  • Add GLES 2.0 GPUISP to libcamera
Related show

Commit Message

Bryan O'Donoghue Jan. 6, 2026, 5 p.m. UTC
Apply contrast after black-level and CCM operations.

Suggested-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Milan Zamazal <mzamazal@redhat.com>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 src/libcamera/shaders/bayer_1x_packed.frag | 19 +++++++++++++++++++
 src/libcamera/shaders/bayer_unpacked.frag  | 18 ++++++++++++++++++
 2 files changed, 37 insertions(+)

Patch
diff mbox series

diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag
index 77d9fbfa7..23747f78a 100644
--- a/src/libcamera/shaders/bayer_1x_packed.frag
+++ b/src/libcamera/shaders/bayer_1x_packed.frag
@@ -68,6 +68,16 @@  uniform sampler2D tex_y;
 uniform mat3 ccm;
 uniform vec3 blacklevel;
 uniform float gamma;
+uniform float contrastExp;
+
+float apply_contrast(float value)
+{
+	// Apply simple S-curve
+	if (value < 0.5)
+		return 0.5 * pow(value / 0.5, contrastExp);
+	else
+		return 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp);
+}
 
 void main(void)
 {
@@ -261,6 +271,15 @@  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
+	 * contrastExp 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2)
+	 */
+	rgb = clamp(rgb, 0.0, 1.0);
+	rgb.r = apply_contrast(rgb.r);
+	rgb.g = apply_contrast(rgb.g);
+	rgb.b = apply_contrast(rgb.b);
+
 	/* Apply gamma after colour correction */
 	rgb = pow(rgb, vec3(gamma));
 
diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag
index aba11a87f..af4a30c4b 100644
--- a/src/libcamera/shaders/bayer_unpacked.frag
+++ b/src/libcamera/shaders/bayer_unpacked.frag
@@ -27,6 +27,16 @@  varying vec4            xCoord;
 uniform mat3            ccm;
 uniform vec3            blacklevel;
 uniform float           gamma;
+uniform float           contrastExp;
+
+float apply_contrast(float value)
+{
+    // Apply simple S-curve
+    if (value < 0.5)
+        return 0.5 * pow(value / 0.5, contrastExp);
+    else
+        return 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp);
+}
 
 void main(void) {
     vec3 rgb;
@@ -156,6 +166,14 @@  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);
+    rgb.g = apply_contrast(rgb.g);
+    rgb.b = apply_contrast(rgb.b);
+
     /* Apply gamma after colour correction */
     rgb = pow(rgb, vec3(gamma));