[{"id":37426,"web_url":"https://patchwork.libcamera.org/comment/37426/","msgid":"<85ldj1b6l0.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2025-12-17T13:06:51","subject":"Re: [PATCH v9 10/26] libcamera: shaders: Add support for contrast","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Bryan O'Donoghue <bryan.odonoghue@linaro.org> writes:\n\n> Apply contrast after black-level and CCM operations.\n>\n> Suggested-by: Milan Zamazal <mzamazal@redhat.com>\n> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>\n> ---\n>  src/libcamera/shaders/bayer_1x_packed.frag | 21 +++++++++++++++++++++\n>  src/libcamera/shaders/bayer_unpacked.frag  | 21 +++++++++++++++++++++\n>  2 files changed, 42 insertions(+)\n>\n> diff --git a/src/libcamera/shaders/bayer_1x_packed.frag b/src/libcamera/shaders/bayer_1x_packed.frag\n> index 77d9fbfa7..0b730070e 100644\n> --- a/src/libcamera/shaders/bayer_1x_packed.frag\n> +++ b/src/libcamera/shaders/bayer_1x_packed.frag\n> @@ -68,6 +68,16 @@ uniform sampler2D tex_y;\n>  uniform mat3 ccm;\n>  uniform vec3 blacklevel;\n>  uniform float gamma;\n> +uniform float contrast;\n> +\n> +float apply_contrast(float value, float contrastExp)\n> +{\n> +\t// Apply simple S-curve\n> +\tif (value < 0.5)\n> +\t\treturn 0.5 * pow(value / 0.5, contrastExp);\n> +\telse\n> +\t\treturn 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp);\n> +}\n>  \n>  void main(void)\n>  {\n> @@ -261,6 +271,17 @@ void main(void)\n>  \trgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]);\n>  \trgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]);\n>  \n> +\t/*\n> +\t * Contrast\n> +\t * contrastExp 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2)\n> +\t */\n> +\tfloat contrastExp = tan(clamp(contrast * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001));\n\nAs discussed at the sync, the constants should be either computed from\nnamed constants or explained in a source code comment (here and in the\nunpacked shader).\n\n0.78539816339744830962 = pi / 4\n1.5707963267948966 = pi / 2\n\nPassing contrastExp value as a uniform is another option.\n\nWith either of these:\n\nReviewed-by: Milan Zamazal <mzamazal@redhat.com>\n\n> +\n> +\trgb = clamp(rgb, 0.0, 1.0);\n> +\trgb.r = apply_contrast(rgb.r, contrastExp);\n> +\trgb.g = apply_contrast(rgb.g, contrastExp);\n> +\trgb.b = apply_contrast(rgb.b, contrastExp);\n> +\n>  \t/* Apply gamma after colour correction */\n>  \trgb = pow(rgb, vec3(gamma));\n>  \n> diff --git a/src/libcamera/shaders/bayer_unpacked.frag b/src/libcamera/shaders/bayer_unpacked.frag\n> index aba11a87f..114e32058 100644\n> --- a/src/libcamera/shaders/bayer_unpacked.frag\n> +++ b/src/libcamera/shaders/bayer_unpacked.frag\n> @@ -27,6 +27,16 @@ varying vec4            xCoord;\n>  uniform mat3            ccm;\n>  uniform vec3            blacklevel;\n>  uniform float           gamma;\n> +uniform float           contrast;\n> +\n> +float apply_contrast(float value, float contrastExp)\n> +{\n> +    // Apply simple S-curve\n> +    if (value < 0.5)\n> +        return 0.5 * pow(value / 0.5, contrastExp);\n> +    else\n> +        return 1.0 - 0.5 * pow((1.0 - value) / 0.5, contrastExp);\n> +}\n>  \n>  void main(void) {\n>      vec3 rgb;\n> @@ -156,6 +166,17 @@ void main(void) {\n>      rgb.g = (rin * ccm[1][0]) + (gin * ccm[1][1]) + (bin * ccm[1][2]);\n>      rgb.b = (rin * ccm[2][0]) + (gin * ccm[2][1]) + (bin * ccm[2][2]);\n>  \n> +    /*\n> +     * Contrast\n> +     * Convert 0..2 contrast to 0..infinity; avoid actual infinity at tan(pi/2)\n> +     */\n> +    float contrastExp = tan(clamp(contrast * 0.78539816339744830962, 0.0, 1.5707963267948966 - 0.00001));\n> +\n> +    rgb = clamp(rgb, 0.0, 1.0);\n> +    rgb.r = apply_contrast(rgb.r, contrastExp);\n> +    rgb.g = apply_contrast(rgb.g, contrastExp);\n> +    rgb.b = apply_contrast(rgb.b, contrastExp);\n> +\n>      /* Apply gamma after colour correction */\n>      rgb = pow(rgb, vec3(gamma));","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 1C1CFBD7D8\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 17 Dec 2025 13:07:01 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1F44D61A4E;\n\tWed, 17 Dec 2025 14:07:00 +0100 (CET)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4204761A35\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 17 Dec 2025 14:06:58 +0100 (CET)","from mail-wm1-f72.google.com (mail-wm1-f72.google.com\n\t[209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-593-lWVA9gPKOjiqHkPm1UCkQw-1; Wed, 17 Dec 2025 08:06:54 -0500","by mail-wm1-f72.google.com with SMTP id\n\t5b1f17b1804b1-4779da35d27so53750565e9.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 17 Dec 2025 05:06:54 -0800 (PST)","from mzamazal-thinkpadp1gen7.tpbc.csb ([213.175.46.86])\n\tby smtp.gmail.com with ESMTPSA id\n\t5b1f17b1804b1-47bdc222061sm35957595e9.9.2025.12.17.05.06.52\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 17 Dec 2025 05:06:52 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"fzjfEDT0\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1765976817;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=47wjtrR2P2rYrhncHFkM9WMrYtmiBCYKRN02HLizakQ=;\n\tb=fzjfEDT0IK3RJsmedC2Efa2OxSFKQwgS6Zgovm2JngCbk9QvVtCs1/VlD5V2zbi/S+QwkH\n\tFqYl3lm5oePka988pCL+pQlcVFEI4gF9H7z/OHielPvKPyOej9I7lFl0VFEIuWp9HBYVlo\n\tujFBAqYWS/jKx203v0CAJEpQ5gXFMzk=","X-MC-Unique":"lWVA9gPKOjiqHkPm1UCkQw-1","X-Mimecast-MFC-AGG-ID":"lWVA9gPKOjiqHkPm1UCkQw_1765976813","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1765976813; x=1766581613;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject\n\t:date:message-id:reply-to;\n\tbh=47wjtrR2P2rYrhncHFkM9WMrYtmiBCYKRN02HLizakQ=;\n\tb=LQNmqO3mJeEXnhMcG9kX8QRy2hmHdjIgTgBXhTaf33fWecdSCCt3yzLld0OyP2YKr6\n\tvQX9kAYbKQ1/OBRDayCYaTDt+BAoPT4FMENBqx+Q0EeAaFYaDAFxGVCvlQBSte6UsG7K\n\tPj4P9BtwZp8QvO7epPjev1xkoZNqbdah84qdQiKmRh0RRN9GwFYNA++skTkgPgYVnGVF\n\t28RaiVF1WxdSnD4q5z50eXs63dtDe63IOB833HXKqQbgWRJ9RAq5ayZQxLyNkRxadA2V\n\tXmt70+1eCQ+aC8Hig2NNudwGXVgNtftq+XZVx3Dfa+8+37zMG4dFxfTqRerjog7x4BJV\n\tNWTg==","X-Gm-Message-State":"AOJu0YxFDg+65pVXvvYmlVrcz4V/ptrVvqB2WcUB/u0mTvw8Zg92ehgV\n\te1kx9KiDqDhSJJE7zU1kwaxbIKDVwp0TVIpx8Kzt8TvreZe66IEIeWqDav1pQfvs1XGjkLkl1xD\n\tIYzJKlSNLUlxGNcmZejuL5PfFfkSP+vJEX69J4D4HRPTdH1cCW0G1GMcm2rdnonDbE7mM4wuvhi\n\tw=","X-Gm-Gg":"AY/fxX5GTFZKAIIGq4fKiTCLejytLz+CZnJ0bxtOB1d1FedtfuWQM6xAkdKcjdHEFN/\n\tpUYRPWXFjUSU7VT6DNKiqbMprv3by3Gsm36aXSFglmGIM6zwNFtjsl+GyCHublVP/bisoJe0e+R\n\tbMZg8IE7nZSz7B8iptZwuOXO3YIlgs68dPDNBjLhMSgaTE5XFczP82ruYjSzY1x6Phi/KDS+8E4\n\tpohu6YGGw11gkEcVDqxJ9I+jeIkhtEYJIAFIyGx1Tuq3MTFxt11mPDjrkPwzGkSSc21ciolUD+n\n\tlWYlUS9OClHO2Hx66XmGvlKWh/SSSteFHobq23Dp0m4Ylu87Zwg8VzFRma6olWttV+aV+UWAoMS\n\tqrvK7umRTvu7j+h+h2U+gOnexcg==","X-Received":["by 2002:a05:600d:8401:b0:47a:935f:61a0 with SMTP id\n\t5b1f17b1804b1-47a935f64f6mr142969905e9.0.1765976813495; \n\tWed, 17 Dec 2025 05:06:53 -0800 (PST)","by 2002:a05:600d:8401:b0:47a:935f:61a0 with SMTP id\n\t5b1f17b1804b1-47a935f64f6mr142969675e9.0.1765976813071; \n\tWed, 17 Dec 2025 05:06:53 -0800 (PST)"],"X-Google-Smtp-Source":"AGHT+IGfLxEtSqivQY8Fq95K6h42yEV0NcdPMss1/eyPoZglvIiPjzEQu0c8xfI7atCNElIihGtlig==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Bryan O'Donoghue <bryan.odonoghue@linaro.org>","Cc":"libcamera-devel@lists.libcamera.org,  pavel@ucw.cz","Subject":"Re: [PATCH v9 10/26] libcamera: shaders: Add support for contrast","In-Reply-To":"<20251217100138.82525-11-bryan.odonoghue@linaro.org> (Bryan\n\tO'Donoghue's message of \"Wed, 17 Dec 2025 10:01:22 +0000\")","References":"<20251217100138.82525-1-bryan.odonoghue@linaro.org>\n\t<20251217100138.82525-11-bryan.odonoghue@linaro.org>","Date":"Wed, 17 Dec 2025 14:06:51 +0100","Message-ID":"<85ldj1b6l0.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"A05DVfoIuTYyJjoITRB88bv71ZhcSsG9GQ1NTnkPYUI_1765976813","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]