From patchwork Thu Mar 9 14:25:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 18374 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B3AA9C32A4 for ; Thu, 9 Mar 2023 14:26:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4709062712; Thu, 9 Mar 2023 15:26:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1678371990; bh=a834tRZgWj+HQJbehTbn0uHl1GWwsCL3m61QJJX++a4=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=MvASTM+DzR+Da5PuAPaRv9DDRU0snJ2nBb/s5+BoRVwEP5oOm4skDHMvDYSEteyRR eaxia4339yjjfbxpxQyYvfWrpYr0QwgEq2RZYRnLKG7uORYjYSBd7ymXPzp7VKStZu qV/GaOim8MCylZTqyCBvCfJ+CxFJ0+cm6Qz4SwSUozgEsSElZwjGetmnDxnRYqPSaY nADueC0SB3DYLnMyhgtj+Pa8XhRhPRuR81nvdzW8MJBttf8gWaSWjI91iuUCoIKO+2 JO+6PsutFl9shcg/T5NNgwZ0tv8Zub/ZP73h7Az1CHV8xZtj3jML9tDipMkEY+Q8E4 OpLH0tf+yLe5A== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A104C626F4 for ; Thu, 9 Mar 2023 15:26:21 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="sYGHLIDD"; dkim-atps=neutral Received: from desky.lan (91-154-32-225.elisa-laajakaista.fi [91.154.32.225]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 33D2B886; Thu, 9 Mar 2023 15:26:21 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1678371981; bh=a834tRZgWj+HQJbehTbn0uHl1GWwsCL3m61QJJX++a4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sYGHLIDDK+fOjCLEDeFEXLrj6+3xsGqOG47c+GXOyRm0NJkwefJrlMws1cj9EzMxJ 46cq7MEAwrfp/FeZ05l5Ty2EHHZsgoKDVAMbXgPNOj/Gv61uSQ4aHAjUABqlU1jnoY LQeLvdMhdFaGcFzDkYRMckgxDS/tKhcsrMh0+ulA= To: libcamera-devel@lists.libcamera.org Date: Thu, 9 Mar 2023 16:25:59 +0200 Message-Id: <20230309142601.70556-14-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230309142601.70556-1-tomi.valkeinen@ideasonboard.com> References: <20230309142601.70556-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 13/15] py: Move Color Space and Transform classes to separate files X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Tomi Valkeinen via libcamera-devel From: Tomi Valkeinen Reply-To: Tomi Valkeinen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Move Color Space and Transform classes to separate files from the main py_main.cpp, for clarity. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart --- src/py/libcamera/meson.build | 2 + src/py/libcamera/py_color_space.cpp | 71 +++++++++++++++++ src/py/libcamera/py_main.cpp | 115 ++-------------------------- src/py/libcamera/py_transform.cpp | 81 ++++++++++++++++++++ 4 files changed, 159 insertions(+), 110 deletions(-) create mode 100644 src/py/libcamera/py_color_space.cpp create mode 100644 src/py/libcamera/py_transform.cpp diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build index af19ffdd..f87b1b4d 100644 --- a/src/py/libcamera/meson.build +++ b/src/py/libcamera/meson.build @@ -14,10 +14,12 @@ pybind11_dep = pybind11_proj.get_variable('pybind11_dep') pycamera_sources = files([ 'py_camera_manager.cpp', + 'py_color_space.cpp', 'py_enums.cpp', 'py_geometry.cpp', 'py_helpers.cpp', 'py_main.cpp', + 'py_transform.cpp', ]) # Generate controls diff --git a/src/py/libcamera/py_color_space.cpp b/src/py/libcamera/py_color_space.cpp new file mode 100644 index 00000000..4bd86320 --- /dev/null +++ b/src/py/libcamera/py_color_space.cpp @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2022, Tomi Valkeinen + * + * Python bindings - Color Space classes + */ + +#include +#include + +#include +#include +#include + +namespace py = pybind11; + +using namespace libcamera; + +void init_py_color_space(py::module &m) +{ + auto pyColorSpace = py::class_(m, "ColorSpace"); + auto pyColorSpacePrimaries = py::enum_(pyColorSpace, "Primaries"); + auto pyColorSpaceTransferFunction = py::enum_(pyColorSpace, "TransferFunction"); + auto pyColorSpaceYcbcrEncoding = py::enum_(pyColorSpace, "YcbcrEncoding"); + auto pyColorSpaceRange = py::enum_(pyColorSpace, "Range"); + + pyColorSpace + .def(py::init([](ColorSpace::Primaries primaries, + ColorSpace::TransferFunction transferFunction, + ColorSpace::YcbcrEncoding ycbcrEncoding, + ColorSpace::Range range) { + return ColorSpace(primaries, transferFunction, ycbcrEncoding, range); + }), py::arg("primaries"), py::arg("transferFunction"), + py::arg("ycbcrEncoding"), py::arg("range")) + .def(py::init([](ColorSpace &other) { return other; })) + .def("__str__", [](ColorSpace &self) { + return ""; + }) + .def_readwrite("primaries", &ColorSpace::primaries) + .def_readwrite("transferFunction", &ColorSpace::transferFunction) + .def_readwrite("ycbcrEncoding", &ColorSpace::ycbcrEncoding) + .def_readwrite("range", &ColorSpace::range) + .def_static("Raw", []() { return ColorSpace::Raw; }) + .def_static("Srgb", []() { return ColorSpace::Srgb; }) + .def_static("Sycc", []() { return ColorSpace::Sycc; }) + .def_static("Smpte170m", []() { return ColorSpace::Smpte170m; }) + .def_static("Rec709", []() { return ColorSpace::Rec709; }) + .def_static("Rec2020", []() { return ColorSpace::Rec2020; }); + + pyColorSpacePrimaries + .value("Raw", ColorSpace::Primaries::Raw) + .value("Smpte170m", ColorSpace::Primaries::Smpte170m) + .value("Rec709", ColorSpace::Primaries::Rec709) + .value("Rec2020", ColorSpace::Primaries::Rec2020); + + pyColorSpaceTransferFunction + .value("Linear", ColorSpace::TransferFunction::Linear) + .value("Srgb", ColorSpace::TransferFunction::Srgb) + .value("Rec709", ColorSpace::TransferFunction::Rec709); + + pyColorSpaceYcbcrEncoding + .value("Null", ColorSpace::YcbcrEncoding::None) + .value("Rec601", ColorSpace::YcbcrEncoding::Rec601) + .value("Rec709", ColorSpace::YcbcrEncoding::Rec709) + .value("Rec2020", ColorSpace::YcbcrEncoding::Rec2020); + + pyColorSpaceRange + .value("Full", ColorSpace::Range::Full) + .value("Limited", ColorSpace::Range::Limited); + +} diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp index 1069fd9c..1585b14a 100644 --- a/src/py/libcamera/py_main.cpp +++ b/src/py/libcamera/py_main.cpp @@ -40,11 +40,13 @@ LOG_DEFINE_CATEGORY(Python) */ static std::weak_ptr gCameraManager; -void init_py_enums(py::module &m); +void init_py_color_space(py::module &m); void init_py_controls_generated(py::module &m); +void init_py_enums(py::module &m); void init_py_formats_generated(py::module &m); void init_py_geometry(py::module &m); void init_py_properties_generated(py::module &m); +void init_py_transform(py::module &m); PYBIND11_MODULE(_libcamera, m) { @@ -52,6 +54,8 @@ PYBIND11_MODULE(_libcamera, m) init_py_controls_generated(m); init_py_geometry(m); init_py_properties_generated(m); + init_py_color_space(m); + init_py_transform(m); /* Forward declarations */ @@ -80,12 +84,6 @@ PYBIND11_MODULE(_libcamera, m) auto pyFrameMetadata = py::class_(m, "FrameMetadata"); auto pyFrameMetadataStatus = py::enum_(pyFrameMetadata, "Status"); auto pyFrameMetadataPlane = py::class_(pyFrameMetadata, "Plane"); - auto pyTransform = py::class_(m, "Transform"); - auto pyColorSpace = py::class_(m, "ColorSpace"); - auto pyColorSpacePrimaries = py::enum_(pyColorSpace, "Primaries"); - auto pyColorSpaceTransferFunction = py::enum_(pyColorSpace, "TransferFunction"); - auto pyColorSpaceYcbcrEncoding = py::enum_(pyColorSpace, "YcbcrEncoding"); - auto pyColorSpaceRange = py::enum_(pyColorSpace, "Range"); auto pyPixelFormat = py::class_(m, "PixelFormat"); init_py_formats_generated(m); @@ -455,109 +453,6 @@ PYBIND11_MODULE(_libcamera, m) pyFrameMetadataPlane .def_readwrite("bytes_used", &FrameMetadata::Plane::bytesused); - pyTransform - .def(py::init([](int rotation, bool hflip, bool vflip, bool transpose) { - bool ok; - - Transform t = transformFromRotation(rotation, &ok); - if (!ok) - throw std::invalid_argument("Invalid rotation"); - - if (hflip) - t ^= Transform::HFlip; - if (vflip) - t ^= Transform::VFlip; - if (transpose) - t ^= Transform::Transpose; - return t; - }), py::arg("rotation") = 0, py::arg("hflip") = false, - py::arg("vflip") = false, py::arg("transpose") = false) - .def(py::init([](Transform &other) { return other; })) - .def("__str__", [](Transform &self) { - return ""; - }) - .def_property("hflip", - [](Transform &self) { - return !!(self & Transform::HFlip); - }, - [](Transform &self, bool hflip) { - if (hflip) - self |= Transform::HFlip; - else - self &= ~Transform::HFlip; - }) - .def_property("vflip", - [](Transform &self) { - return !!(self & Transform::VFlip); - }, - [](Transform &self, bool vflip) { - if (vflip) - self |= Transform::VFlip; - else - self &= ~Transform::VFlip; - }) - .def_property("transpose", - [](Transform &self) { - return !!(self & Transform::Transpose); - }, - [](Transform &self, bool transpose) { - if (transpose) - self |= Transform::Transpose; - else - self &= ~Transform::Transpose; - }) - .def("inverse", [](Transform &self) { return -self; }) - .def("invert", [](Transform &self) { - self = -self; - }) - .def("compose", [](Transform &self, Transform &other) { - self = self * other; - }); - - pyColorSpace - .def(py::init([](ColorSpace::Primaries primaries, - ColorSpace::TransferFunction transferFunction, - ColorSpace::YcbcrEncoding ycbcrEncoding, - ColorSpace::Range range) { - return ColorSpace(primaries, transferFunction, ycbcrEncoding, range); - }), py::arg("primaries"), py::arg("transferFunction"), - py::arg("ycbcrEncoding"), py::arg("range")) - .def(py::init([](ColorSpace &other) { return other; })) - .def("__str__", [](ColorSpace &self) { - return ""; - }) - .def_readwrite("primaries", &ColorSpace::primaries) - .def_readwrite("transferFunction", &ColorSpace::transferFunction) - .def_readwrite("ycbcrEncoding", &ColorSpace::ycbcrEncoding) - .def_readwrite("range", &ColorSpace::range) - .def_static("Raw", []() { return ColorSpace::Raw; }) - .def_static("Srgb", []() { return ColorSpace::Srgb; }) - .def_static("Sycc", []() { return ColorSpace::Sycc; }) - .def_static("Smpte170m", []() { return ColorSpace::Smpte170m; }) - .def_static("Rec709", []() { return ColorSpace::Rec709; }) - .def_static("Rec2020", []() { return ColorSpace::Rec2020; }); - - pyColorSpacePrimaries - .value("Raw", ColorSpace::Primaries::Raw) - .value("Smpte170m", ColorSpace::Primaries::Smpte170m) - .value("Rec709", ColorSpace::Primaries::Rec709) - .value("Rec2020", ColorSpace::Primaries::Rec2020); - - pyColorSpaceTransferFunction - .value("Linear", ColorSpace::TransferFunction::Linear) - .value("Srgb", ColorSpace::TransferFunction::Srgb) - .value("Rec709", ColorSpace::TransferFunction::Rec709); - - pyColorSpaceYcbcrEncoding - .value("Null", ColorSpace::YcbcrEncoding::None) - .value("Rec601", ColorSpace::YcbcrEncoding::Rec601) - .value("Rec709", ColorSpace::YcbcrEncoding::Rec709) - .value("Rec2020", ColorSpace::YcbcrEncoding::Rec2020); - - pyColorSpaceRange - .value("Full", ColorSpace::Range::Full) - .value("Limited", ColorSpace::Range::Limited); - pyPixelFormat .def(py::init<>()) .def(py::init()) diff --git a/src/py/libcamera/py_transform.cpp b/src/py/libcamera/py_transform.cpp new file mode 100644 index 00000000..08783e29 --- /dev/null +++ b/src/py/libcamera/py_transform.cpp @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2022, Tomi Valkeinen + * + * Python bindings - Transform class + */ + +#include +#include + +#include +#include +#include + +namespace py = pybind11; + +using namespace libcamera; + +void init_py_transform(py::module &m) +{ + auto pyTransform = py::class_(m, "Transform"); + + pyTransform + .def(py::init([](int rotation, bool hflip, bool vflip, bool transpose) { + bool ok; + + Transform t = transformFromRotation(rotation, &ok); + if (!ok) + throw std::invalid_argument("Invalid rotation"); + + if (hflip) + t ^= Transform::HFlip; + if (vflip) + t ^= Transform::VFlip; + if (transpose) + t ^= Transform::Transpose; + return t; + }), py::arg("rotation") = 0, py::arg("hflip") = false, + py::arg("vflip") = false, py::arg("transpose") = false) + .def(py::init([](Transform &other) { return other; })) + .def("__str__", [](Transform &self) { + return ""; + }) + .def_property("hflip", + [](Transform &self) { + return !!(self & Transform::HFlip); + }, + [](Transform &self, bool hflip) { + if (hflip) + self |= Transform::HFlip; + else + self &= ~Transform::HFlip; + }) + .def_property("vflip", + [](Transform &self) { + return !!(self & Transform::VFlip); + }, + [](Transform &self, bool vflip) { + if (vflip) + self |= Transform::VFlip; + else + self &= ~Transform::VFlip; + }) + .def_property("transpose", + [](Transform &self) { + return !!(self & Transform::Transpose); + }, + [](Transform &self, bool transpose) { + if (transpose) + self |= Transform::Transpose; + else + self &= ~Transform::Transpose; + }) + .def("inverse", [](Transform &self) { return -self; }) + .def("invert", [](Transform &self) { + self = -self; + }) + .def("compose", [](Transform &self, Transform &other) { + self = self * other; + }); +}