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)
 |