summaryrefslogtreecommitdiff
path: root/src/ipa/raspberrypi/controller/rpi/ccm.hpp
blob: 330ed51fe398911c9fa49644a3ed99432f902125 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (C) 2019, Raspberry Pi (Trading) Limited
 *
 * ccm.hpp - CCM (colour correction matrix) control algorithm
 */
#pragma once

#include <vector>

#include "../ccm_algorithm.hpp"
#include "../pwl.hpp"

namespace RPiController {

// Algorithm to calculate colour matrix. Should be placed after AWB.

struct Matrix {
	Matrix(double m0, double m1, double m2, double m3, double m4, double m5,
	       double m6, double m7, double m8);
	Matrix();
	double m[3][3];
	void Read(boost::property_tree::ptree const &params);
};
static inline Matrix operator*(double d, Matrix const &m)
{
	return Matrix(m.m[0][0] * d, m.m[0][1] * d, m.m[0][2] * d,
		      m.m[1][0] * d, m.m[1][1] * d, m.m[1][2] * d,
		      m.m[2][0] * d, m.m[2][1] * d, m.m[2][2] * d);
}
static inline Matrix operator*(Matrix const &m1, Matrix const &m2)
{
	Matrix m;
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			m.m[i][j] = m1.m[i][0] * m2.m[0][j] +
				    m1.m[i][1] * m2.m[1][j] +
				    m1.m[i][2] * m2.m[2][j];
	return m;
}
static inline Matrix operator+(Matrix const &m1, Matrix const &m2)
{
	Matrix m;
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			m.m[i][j] = m1.m[i][j] + m2.m[i][j];
	return m;
}

struct CtCcm {
	double ct;
	Matrix ccm;
};

struct CcmConfig {
	std::vector<CtCcm> ccms;
	Pwl saturation;
};

class Ccm : public CcmAlgorithm
{
public:
	Ccm(Controller *controller = NULL);
	char const *Name() const override;
	void Read(boost::property_tree::ptree const &params) override;
	void SetSaturation(double saturation) override;
	void Initialise() override;
	void Prepare(Metadata *image_metadata) override;

private:
	CcmConfig config_;
	double saturation_;
};

} // namespace RPiController
"hl com">/* 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)