[PATCH 2/4] libcamera: Enable and use matrix implementation from libcamera/internal
Stefan Klug
stefan.klug at ideasonboard.com
Mon Nov 18 16:05:05 CET 2024
The matrix code copied from libipa needs to be adapted to compile and
work from the new location. To keep the project buildable at all times,
these changes are not split into multiple commits but kept as a single
one.
The changes are:
- Add matrix class to meson.build
- Move matrix class from libipa namespace into libcamera
- Add std::initializer_list based constructor to be able to replace the
Matrix implementation contained in the rpi pipeline
- Replace Matrix class in rpi pipeline with the new one to prevent name
clashes
Signed-off-by: Stefan Klug <stefan.klug at ideasonboard.com>
---
include/libcamera/internal/matrix.h | 20 ++++-----
include/libcamera/internal/meson.build | 1 +
src/ipa/rpi/controller/rpi/ccm.cpp | 56 +++++++-------------------
src/ipa/rpi/controller/rpi/ccm.h | 35 +---------------
src/libcamera/matrix.cpp | 8 +---
src/libcamera/meson.build | 1 +
6 files changed, 32 insertions(+), 89 deletions(-)
diff --git a/include/libcamera/internal/matrix.h b/include/libcamera/internal/matrix.h
index 5471e6975b74..b82d33f98658 100644
--- a/include/libcamera/internal/matrix.h
+++ b/include/libcamera/internal/matrix.h
@@ -19,8 +19,6 @@ namespace libcamera {
LOG_DECLARE_CATEGORY(Matrix)
-namespace ipa {
-
#ifndef __DOXYGEN__
template<typename T, unsigned int Rows, unsigned int Cols,
std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
@@ -35,6 +33,12 @@ public:
data_.fill(static_cast<T>(0));
}
+ Matrix(std::initializer_list<T> data)
+ {
+ ASSERT(data.size() == Rows * Cols);
+ std::copy(data.begin(), data.end(), data_.begin());
+ }
+
Matrix(const std::vector<T> &data)
{
std::copy(data.begin(), data.end(), data_.begin());
@@ -166,24 +170,22 @@ Matrix<T, Rows, Cols> operator+(const Matrix<T, Rows, Cols> &m1, const Matrix<T,
bool matrixValidateYaml(const YamlObject &obj, unsigned int size);
#endif /* __DOXYGEN__ */
-} /* namespace ipa */
-
#ifndef __DOXYGEN__
template<typename T, unsigned int Rows, unsigned int Cols>
-std::ostream &operator<<(std::ostream &out, const ipa::Matrix<T, Rows, Cols> &m)
+std::ostream &operator<<(std::ostream &out, const Matrix<T, Rows, Cols> &m)
{
out << m.toString();
return out;
}
template<typename T, unsigned int Rows, unsigned int Cols>
-struct YamlObject::Getter<ipa::Matrix<T, Rows, Cols>> {
- std::optional<ipa::Matrix<T, Rows, Cols>> get(const YamlObject &obj) const
+struct YamlObject::Getter<Matrix<T, Rows, Cols>> {
+ std::optional<Matrix<T, Rows, Cols>> get(const YamlObject &obj) const
{
- if (!ipa::matrixValidateYaml(obj, Rows * Cols))
+ if (!matrixValidateYaml(obj, Rows * Cols))
return std::nullopt;
- ipa::Matrix<T, Rows, Cols> matrix;
+ Matrix<T, Rows, Cols> matrix;
T *data = &matrix[0][0];
unsigned int i = 0;
diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
index 1dddcd50c90b..7d6aa8b72bd7 100644
--- a/include/libcamera/internal/meson.build
+++ b/include/libcamera/internal/meson.build
@@ -29,6 +29,7 @@ libcamera_internal_headers = files([
'ipc_pipe.h',
'ipc_unixsocket.h',
'mapped_framebuffer.h',
+ 'matrix.h',
'media_device.h',
'media_object.h',
'pipeline_handler.h',
diff --git a/src/ipa/rpi/controller/rpi/ccm.cpp b/src/ipa/rpi/controller/rpi/ccm.cpp
index aefa580c9a4b..418bead56ecd 100644
--- a/src/ipa/rpi/controller/rpi/ccm.cpp
+++ b/src/ipa/rpi/controller/rpi/ccm.cpp
@@ -29,34 +29,7 @@ LOG_DEFINE_CATEGORY(RPiCcm)
#define NAME "rpi.ccm"
-Matrix::Matrix()
-{
- memset(m, 0, sizeof(m));
-}
-Matrix::Matrix(double m0, double m1, double m2, double m3, double m4, double m5,
- double m6, double m7, double m8)
-{
- m[0][0] = m0, m[0][1] = m1, m[0][2] = m2, m[1][0] = m3, m[1][1] = m4,
- m[1][2] = m5, m[2][0] = m6, m[2][1] = m7, m[2][2] = m8;
-}
-int Matrix::read(const libcamera::YamlObject ¶ms)
-{
- double *ptr = (double *)m;
-
- if (params.size() != 9) {
- LOG(RPiCcm, Error) << "Wrong number of values in CCM";
- return -EINVAL;
- }
-
- for (const auto ¶m : params.asList()) {
- auto value = param.get<double>();
- if (!value)
- return -EINVAL;
- *ptr++ = *value;
- }
-
- return 0;
-}
+using Matrix3x3 = Matrix<double, 3, 3>;
Ccm::Ccm(Controller *controller)
: CcmAlgorithm(controller), saturation_(1.0) {}
@@ -68,8 +41,6 @@ char const *Ccm::name() const
int Ccm::read(const libcamera::YamlObject ¶ms)
{
- int ret;
-
if (params.contains("saturation")) {
config_.saturation = params["saturation"].get<ipa::Pwl>(ipa::Pwl{});
if (config_.saturation.empty())
@@ -83,9 +54,12 @@ int Ccm::read(const libcamera::YamlObject ¶ms)
CtCcm ctCcm;
ctCcm.ct = *value;
- ret = ctCcm.ccm.read(p["ccm"]);
- if (ret)
- return ret;
+
+ auto ccm = p["ccm"].get<Matrix3x3>();
+ if (!ccm)
+ return -EINVAL;
+
+ ctCcm.ccm = *ccm;
if (!config_.ccms.empty() && ctCcm.ct <= config_.ccms.back().ct) {
LOG(RPiCcm, Error)
@@ -125,7 +99,7 @@ bool getLocked(Metadata *metadata, std::string const &tag, T &value)
return true;
}
-Matrix calculateCcm(std::vector<CtCcm> const &ccms, double ct)
+Matrix3x3 calculateCcm(std::vector<CtCcm> const &ccms, double ct)
{
if (ct <= ccms.front().ct)
return ccms.front().ccm;
@@ -141,13 +115,13 @@ Matrix calculateCcm(std::vector<CtCcm> const &ccms, double ct)
}
}
-Matrix applySaturation(Matrix const &ccm, double saturation)
+Matrix3x3 applySaturation(Matrix3x3 const &ccm, double saturation)
{
- Matrix RGB2Y(0.299, 0.587, 0.114, -0.169, -0.331, 0.500, 0.500, -0.419,
- -0.081);
- Matrix Y2RGB(1.000, 0.000, 1.402, 1.000, -0.345, -0.714, 1.000, 1.771,
- 0.000);
- Matrix S(1, 0, 0, 0, saturation, 0, 0, 0, saturation);
+ Matrix3x3 RGB2Y({ 0.299, 0.587, 0.114, -0.169, -0.331, 0.500, 0.500,
+ -0.419, -0.081 });
+ Matrix3x3 Y2RGB({ 1.000, 0.000, 1.402, 1.000, -0.345, -0.714, 1.000,
+ 1.771, 0.000 });
+ Matrix3x3 S({ 1, 0, 0, 0, saturation, 0, 0, 0, saturation });
return Y2RGB * S * RGB2Y * ccm;
}
@@ -181,7 +155,7 @@ void Ccm::prepare(Metadata *imageMetadata)
for (int j = 0; j < 3; j++)
for (int i = 0; i < 3; i++)
ccmStatus.matrix[j * 3 + i] =
- std::max(-8.0, std::min(7.9999, ccm.m[j][i]));
+ std::max(-8.0, std::min(7.9999, ccm[j][i]));
LOG(RPiCcm, Debug)
<< "colour temperature " << awb.temperatureK << "K";
LOG(RPiCcm, Debug)
diff --git a/src/ipa/rpi/controller/rpi/ccm.h b/src/ipa/rpi/controller/rpi/ccm.h
index 4e5b33fefa4e..c05dbb17a264 100644
--- a/src/ipa/rpi/controller/rpi/ccm.h
+++ b/src/ipa/rpi/controller/rpi/ccm.h
@@ -8,6 +8,7 @@
#include <vector>
+#include "libcamera/internal/matrix.h"
#include <libipa/pwl.h>
#include "../ccm_algorithm.h"
@@ -16,41 +17,9 @@ 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];
- int read(const libcamera::YamlObject ¶ms);
-};
-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;
+ libcamera::Matrix<double, 3, 3> ccm;
};
struct CcmConfig {
diff --git a/src/libcamera/matrix.cpp b/src/libcamera/matrix.cpp
index 8346f0d34160..c3ed54895b22 100644
--- a/src/libcamera/matrix.cpp
+++ b/src/libcamera/matrix.cpp
@@ -5,7 +5,7 @@
* Matrix and related operations
*/
-#include "matrix.h"
+#include "libcamera/internal/matrix.h"
#include <libcamera/base/log.h>
@@ -18,8 +18,6 @@ namespace libcamera {
LOG_DEFINE_CATEGORY(Matrix)
-namespace ipa {
-
/**
* \class Matrix
* \brief Matrix class
@@ -34,7 +32,7 @@ namespace ipa {
*/
/**
- * \fn Matrix::Matrix(const std::vector<T> &data)
+ * \fn Matrix::Matrix(const Span<T> &data)
* \brief Construct a matrix from supplied data
* \param[in] data Data from which to construct a matrix
*
@@ -144,6 +142,4 @@ bool matrixValidateYaml(const YamlObject &obj, unsigned int size)
}
#endif /* __DOXYGEN__ */
-} /* namespace ipa */
-
} /* namespace libcamera */
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 21cae11756d6..57fde8a8fab0 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -40,6 +40,7 @@ libcamera_internal_sources = files([
'ipc_pipe_unixsocket.cpp',
'ipc_unixsocket.cpp',
'mapped_framebuffer.cpp',
+ 'matrix.cpp',
'media_device.cpp',
'media_object.cpp',
'pipeline_handler.cpp',
--
2.43.0
More information about the libcamera-devel
mailing list