From patchwork Thu Oct 19 14:01:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 19156 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 8CB9BC3272 for ; Thu, 19 Oct 2023 14:02:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0788C62985; Thu, 19 Oct 2023 16:02:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1697724120; bh=MDEdF8Zm/uyI+9cj5qgwNyaQdBJJAz/15IywI44RK50=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=Fguc0KaaHlpQUVGIOBOYEDnUppKjP8nCQdmDUiS4crP8JVzHot4Zn5U9btxgHbXw4 EK/mN0LH1oiig0uZ6/WDkVQepG2dgmRPiGnDYXd519RRaL3Cn3XK6g4tBpuB5iCYSC yxvU1jX0SR/77CzQJKWBfLP9kvQXTB8J1Z1WFs/drCpCoWemXf8YgdHbXVBK6SHJBO 2qIiEn1PJdhXrhaWUogn24FGWECPfLTKaHQU9y6jhFWuiO7pxuOQunZCrxOa/zGfYp GN7r+U+PtPErXp2Xa9hoSfbZm9YZjY9jbtu2ROGTtj0Q2f8AJPjGLI4jNGUdBl26OA gZVVHFRhv2o1Q== 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 06A066298F for ; Thu, 19 Oct 2023 16:01:53 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="nyMFxhZ8"; dkim-atps=neutral Received: from uno.LocalDomain (93-61-96-190.ip145.fastwebnet.it [93.61.96.190]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DFBA3276; Thu, 19 Oct 2023 16:01:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1697724105; bh=MDEdF8Zm/uyI+9cj5qgwNyaQdBJJAz/15IywI44RK50=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nyMFxhZ8jrR+Q5shqdFvJWsYRuxNFcEuoXOgykxhejfxCGruH+Sby6Rs8jZExDctU 56H5a9in+nnYd0wnnd2HHop70bp1bbyNsKtiONBP8hh9UYW/5mZLBPUPshEROIb8a3 a86k8qQZeL+lozP3lWGAUeLcmCI87ih5meUZ5cns= To: libcamera-devel@lists.libcamera.org Date: Thu, 19 Oct 2023 16:01:29 +0200 Message-ID: <20231019140133.32090-9-jacopo.mondi@ideasonboard.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231019140133.32090-1-jacopo.mondi@ideasonboard.com> References: <20231019140133.32090-1-jacopo.mondi@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v6 08/12] test: Add unit test for Transform and Orientation 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: Jacopo Mondi via libcamera-devel From: Jacopo Mondi Reply-To: Jacopo Mondi Cc: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a unit test for Transform and Orientation to validate the implementation of the operations between the two types. In particular, test that: o1 / o2 = t o2 * t = o1 Signed-off-by: Jacopo Mondi Reviewed-by: David Plowman Reviewed-by: Laurent Pinchart --- test/meson.build | 1 + test/transform.cpp | 329 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 330 insertions(+) create mode 100644 test/transform.cpp diff --git a/test/meson.build b/test/meson.build index b227be818419..189e1428485a 100644 --- a/test/meson.build +++ b/test/meson.build @@ -46,6 +46,7 @@ public_tests = [ {'name': 'public-api', 'sources': ['public-api.cpp']}, {'name': 'signal', 'sources': ['signal.cpp']}, {'name': 'span', 'sources': ['span.cpp']}, + {'name': 'transform', 'sources': ['transform.cpp']}, ] internal_tests = [ diff --git a/test/transform.cpp b/test/transform.cpp new file mode 100644 index 000000000000..fbc0308c5d45 --- /dev/null +++ b/test/transform.cpp @@ -0,0 +1,329 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2023, Ideas On Board Oy + * + * transform.cpp - Transform and Orientation tests + */ + +#include + +#include +#include + +#include "test.h" + +using namespace std; +using namespace libcamera; + +class TransformTest : public Test +{ +protected: + int run(); +}; + +int TransformTest::run() +{ + /* + * RotationTestEntry collects two Orientation and one Transform that + * gets combined to validate that (o1 / o2 = T) and (o1 = o2 * T) + * + * o1 / o2 = t computes the Transform to apply to o2 to obtain o1 + * o2 * t = o1 combines o2 with t by applying o2 first then t + * + * The comments on the (most complex) transform show how applying to + * an image with orientation o2 the Transform t allows to obtain o1. + * + * The image with basic rotation0 is assumed to be: + * + * AB + * CD + * + * And the Transform operators are: + * + * V = vertical flip + * H = horizontal flip + * T = transpose + * + * the operator '* (T|V)' applies V first then T. + */ + static const struct RotationTestEntry { + Orientation o1; + Orientation o2; + Transform t; + } testEntries[] = { + /* Test identities transforms first. */ + { + Orientation::Rotate0, Orientation::Rotate0, + Transform::Identity, + }, + { + Orientation::Rotate0Mirror, Orientation::Rotate0Mirror, + Transform::Identity, + }, + { + Orientation::Rotate180, Orientation::Rotate180, + Transform::Identity, + }, + { + Orientation::Rotate180Mirror, Orientation::Rotate180Mirror, + Transform::Identity, + }, + { + Orientation::Rotate90, Orientation::Rotate90, + Transform::Identity, + }, + { + Orientation::Rotate90Mirror, Orientation::Rotate90Mirror, + Transform::Identity, + }, + { + Orientation::Rotate270, Orientation::Rotate270, + Transform::Identity, + }, + { + Orientation::Rotate270Mirror, Orientation::Rotate270Mirror, + Transform::Identity, + }, + /* + * Combine 0 and 180 degrees rotation as they're the most common + * ones. + */ + { + /* + * o2 t o1 + * -------------------------- + * CD * (H|V) = BA AB + * BA CD CD + */ + Orientation::Rotate0, Orientation::Rotate180, + Transform::Rot180, + }, + { + /* + * o2 t o1 + * -------------------------- + * AB * (H|V) = CD DC + * CD AB BA + */ + Orientation::Rotate180, Orientation::Rotate0, + Transform::Rot180 + }, + /* Test that transpositions are handled correctly. */ + { + /* + * o2 t o1 + * -------------------------- + * AB * (T|V) = CD CA + * CD AB DB + */ + Orientation::Rotate90, Orientation::Rotate0, + Transform::Rot90, + }, + { + /* + * o2 t o1 + * -------------------------- + * CA * (T|H) = AC AB + * DB BD CD + */ + Orientation::Rotate0, Orientation::Rotate90, + Transform::Rot270, + }, + { + /* + * o2 t o1 + * -------------------------- + * AB * (T|H) = BA BD + * CD DC AC + */ + Orientation::Rotate270, Orientation::Rotate0, + Transform::Rot270, + }, + { + /* + * o2 t o1 + * -------------------------- + * BD * (T|V) = AC AB + * AC BD CD + */ + Orientation::Rotate0, Orientation::Rotate270, + Transform::Rot90, + }, + { + /* + * o2 t o1 + * -------------------------- + * CD * (T|H) = DC DA + * BA AB CB + */ + Orientation::Rotate90, Orientation::Rotate180, + Transform::Rot270, + }, + { + /* + * o2 t o1 + * -------------------------- + * DA * (T|V) = CB CD + * CB DA BA + */ + Orientation::Rotate180, Orientation::Rotate90, + Transform::Rot90, + }, + { + /* + * o2 t o1 + * -------------------------- + * CD * (T|V) = BA BC + * BA CD AD + */ + Orientation::Rotate270, Orientation::Rotate180, + Transform::Rot90, + }, + { + /* + * o2 t o1 + * -------------------------- + * BC * (T|H) = CB CD + * AD DA BA + */ + Orientation::Rotate180, Orientation::Rotate270, + Transform::Rot270, + }, + { + /* + * o2 t o1 + * -------------------------- + * DA * (V|H) = AD BC + * CB BC AD + */ + Orientation::Rotate270, Orientation::Rotate90, + Transform::Rot180, + }, + /* Test that mirroring is handled correctly. */ + { + Orientation::Rotate0, Orientation::Rotate0Mirror, + Transform::HFlip + }, + { + Orientation::Rotate0Mirror, Orientation::Rotate0, + Transform::HFlip + }, + { + Orientation::Rotate180, Orientation::Rotate180Mirror, + Transform::HFlip + }, + { + Orientation::Rotate180Mirror, Orientation::Rotate180, + Transform::HFlip + }, + { + Orientation::Rotate90, Orientation::Rotate90Mirror, + Transform::HFlip + }, + { + Orientation::Rotate90Mirror, Orientation::Rotate90, + Transform::HFlip + }, + { + Orientation::Rotate270, Orientation::Rotate270Mirror, + Transform::HFlip + }, + { + Orientation::Rotate270Mirror, Orientation::Rotate270, + Transform::HFlip + }, + { + Orientation::Rotate0, Orientation::Rotate0Mirror, + Transform::HFlip + }, + /* + * More exotic transforms which include Transpositions and + * mirroring. + */ + { + /* + * o2 t o1 + * ------------------ + * BC * (V) = AD + * AD BC + */ + Orientation::Rotate90Mirror, Orientation::Rotate270, + Transform::VFlip, + }, + { + /* + * o2 t o1 + * ------------------ + * CB * (T) = CD + * DA BA + */ + Orientation::Rotate180, Orientation::Rotate270Mirror, + Transform::Transpose, + }, + { + /* + * o2 t o1 + * ------------------ + * AD * (T) = AB + * BC DC + */ + Orientation::Rotate0, Orientation::Rotate90Mirror, + Transform::Transpose, + }, + { + /* + * o2 t o1 + * ------------------ + * AD * (V) = BC + * BC AD + */ + Orientation::Rotate270, Orientation::Rotate90Mirror, + Transform::VFlip, + }, + { + /* + * o2 t o1 + * ------------------ + * DA * (V) = CB + * CB DA + */ + Orientation::Rotate270Mirror, Orientation::Rotate90, + Transform::VFlip, + }, + { + /* + * o2 t o1 + * -------------------------- + * CB * (V|H) = BC AD + * DA AD BC + */ + Orientation::Rotate90Mirror, Orientation::Rotate270Mirror, + Transform::Rot180, + }, + }; + + for (const auto &entry : testEntries) { + Transform transform = entry.o1 / entry.o2; + if (transform != entry.t) { + cerr << "Failed to validate: " << entry.o1 + << " / " << entry.o2 + << " = " << transformToString(entry.t) << endl; + cerr << "Got back: " + << transformToString(transform) << endl; + return TestFail; + } + + Orientation adjusted = entry.o2 * entry.t; + if (adjusted != entry.o1) { + cerr << "Failed to validate: " << entry.o2 + << " * " << transformToString(entry.t) + << " = " << entry.o1 << endl; + cerr << "Got back: " << adjusted << endl; + return TestFail; + } + } + + return TestPass; +} + +TEST_REGISTER(TransformTest)