Show a patch.

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

{
    "id": 21600,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/21600/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/21600/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/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": "<20241011182800.1750589-4-mzamazal@redhat.com>",
    "date": "2024-10-11T18:27:58",
    "name": "[v3,3/4] libcamera: software_isp: Add support for contrast control",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "439086f949ce569bfa858f3bfffcc56c633c601a",
    "submitter": {
        "id": 177,
        "url": "https://patchwork.libcamera.org/api/1.1/people/177/?format=api",
        "name": "Milan Zamazal",
        "email": "mzamazal@redhat.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/21600/mbox/",
    "series": [
        {
            "id": 4688,
            "url": "https://patchwork.libcamera.org/api/1.1/series/4688/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4688",
            "date": "2024-10-11T18:27:55",
            "name": "Add contrast control to software ISP",
            "version": 3,
            "mbox": "https://patchwork.libcamera.org/series/4688/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/21600/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/21600/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 71ADAC3260\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 11 Oct 2024 18:28:20 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 008E965394;\n\tFri, 11 Oct 2024 20:28:19 +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 6F5C465392\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 11 Oct 2024 20:28:16 +0200 (CEST)",
            "from mx-prod-mc-01.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-94-fgvTkO6uNBiXfl3fudIVtg-1;\n\tFri, 11 Oct 2024 14:28:12 -0400",
            "from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com\n\t(mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])\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-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTPS id 4609D1956096; Fri, 11 Oct 2024 18:28:11 +0000 (UTC)",
            "from nuthatch.redhat.com (unknown [10.45.224.99])\n\tby mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTP id ECA0430001A3; Fri, 11 Oct 2024 18:28: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=\"MVjmQ1W3\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1728671295;\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=usHtf8u5MuPnmymKcXXyfopIWLsnb/w1BVM1pLW3SZM=;\n\tb=MVjmQ1W3tuOpMXRvVE+W/TL5g6iCRVpEDWOr4XS+jN8sjWPY9tkjUns+SftSpeMghuKLTq\n\tHIdRpQWY0P6JjKDS4lsMYcvZM2oXmRD4Pq1uBWXZKnfTtRFGK+NPM6JJxGt52MQRTuP8Nb\n\tGbSeDkSTEMHfcyQ0BThOyygK/Qftx58=",
        "X-MC-Unique": "fgvTkO6uNBiXfl3fudIVtg-1",
        "From": "Milan Zamazal <mzamazal@redhat.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Milan Zamazal <mzamazal@redhat.com>,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>",
        "Subject": "[PATCH v3 3/4] libcamera: software_isp: Add support for contrast\n\tcontrol",
        "Date": "Fri, 11 Oct 2024 20:27:58 +0200",
        "Message-ID": "<20241011182800.1750589-4-mzamazal@redhat.com>",
        "In-Reply-To": "<20241011182800.1750589-1-mzamazal@redhat.com>",
        "References": "<20241011182800.1750589-1-mzamazal@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.4",
        "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 support for contrast control, 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 providing the control\nitself, which is done in the following patch.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\n---\n src/ipa/simple/algorithms/lut.cpp | 38 +++++++++++++++++++++++++++----\n src/ipa/simple/algorithms/lut.h   |  5 ++++\n src/ipa/simple/ipa_context.h      |  8 +++++++\n 3 files changed, 46 insertions(+), 5 deletions(-)",
    "diff": "diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp\nindex 9744e773a..ffded0594 100644\n--- a/src/ipa/simple/algorithms/lut.cpp\n+++ b/src/ipa/simple/algorithms/lut.cpp\n@@ -9,14 +9,19 @@\n \n #include <algorithm>\n #include <cmath>\n+#include <optional>\n #include <stdint.h>\n \n #include <libcamera/base/log.h>\n \n #include \"simple/ipa_context.h\"\n \n+#include \"control_ids.h\"\n+\n namespace libcamera {\n \n+LOG_DEFINE_CATEGORY(IPASoftLut)\n+\n namespace ipa::soft::algorithms {\n \n int Lut::configure(IPAContext &context,\n@@ -24,24 +29,46 @@ int Lut::configure(IPAContext &context,\n {\n \t/* Gamma value is fixed */\n \tcontext.configuration.gamma = 0.5;\n+\tcontext.activeState.knobs.contrast = std::optional<double>();\n \tupdateGammaTable(context);\n \n \treturn 0;\n }\n \n+void Lut::queueRequest(typename Module::Context &context,\n+\t\t       [[maybe_unused]] const uint32_t frame,\n+\t\t       [[maybe_unused]] typename Module::FrameContext &frameContext,\n+\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(IPASoftLut, Debug) << \"Setting contrast to \" << contrast.value();\n+\t}\n+}\n+\n void Lut::updateGammaTable(IPAContext &context)\n {\n \tauto &gammaTable = context.activeState.gamma.gammaTable;\n-\tauto blackLevel = context.activeState.blc.level;\n+\tconst auto blackLevel = context.activeState.blc.level;\n \tconst unsigned int blackIndex = blackLevel * gammaTable.size() / 256;\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 = gammaTable.size() - blackIndex - 1.0;\n-\tfor (unsigned int i = blackIndex; i < gammaTable.size(); i++)\n-\t\tgammaTable[i] = UINT8_MAX * std::pow((i - blackIndex) / divisor,\n-\t\t\t\t\t\t     context.configuration.gamma);\n+\tfor (unsigned int i = blackIndex; i < gammaTable.size(); 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 Lut::prepare(IPAContext &context,\n@@ -55,7 +82,8 @@ void Lut::prepare(IPAContext &context,\n \t * observed, it's not permanently prone to minor fluctuations or\n \t * rounding errors.\n \t */\n-\tif (context.activeState.gamma.blackLevel != context.activeState.blc.level)\n+\tif (context.activeState.gamma.blackLevel != context.activeState.blc.level ||\n+\t    context.activeState.gamma.contrast != context.activeState.knobs.contrast)\n \t\tupdateGammaTable(context);\n \n \tauto &gains = context.activeState.gains;\ndiff --git a/src/ipa/simple/algorithms/lut.h b/src/ipa/simple/algorithms/lut.h\nindex b635987d0..ef2df147c 100644\n--- a/src/ipa/simple/algorithms/lut.h\n+++ b/src/ipa/simple/algorithms/lut.h\n@@ -20,6 +20,11 @@ public:\n \t~Lut() = default;\n \n \tint configure(IPAContext &context, const IPAConfigInfo &configInfo) override;\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 \tvoid prepare(IPAContext &context,\n \t\t     const uint32_t frame,\n \t\t     IPAFrameContext &frameContext,\ndiff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\nindex 491448ece..3a8d2d59c 100644\n--- a/src/ipa/simple/ipa_context.h\n+++ b/src/ipa/simple/ipa_context.h\n@@ -8,8 +8,11 @@\n #pragma once\n \n #include <array>\n+#include <optional>\n #include <stdint.h>\n \n+#include <libcamera/controls.h>\n+\n #include <libipa/fc_queue.h>\n \n namespace libcamera {\n@@ -44,7 +47,12 @@ struct IPAActiveState {\n \tstruct {\n \t\tstd::array<double, kGammaLookupSize> gammaTable;\n \t\tuint8_t blackLevel;\n+\t\tdouble contrast;\n \t} gamma;\n+\tstruct {\n+\t\t/* 0..inf range, 1.0 = normal */\n+\t\tstd::optional<double> contrast;\n+\t} knobs;\n };\n \n struct IPAFrameContext : public FrameContext {\n",
    "prefixes": [
        "v3",
        "3/4"
    ]
}