From patchwork Tue Sep 29 16:39:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Plowman X-Patchwork-Id: 9867 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 D8100C3B5B for ; Tue, 29 Sep 2020 16:40:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A4B2B62213; Tue, 29 Sep 2020 18:40:13 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="HBTX5fo+"; dkim-atps=neutral Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F2956621C2 for ; Tue, 29 Sep 2020 18:40:08 +0200 (CEST) Received: by mail-wr1-x436.google.com with SMTP id x14so6134561wrl.12 for ; Tue, 29 Sep 2020 09:40:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=g9k5si71vIidZueH7m+O0H4368v3VtJ6f9kU5NAWJuA=; b=HBTX5fo+tjgVv6NRC9kOVzeHgt+mB+UqwN52MVjqrw857mzx02bVWWetMDKKmcGxm2 hxtxFWVSiTS+RJSkIo8BBZygZ2ut/ormxKZylq/3R8lG6AzLiL3BXIVO4SOOZTGBNTcl GQVYnsuyL11O5EDeB8JxOpFaSQFI4Q4fBUIumquZUtfbKzNs/WxOAhXkKJnRcEJTX8TH z/VddfaQ3kxAySN4T19u0kVmonwi2X2710D3pRJuci6TxBXVvKKKkpy1UYwUQjbb6qQI HXR7ZRYMLMKwgn+op5ygvYD9V9XwO+O1nOvRSwam9zQv2R4LJRwQ29sQMhQO5+4lld+R w+Rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=g9k5si71vIidZueH7m+O0H4368v3VtJ6f9kU5NAWJuA=; b=cyRjiMV75BDvOXlKsLYhlU+Dp5xlHCBqw2/DgQ6YnjxPOrbTF2+9JIrFA4Cob7xR+c o7oFRhJvZc6q0nGp42cmqbEon6qFbI193z6lKuGZxqFe/zKwSW1k/9k9Y6nuko2jPewb +ud2aZOO4hzEIHKNN3FjrGJbeaHwqVD5a/RZSesaeYdy/ysDyBQCYXAnnCV7k/yrx4U6 RUk0GCKLcjsv30VJ1Nv4EpE0OTqvb1Y/glsjO2zopLuRauIXsM19HUnpIxOR7hzj5DSj TmMGZTijXdPrvVDw0y0b27Yd/TOiMFYUM8WAVJiOKcZIpxWwptnUbE9cBTgamra8M34A nN5g== X-Gm-Message-State: AOAM531WcW6XGSAhWjb9LdjY26rWNm+yP0y3/5wBSObz1H4XGVMgxbK1 7ueycyfP7r+2oCW8p66enc+p51XfqQDVjA== X-Google-Smtp-Source: ABdhPJzVl4LGEGQegwf+bOMrTBL24ei5OWagthEHRR4f/CUN0U5ZEMdoxi+XcXYuozSTNB2FG7fbeQ== X-Received: by 2002:adf:e58b:: with SMTP id l11mr5680562wrm.210.1601397608272; Tue, 29 Sep 2020 09:40:08 -0700 (PDT) Received: from pi4-davidp.lan (plowpeople3.plus.com. [80.229.223.72]) by smtp.gmail.com with ESMTPSA id q12sm6977393wrs.48.2020.09.29.09.40.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 09:40:07 -0700 (PDT) From: David Plowman To: libcamera-devel@lists.libcamera.org Date: Tue, 29 Sep 2020 17:39:58 +0100 Message-Id: <20200929164000.15429-5-david.plowman@raspberrypi.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200929164000.15429-1-david.plowman@raspberrypi.com> References: <20200929164000.15429-1-david.plowman@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 4/6] libcamera: Add geometry helper functions 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" These functions are aimed at making it easier to calculate cropping rectangles, particularly in order to implement digital zoom. Signed-off-by: David Plowman Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/geometry.h | 20 ++++++ src/libcamera/geometry.cpp | 129 +++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h index 02fb63c0..0447ee3e 100644 --- a/include/libcamera/geometry.h +++ b/include/libcamera/geometry.h @@ -13,6 +13,8 @@ namespace libcamera { +class Rectangle; + class Size { public: @@ -93,8 +95,17 @@ public: std::max(height, expand.height) }; } + + Size alignedDownToAspectRatio(const Size &ratio) const; + Size alignedUpToAspectRatio(const Size &ratio) const; + + Rectangle centredTo(const Rectangle ®ion, + int offsetX = 0, int offsetY = 0) const; }; +Size operator*(const Size &size, float f); +Size operator/(const Size &size, float f); + bool operator==(const Size &lhs, const Size &rhs); bool operator<(const Size &lhs, const Size &rhs); @@ -176,6 +187,11 @@ public: { } + constexpr explicit Rectangle(const Size &size) + : x(0), y(0), width(size.width), height(size.height) + { + } + int x; int y; unsigned int width; @@ -183,6 +199,10 @@ public: bool isNull() const { return !width && !height; } const std::string toString() const; + + Size size() const; + + Rectangle boundedTo(const Rectangle &boundary) const; }; bool operator==(const Rectangle &lhs, const Rectangle &rhs); diff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp index b12e1a62..649ee179 100644 --- a/src/libcamera/geometry.cpp +++ b/src/libcamera/geometry.cpp @@ -143,6 +143,88 @@ const std::string Size::toString() const * height of this size and the \a expand size */ +/** + * \brief Align down to the aspect ratio given by \a ratio + * \param[in] ratio The size whose aspect ratio to align down to + * \return A Size whose width and height are equal to the width and height + * of this Size aligned down to the aspect ratio of \a ratio + */ +Size Size::alignedDownToAspectRatio(const Size &ratio) const +{ + uint64_t ratio1 = static_cast(width) * + static_cast(ratio.height); + uint64_t ratio2 = static_cast(ratio.width) * + static_cast(height); + + if (ratio1 > ratio2) + return { static_cast(ratio2 / ratio.height), height }; + else + return { width, static_cast(ratio1 / ratio.width) }; +} + +/** + * \brief Align up to the aspect ratio given by \a ratio + * \param[in] ratio The size whose aspect ratio to align up to + * \return A Size whose width and height are equal to the width and height + * of this Size aligned up to the aspect ratio of \a ratio + */ +Size Size::alignedUpToAspectRatio(const Size &ratio) const +{ + uint64_t ratio1 = static_cast(width) * + static_cast(ratio.height); + uint64_t ratio2 = static_cast(ratio.width) * + static_cast(height); + + if (ratio1 < ratio2) + return { static_cast(ratio2 / ratio.height), height }; + else + return { width, static_cast(ratio1 / ratio.width) }; +} + +/** + * \brief Centre a rectangle of this size within another rectangular region, + * with optional offsets + * \param[in] region The rectangular region relative to which the returned + * rectangle can be position + * \param[in] offsetX The X offset of the mid-point of the returned rectangle + * relative to the mid-point of the region + * \param[in] offsetY The Y offset of the mid-point of the returned rectangle + * relative to the mid-point of the region + * + * A Rectangle of this object's size is positioned within the Rectangle + * given by \a region. It is positioned so that its mid-point coincides + * with the mid-point of \a region, and is then further offset by the + * values \a offsetX and \a offsetY. + * + * \return A Rectangle with the horizontal and vertical sizes of + * this Size instance, centred with offsets within a region + */ +Rectangle Size::centredTo(const Rectangle ®ion, int offsetX, int offsetY) const +{ + int x = (region.width - width) / 2 + region.x + offsetX; + int y = (region.height - height) / 2 + region.y + offsetY; + + return Rectangle(x, y, width, height); +} + +/** + * \brief Scale size up by the given factor + * \return The scaled Size + */ +Size operator*(const Size &size, float f) +{ + return Size(size.width * f, size.height * f); +} + +/** + * \brief Scale size down by the given factor + * \return The scaled Size + */ +Size operator/(const Size &size, float f) +{ + return Size(size.width / f, size.height / f); +} + /** * \brief Compare sizes for equality * \return True if the two sizes are equal, false otherwise @@ -365,6 +447,12 @@ bool operator==(const SizeRange &lhs, const SizeRange &rhs) * \param[in] height The height */ +/** + * \fn Rectangle::Rectangle(const Size &size) + * \brief Construct a Rectangle with zero offsets and the given \a size + * \param[in] size The desired Rectangle size + */ + /** * \var Rectangle::x * \brief The horizontal coordinate of the rectangle's top-left corner @@ -404,6 +492,47 @@ const std::string Rectangle::toString() const return ss.str(); } +/** + * \brief Retrieve the size of this rectangle + * \return A Size reporting the Rectangle horizontal and vertical sizes + */ +Size Rectangle::size() const +{ + return Size(width, height); +} + +/** + * \brief Bound a Rectangle so as not to exceeed another Rectangle + * \param[in] boundary The limit that the returned Rectangle will not exceed + * + * The Rectangle is bounded so that it does not exceeed the given \a boundary. + * This process involves translating the Rectangle if any of its edges + * lie beyond \a boundary, so that those edges then lie along the boundary + * instead. + * + * If either width or height are larger than \a bounary, then the returned + * Rectangle is clipped to be no larger. But other than this, the + * Rectangle is not clipped or reduced in size, merely translated. + * + * We note that this is not a conventional Rectangle intersection function. + * + * \return A Rectangle that does not extend beyond a boundary Rectangle + */ +Rectangle Rectangle::boundedTo(const Rectangle &boundary) const +{ + Rectangle result(*this); + + result.width = std::min(result.width, boundary.width); + result.x = std::clamp(result.x, boundary.x, + boundary.x + boundary.width - result.width); + + result.height = std::min(result.height, boundary.height); + result.y = std::clamp(result.y, boundary.y, + boundary.y + boundary.height - result.height); + + return result; +} + /** * \brief Compare rectangles for equality * \return True if the two rectangles are equal, false otherwise