[libcamera-devel] [PATCH 1/5] libcamera: Add Transform class

David Plowman david.plowman at raspberrypi.com
Wed Jul 29 11:31:50 CEST 2020


Add implementation of 2d plane transforms, and include a Transform
field in the CameraConfiguration to record the application's choice of
image transform for this session.
---
 include/libcamera/camera.h    |   3 +
 include/libcamera/meson.build |   1 +
 include/libcamera/transform.h | 193 ++++++++++++++++++++++++++++++++++
 3 files changed, 197 insertions(+)
 create mode 100644 include/libcamera/transform.h

diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h
index 4d1a4a9..fd9355e 100644
--- a/include/libcamera/camera.h
+++ b/include/libcamera/camera.h
@@ -16,6 +16,7 @@
 #include <libcamera/request.h>
 #include <libcamera/signal.h>
 #include <libcamera/stream.h>
+#include <libcamera/transform.h>
 
 namespace libcamera {
 
@@ -60,6 +61,8 @@ public:
 	bool empty() const;
 	std::size_t size() const;
 
+	Transform userTransform;
+
 protected:
 	CameraConfiguration();
 
diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
index cdb8e03..7fae5e5 100644
--- a/include/libcamera/meson.build
+++ b/include/libcamera/meson.build
@@ -19,6 +19,7 @@ libcamera_public_headers = files([
     'span.h',
     'stream.h',
     'timer.h',
+    'transform.h',
 ])
 
 include_dir = join_paths(libcamera_include_dir, 'libcamera')
diff --git a/include/libcamera/transform.h b/include/libcamera/transform.h
new file mode 100644
index 0000000..cfd5026
--- /dev/null
+++ b/include/libcamera/transform.h
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2020, Google Inc.
+ *
+ * transform.h - Implementation of 2d plane transforms
+ */
+
+#ifndef __LIBCAMERA_TRANSFORM_H__
+#define __LIBCAMERA_TRANSFORM_H__
+
+#include <string>
+
+namespace libcamera {
+
+class Transform
+{
+public:
+	constexpr Transform()
+		: Transform(Identity)
+	{
+	}
+
+	constexpr static Transform identity()
+	{
+		return Transform(Identity);
+	}
+
+	constexpr static Transform rot0()
+	{
+		return identity();
+	}
+
+	constexpr static Transform hflip()
+	{
+		return Transform(HFlip);
+	}
+
+	constexpr static Transform vflip()
+	{
+		return Transform(VFlip);
+	}
+
+	constexpr static Transform hvflip()
+	{
+		return Transform(HVFlip);
+	}
+
+	constexpr static Transform rot180()
+	{
+		return hvflip();
+	}
+
+	constexpr static Transform transpose()
+	{
+		return Transform(Transpose);
+	}
+
+	constexpr static Transform rot270()
+	{
+		return Transform(Rot270);
+	}
+
+	constexpr static Transform rot90()
+	{
+		return Transform(Rot90);
+	}
+
+	constexpr static Transform rot180Transpose()
+	{
+		return Transform(Rot180Transpose);
+	}
+
+	constexpr static Transform hvflipTranspose()
+	{
+		return rot180Transpose();
+	}
+
+	constexpr static bool rotation(int32_t angle, Transform &xfm)
+	{
+		bool success = true;
+		angle = angle % 360;
+		if (angle < 0)
+			angle += 360;
+
+		if (angle == 0)
+			xfm = identity();
+		else if (angle == 90)
+			xfm = rot90();
+		else if (angle == 180)
+			xfm = rot180();
+		else if (angle == 270)
+			xfm = rot270();
+		else
+			success = false;
+
+		return success;
+	}
+
+	constexpr bool rotation(int32_t &angle) const
+	{
+		bool success = true;
+
+		if (type_ == Identity)
+			angle = 0;
+		else if (type_ == Rot90)
+			angle = 90;
+		else if (type_ == HVFlip)
+			angle = 180;
+		else if (type_ == Rot270)
+			angle = 270;
+		else
+			success = false;
+
+		return success;
+	}
+
+	constexpr bool contains(Transform xfm) const
+	{
+		return (type_ & xfm.type_) == xfm.type_;
+	}
+
+	constexpr Transform inverse() const
+	{
+		/* They're all self-inverses, except for Rot90 and Rot270. */
+		const Type inverses[] = { Identity, HFlip, VFlip, HVFlip,
+					  Transpose, Rot90, Rot270, Rot180Transpose };
+
+		return Transform(inverses[type_]);
+	}
+
+	constexpr Transform operator*(Transform xfm) const
+	{
+		/*
+		 * Reorder the operations so that we imagine doing xfm's transpose
+		 * (if any) after our flips. The effect is to swap our hflips for
+		 * vflips and vice versa, after which we can just xor all the bits.
+		 */
+		int reorderedType = type_;
+		if (xfm.type_ & Transpose)
+			reorderedType = (type_ & 4) | ((type_ & 1) << 1) | ((type_ & 2) >> 1);
+
+		return Transform((Type)(reorderedType ^ xfm.type_));
+	}
+
+	bool operator==(Transform xfm) const
+	{
+		return type_ == xfm.type_;
+	}
+
+	bool operator!=(Transform xfm) const
+	{
+		return !(*this == xfm);
+	}
+
+	std::string toString() const
+	{
+		char const *strings[] = {
+			"identity",
+			"hflip",
+			"vflip",
+			"hvflip",
+			"transpose",
+			"rot270",
+			"rot90",
+			"rot180transpose"
+		};
+		return strings[type_];
+	}
+
+private:
+	enum Type : int {
+		Identity = 0,
+		HFlip = 1,
+		VFlip = 2,
+		HVFlip = HFlip | VFlip,
+		Transpose = 4,
+		Rot270 = HFlip | Transpose,
+		Rot90 = VFlip | Transpose,
+		Rot180Transpose = HFlip | VFlip | Transpose
+	};
+
+	constexpr Transform(Type type)
+		: type_(type)
+	{
+	}
+
+	Type type_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_TRANSFORM_H__ */
+
-- 
2.20.1



More information about the libcamera-devel mailing list