mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-12 23:09:45 +03:00
Source files in libcamera start by a comment block header, which includes the file name and a one-line description of the file contents. While the latter is useful to get a quick overview of the file contents at a glance, the former is mostly a source of inconvenience. The name in the comments can easily get out of sync with the file name when files are renamed, and copy & paste during development have often lead to incorrect names being used to start with. Readers of the source code are expected to know which file they're looking it. Drop the file name from the header comment block. The change was generated with the following script: ---------------------------------------- dirs="include/libcamera src test utils" declare -rA patterns=( ['c']=' \* ' ['cpp']=' \* ' ['h']=' \* ' ['py']='# ' ['sh']='# ' ) for ext in ${!patterns[@]} ; do files=$(for dir in $dirs ; do find $dir -name "*.${ext}" ; done) pattern=${patterns[${ext}]} for file in $files ; do name=$(basename ${file}) sed -i "s/^\(${pattern}\)${name} - /\1/" "$file" done done ---------------------------------------- This misses several files that are out of sync with the comment block header. Those will be addressed separately and manually. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
329 lines
7 KiB
C++
329 lines
7 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)
|