330 lines
7.0 KiB
C++
330 lines
7.0 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2023, Ideas On Board Oy
|
|
*
|
|
* Transform and Orientation tests
|
|
*/
|
|
|
|
#include <iostream>
|
|
|
|
#include <libcamera/orientation.h>
|
|
#include <libcamera/transform.h>
|
|
|
|
#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)
|