From patchwork Mon Jul 24 07:10:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 18870 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 CF12BC32AA for ; Mon, 24 Jul 2023 07:11:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 59C9E628C8; Mon, 24 Jul 2023 09:11:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1690182692; bh=qTPUrJtjfBz/W3EoRsvo4YPyZE3kCvlmGeoor6hJi9I=; 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=2/07GHztv0fG1jwFchL3Zhu75/tdXgEi+CJHNha/OCdeqHZREgVA3NUI718a8US7T p3lpJmPihpJvdw2oclhccHunlZ3sXG8NZCx8qofAc4lLbSA08kEKNDhKr1vFGHXAYn rcdHVxYa/YOLhfHAx98yQGcMM4Lys+SD9Uh9RGpkJAOI0+IKT6J+zZKCFcSx5uppNc Ryge6ewIyeZADL2O3aIS2AUaHwE9Q1E7/uQD6a0W+hQPV0WDrNGWj4o+prF2K07aqq JQ0aRNUJ9td0xnKlY2In66EVZN7BarmJ02qHKJk8NsGnTEzAcX1gNDAL8PAHTxruw/ oeh6+n11+WfSw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4A37D628D6 for ; Mon, 24 Jul 2023 09:11:27 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ZJUEFetb"; dkim-atps=neutral Received: from uno.localdomain (mob-5-91-20-233.net.vodafone.it [5.91.20.233]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 496E92C6; Mon, 24 Jul 2023 09:10:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1690182630; bh=qTPUrJtjfBz/W3EoRsvo4YPyZE3kCvlmGeoor6hJi9I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZJUEFetbOD6R+ISNUb9tbyQ3/ti9C030za68DK1IYDNcW6o5rZ45ulSXkG2vSB+JR mOW6hEqWDBpv409j6icgZVoIHjVeO/QXw1zfe5kLAK4DHqA1Lv0fb6hgLWTpo8QJ3W wg2nuejwULtDQzBifYSDWU61RxMyWSyzDnxZyzSI= To: libcamera-devel@lists.libcamera.org Date: Mon, 24 Jul 2023 09:10:59 +0200 Message-Id: <20230724071101.5256-9-jacopo.mondi@ideasonboard.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230724071101.5256-1-jacopo.mondi@ideasonboard.com> References: <20230724071101.5256-1-jacopo.mondi@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 08/10] 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 --- test/meson.build | 1 + test/transform.cpp | 331 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 332 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..4a6cf7387f02 --- /dev/null +++ b/test/transform.cpp @@ -0,0 +1,331 @@ +/* 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. + */ + struct RotationTestEntry { + Orientation o1; + Orientation o2; + Transform t; + } testEntries[] = { + /* Test identities transforms first. */ + { + Orientation::rotate0, Orientation::rotate0, + Transform::Identity, + }, + { + Orientation::rotate0Flip, Orientation::rotate0Flip, + Transform::Identity, + }, + { + Orientation::rotate180, Orientation::rotate180, + Transform::Identity, + }, + { + Orientation::rotate180Flip, Orientation::rotate180Flip, + Transform::Identity, + }, + { + Orientation::rotate90, Orientation::rotate90, + Transform::Identity, + }, + { + Orientation::rotate90Flip, Orientation::rotate90Flip, + Transform::Identity, + }, + { + Orientation::rotate270, Orientation::rotate270, + Transform::Identity, + }, + { + Orientation::rotate270Flip, Orientation::rotate270Flip, + 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::rotate0Flip, + Transform::HFlip + }, + { + Orientation::rotate0Flip, Orientation::rotate0, + Transform::HFlip + }, + { + Orientation::rotate180, Orientation::rotate180Flip, + Transform::HFlip + }, + { + Orientation::rotate180Flip, Orientation::rotate180, + Transform::HFlip + }, + { + Orientation::rotate90, Orientation::rotate90Flip, + Transform::HFlip + }, + { + Orientation::rotate90Flip, Orientation::rotate90, + Transform::HFlip + }, + { + Orientation::rotate270, Orientation::rotate270Flip, + Transform::HFlip + }, + { + Orientation::rotate270Flip, Orientation::rotate270, + Transform::HFlip + }, + { + Orientation::rotate0, Orientation::rotate0Flip, + Transform::HFlip + }, + /* + * More exotic transforms which include Transpositions and + * mirroring. + */ + { + /* + * o2 t o1 + * ------------------ + * BC * (V) = AD + * AD BC + */ + Orientation::rotate90Flip, Orientation::rotate270, + Transform::VFlip, + }, + { + /* + * o2 t o1 + * ------------------ + * CB * (T) = CD + * DA BA + */ + Orientation::rotate180, Orientation::rotate270Flip, + Transform::Transpose, + }, + { + /* + * o2 t o1 + * ------------------ + * AD * (T) = AB + * BC DC + */ + Orientation::rotate0, Orientation::rotate90Flip, + Transform::Transpose, + }, + { + /* + * o2 t o1 + * ------------------ + * AD * (V) = BC + * BC AD + */ + Orientation::rotate270, Orientation::rotate90Flip, + Transform::VFlip, + }, + { + /* + * o2 t o1 + * ------------------ + * DA * (V) = CB + * CB DA + */ + Orientation::rotate270Flip, Orientation::rotate90, + Transform::VFlip, + }, + { + /* + * o2 t o1 + * -------------------------- + * CB * (V|H) = BC AD + * DA AD BC + */ + Orientation::rotate90Flip, Orientation::rotate270Flip, + Transform::Rot180, + }, + }; + + for (const auto &entry : testEntries) { + Transform transform = entry.o1 / entry.o2; + cout << "Testing: " << entry.o1 << " / " << entry.o2 + << " = " << transformToString(transform) << endl; + 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)