Message ID | 20250901162606.44139-2-mzamazal@redhat.com |
---|---|
State | Accepted |
Commit | baea40a8a5dddbad3cf6398aa8ce248e4547c955 |
Headers | show |
Series |
|
Related | show |
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
Quoting Milan Zamazal (2025-09-02 01:25:15) > 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> Looks good to me. Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > --- > 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 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; > -- > 2.51.0 >
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;