[v3,1/1] apps: cam: Support PPM output for other RGB formats
diff mbox series

Message ID 20250901162606.44139-2-mzamazal@redhat.com
State New
Headers show
Series
  • PPM output for RGB formats
Related show

Commit Message

Milan Zamazal Sept. 1, 2025, 4:25 p.m. UTC
GPU ISP can produce only 32-bit output.  Let's add support to the PPM
writer for all the common RGB image formats so that we can store GPU ISP
output as PPM files.  Contingent alpha values are ignored as there is no
support for the alpha channel in PPM.

There is no obvious performance penalty in my environment compared to
output in the raw format.

Signed-off-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
---
 src/apps/common/ppm_writer.cpp | 48 +++++++++++++++++++++++++++++++---
 1 file changed, 44 insertions(+), 4 deletions(-)

Comments

Pavel Machek Sept. 1, 2025, 4:59 p.m. UTC | #1
On Mon 2025-09-01 18:25:15, Milan Zamazal wrote:
> GPU ISP can produce only 32-bit output.  Let's add support to the PPM
> writer for all the common RGB image formats so that we can store GPU ISP
> output as PPM files.  Contingent alpha values are ignored as there is no
> support for the alpha channel in PPM.
> 
> There is no obvious performance penalty in my environment compared to
> output in the raw format.
> 

Reviewed-by: Pavel Machek <pavel@ucw.cz>

Thank you,
								Pavel

Patch
diff mbox series

diff --git a/src/apps/common/ppm_writer.cpp b/src/apps/common/ppm_writer.cpp
index 368de8bf6..6f0bbbe9e 100644
--- a/src/apps/common/ppm_writer.cpp
+++ b/src/apps/common/ppm_writer.cpp
@@ -10,6 +10,7 @@ 
 #include <errno.h>
 #include <fstream>
 #include <iostream>
+#include <vector>
 
 #include <libcamera/formats.h>
 #include <libcamera/pixel_format.h>
@@ -20,9 +21,34 @@  int PPMWriter::write(const char *filename,
 		     const StreamConfiguration &config,
 		     const Span<uint8_t> &data)
 {
-	if (config.pixelFormat != formats::BGR888) {
-		std::cerr << "Only BGR888 output pixel format is supported ("
-			  << config.pixelFormat << " requested)" << std::endl;
+	struct FormatTransformation {
+		unsigned int rPos;
+		unsigned int gPos;
+		unsigned int bPos;
+		unsigned int bytesPerPixel;
+	};
+
+	static const std::map<libcamera::PixelFormat, FormatTransformation> transforms = {
+		{ libcamera::formats::R8, { 0, 0, 0, 1 } },
+		{ libcamera::formats::RGB888, { 2, 1, 0, 3 } },
+		{ libcamera::formats::BGR888, { 0, 1, 2, 3 } },
+		{ libcamera::formats::ARGB8888, { 2, 1, 0, 4 } },
+		{ libcamera::formats::XRGB8888, { 2, 1, 0, 4 } },
+		{ libcamera::formats::ABGR8888, { 0, 1, 2, 4 } },
+		{ libcamera::formats::XBGR8888, { 0, 1, 2, 4 } },
+		{ libcamera::formats::RGBA8888, { 3, 2, 1, 4 } },
+		{ libcamera::formats::RGBX8888, { 3, 2, 1, 4 } },
+		{ libcamera::formats::BGRA8888, { 1, 2, 3, 4 } },
+		{ libcamera::formats::BGRX8888, { 1, 2, 3, 4 } },
+	};
+
+	FormatTransformation transformation;
+	if (auto search = transforms.find(config.pixelFormat); search != transforms.end()) {
+		transformation = search->second;
+	} else {
+		std::cerr
+			<< "Only RGB output pixel formats are supported ("
+			<< config.pixelFormat << " requested)" << std::endl;
 		return -EINVAL;
 	}
 
@@ -42,8 +68,22 @@  int PPMWriter::write(const char *filename,
 
 	const unsigned int rowLength = config.size.width * 3;
 	const char *row = reinterpret_cast<const char *>(data.data());
+	const bool transform = config.pixelFormat != formats::BGR888;
+	std::vector<char> transformedRow(transform ? rowLength : 0);
+
 	for (unsigned int y = 0; y < config.size.height; y++, row += config.stride) {
-		output.write(row, rowLength);
+		if (transform) {
+			for (unsigned int x = 0; x < config.size.width; x++) {
+				transformedRow[x * 3] =
+					row[x * transformation.bytesPerPixel + transformation.rPos];
+				transformedRow[x * 3 + 1] =
+					row[x * transformation.bytesPerPixel + transformation.gPos];
+				transformedRow[x * 3 + 2] =
+					row[x * transformation.bytesPerPixel + transformation.bPos];
+			}
+		}
+
+		output.write(transform ? transformedRow.data() : row, rowLength);
 		if (!output) {
 			std::cerr << "Failed to write image data at row " << y << std::endl;
 			return -EIO;