Show a patch.

GET /api/patches/21161/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 21161,
    "url": "https://patchwork.libcamera.org/api/patches/21161/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/21161/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20240904074500.106019-2-mzamazal@redhat.com>",
    "date": "2024-09-04T07:44:58",
    "name": "[1/2] libcamera: software_isp: Add contrast algorithm",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "70a6e07a623c7c14a76267316d701f81a259ee48",
    "submitter": {
        "id": 177,
        "url": "https://patchwork.libcamera.org/api/people/177/?format=api",
        "name": "Milan Zamazal",
        "email": "mzamazal@redhat.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/21161/mbox/",
    "series": [
        {
            "id": 4561,
            "url": "https://patchwork.libcamera.org/api/series/4561/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4561",
            "date": "2024-09-04T07:44:57",
            "name": "Add contrast control to software ISP",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/4561/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/21161/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/21161/checks/",
    "tags": {},
    "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 99F0DC324C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  4 Sep 2024 07:45:17 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 42065634E9;\n\tWed,  4 Sep 2024 09:45:17 +0200 (CEST)",
            "from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 48550634CB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  4 Sep 2024 09:45:14 +0200 (CEST)",
            "from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com\n\t(ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63])\n\tby relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n\tcipher=TLS_AES_256_GCM_SHA384) id us-mta-70-s5wBryNwNO67VyqUo3tr9Q-1;\n\tWed, 04 Sep 2024 03:45:11 -0400",
            "from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com\n\t(mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com\n\t[10.30.177.15])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (2048 bits)\n\tserver-digest SHA256) (No client certificate requested)\n\tby mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTPS\n\tid C57191955E9D for <libcamera-devel@lists.libcamera.org>;\n\tWed,  4 Sep 2024 07:45:10 +0000 (UTC)",
            "from nuthatch.redhat.com (unknown [10.45.225.152])\n\tby mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTP id A95F91956088; Wed,  4 Sep 2024 07:45:09 +0000 (UTC)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"KKizoD0i\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1725435913;\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\tcontent-transfer-encoding:content-transfer-encoding:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=xe9EiWkpEvv3s1Xx1vmcLBWhu8z0mKiMuU/c2VecRKs=;\n\tb=KKizoD0i6FgAskeQkvCPcit9lWyKR3DB5bJdJHmXz8MDrsB6ner45gYbEswi+BCQlcENmF\n\tryuGx4/LRgHmbQJ+J75Ed+GX0kgKVSl+QTVN4846rGXZ0eF3h468b0rTBjS+W8b8Cwyvmb\n\t8ILX7qmPrZL/+JZ8fTi6Qe82J4vfkIw=",
        "X-MC-Unique": "s5wBryNwNO67VyqUo3tr9Q-1",
        "From": "Milan Zamazal <mzamazal@redhat.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Milan Zamazal <mzamazal@redhat.com>",
        "Subject": "[PATCH 1/2] libcamera: software_isp: Add contrast algorithm",
        "Date": "Wed,  4 Sep 2024 09:44:58 +0200",
        "Message-ID": "<20240904074500.106019-2-mzamazal@redhat.com>",
        "In-Reply-To": "<20240904074500.106019-1-mzamazal@redhat.com>",
        "References": "<20240904074500.106019-1-mzamazal@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.0 on 127.0.0.2",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain; charset=\"US-ASCII\"; x-default=true",
        "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>"
    },
    "content": "Software ISP is currently fully automatic and doesn't allow image\nmodifications by explicitly set control values.  The user has no means\nto make the image looking better.\n\nThis patch introduces contrast control algorithm, which can improve\ne.g. a flat looking image.  Based on the provided contrast value with a\nrange 0..infinity and 1.0 being the normal value, it applies a simple\nS-curve modification to the image.  The contrast algorithm just handles\nthe provided values, while the S-curve is applied in the gamma algorithm\non the computed gamma curve whenever the contrast value changes.  Since\nthe algorithm is applied only on the lookup table already present, its\noverhead is negligible.\n\nThis is a preparation patch without actually activating the contrast\nalgorithm, which will be done in the following patch.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\n---\n src/ipa/simple/algorithms/contrast.cpp | 45 ++++++++++++++++++++++++++\n src/ipa/simple/algorithms/contrast.h   | 37 +++++++++++++++++++++\n src/ipa/simple/algorithms/gamma.cpp    | 22 ++++++++++---\n src/ipa/simple/algorithms/meson.build  |  1 +\n src/ipa/simple/ipa_context.h           |  4 +++\n 5 files changed, 104 insertions(+), 5 deletions(-)\n create mode 100644 src/ipa/simple/algorithms/contrast.cpp\n create mode 100644 src/ipa/simple/algorithms/contrast.h",
    "diff": "diff --git a/src/ipa/simple/algorithms/contrast.cpp b/src/ipa/simple/algorithms/contrast.cpp\nnew file mode 100644\nindex 00000000..75bf37ad\n--- /dev/null\n+++ b/src/ipa/simple/algorithms/contrast.cpp\n@@ -0,0 +1,45 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024, Red Hat Inc.\n+ *\n+ * Contrast adjustment\n+ */\n+\n+#include \"contrast.h\"\n+\n+#include <optional>\n+\n+#include <libcamera/base/log.h>\n+\n+#include \"control_ids.h\"\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(IPASoftContrast)\n+\n+namespace ipa::soft::algorithms {\n+\n+int Contrast::configure(typename Module::Context &context,\n+\t\t\t[[maybe_unused]] const typename Module::Config &configInfo)\n+{\n+\tcontext.activeState.knobs.contrast = std::optional<double>();\n+\treturn 0;\n+}\n+\n+void Contrast::queueRequest(typename Module::Context &context,\n+\t\t\t    [[maybe_unused]] const uint32_t frame,\n+\t\t\t    [[maybe_unused]] typename Module::FrameContext &frameContext,\n+\t\t\t    const ControlList &controls)\n+{\n+\tconst auto &contrast = controls.get(controls::Contrast);\n+\tif (contrast.has_value()) {\n+\t\tcontext.activeState.knobs.contrast = contrast;\n+\t\tLOG(IPASoftContrast, Debug) << \"Setting contrast to\" << contrast.value();\n+\t}\n+}\n+\n+REGISTER_IPA_ALGORITHM(Contrast, \"Contrast\")\n+\n+} /* namespace ipa::soft::algorithms */\n+\n+} /* namespace libcamera */\ndiff --git a/src/ipa/simple/algorithms/contrast.h b/src/ipa/simple/algorithms/contrast.h\nnew file mode 100644\nindex 00000000..0b393309\n--- /dev/null\n+++ b/src/ipa/simple/algorithms/contrast.h\n@@ -0,0 +1,37 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2024, Red Hat Inc.\n+ *\n+ * Contrast adjustment\n+ */\n+\n+#pragma once\n+\n+#include <libcamera/controls.h>\n+\n+#include \"algorithm.h\"\n+\n+namespace libcamera {\n+\n+namespace ipa::soft::algorithms {\n+\n+class Contrast : public Algorithm\n+{\n+public:\n+\tContrast() = default;\n+\t~Contrast() = default;\n+\n+\tint configure(typename Module::Context &context,\n+\t\t      const typename Module::Config &configInfo)\n+\t\toverride;\n+\n+\tvoid queueRequest(typename Module::Context &context,\n+\t\t\t  const uint32_t frame,\n+\t\t\t  typename Module::FrameContext &frameContext,\n+\t\t\t  const ControlList &controls)\n+\t\toverride;\n+};\n+\n+} /* namespace ipa::soft::algorithms */\n+\n+} /* namespace libcamera */\ndiff --git a/src/ipa/simple/algorithms/gamma.cpp b/src/ipa/simple/algorithms/gamma.cpp\nindex b03dff25..fe59ca9f 100644\n--- a/src/ipa/simple/algorithms/gamma.cpp\n+++ b/src/ipa/simple/algorithms/gamma.cpp\n@@ -32,15 +32,26 @@ int Gamma::init(IPAContext &context,\n void Gamma::updateGammaTable(IPAContext &context)\n {\n \tauto &gammaTable = context.activeState.gamma.gammaTable;\n-\tauto blackLevel = context.activeState.black.level;\n+\tconst auto blackLevel = context.activeState.black.level;\n \tconst unsigned int blackIndex =\n \t\tblackLevel * IPAActiveState::kGammaLookupSize;\n+\tconst auto contrast = context.activeState.knobs.contrast.value_or(1.0);\n+\n \tstd::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, 0);\n \tconst float divisor = kGammaLookupSize - blackIndex - 1.0;\n-\tfor (unsigned int i = blackIndex; i < kGammaLookupSize; i++)\n-\t\tgammaTable[i] = UINT8_MAX * powf((i - blackIndex) / divisor,\n-\t\t\t\t\t\t context.configuration.gamma);\n+\tfor (unsigned int i = blackIndex; i < kGammaLookupSize; i++) {\n+\t\tdouble normalized = (i - blackIndex) / divisor;\n+\t\t/* Apply simple S-curve */\n+\t\tif (normalized < 0.5)\n+\t\t\tnormalized = 0.5 * std::pow(normalized / 0.5, contrast);\n+\t\telse\n+\t\t\tnormalized = 1.0 - 0.5 * std::pow((1.0 - normalized) / 0.5, contrast);\n+\t\tgammaTable[i] = UINT8_MAX *\n+\t\t\t\tstd::pow(normalized, context.configuration.gamma);\n+\t}\n+\n \tcontext.activeState.gamma.blackLevel = blackLevel;\n+\tcontext.activeState.gamma.contrast = contrast;\n }\n \n void Gamma::prepare(IPAContext &context,\n@@ -53,7 +64,8 @@ void Gamma::prepare(IPAContext &context,\n \t * since the black level gets updated only if a lower value is observed,\n \t * it's not permanently prone to minor fluctuations or rounding errors.\n \t */\n-\tif (context.activeState.gamma.blackLevel != context.activeState.black.level)\n+\tif (context.activeState.gamma.blackLevel != context.activeState.black.level ||\n+\t    context.activeState.gamma.contrast != context.activeState.knobs.contrast)\n \t\tupdateGammaTable(context);\n }\n \ndiff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build\nindex ec2638c2..73dc077e 100644\n--- a/src/ipa/simple/algorithms/meson.build\n+++ b/src/ipa/simple/algorithms/meson.build\n@@ -4,6 +4,7 @@ soft_simple_ipa_algorithms = files([\n     'awb.cpp',\n     'agc.cpp',\n     'blc.cpp',\n+    'contrast.cpp',\n     'gamma.cpp',\n     'lut.cpp',\n ])\ndiff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\nindex 08f965f4..6655baa9 100644\n--- a/src/ipa/simple/ipa_context.h\n+++ b/src/ipa/simple/ipa_context.h\n@@ -46,7 +46,11 @@ struct IPAActiveState {\n \tstruct {\n \t\tstd::array<double, kGammaLookupSize> gammaTable;\n \t\tdouble blackLevel;\n+\t\tdouble contrast;\n \t} gamma;\n+\tstruct {\n+\t\tstd::optional<double> contrast; // 0..inf, 1 = neutral\n+\t} knobs;\n };\n \n struct IPAFrameContext : public FrameContext {\n",
    "prefixes": [
        "1/2"
    ]
}