From baea40a8a5dddbad3cf6398aa8ce248e4547c955 Mon Sep 17 00:00:00 2001 From: Milan Zamazal Date: Mon, 1 Sep 2025 18:25:15 +0200 Subject: [PATCH] apps: cam: Support PPM output for other RGB formats 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 Signed-off-by: Milan Zamazal Reviewed-by: Pavel Machek Reviewed-by: Paul Elder Signed-off-by: Kieran Bingham --- src/apps/common/ppm_writer.cpp | 48 +++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/apps/common/ppm_writer.cpp b/src/apps/common/ppm_writer.cpp index 368de8bf..6f0bbbe9 100644 --- a/src/apps/common/ppm_writer.cpp +++ b/src/apps/common/ppm_writer.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -20,9 +21,34 @@ int PPMWriter::write(const char *filename, const StreamConfiguration &config, const Span &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 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(data.data()); + const bool transform = config.pixelFormat != formats::BGR888; + std::vector 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;