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;