[WIP,RFC,26/26] apps: dng_writer: Split cfa pattern handling
diff mbox series

Message ID 20261023-b4-raw-model-v1-26-eadb9948901b@ideasonboard.com
State New
Headers show
Series
  • Support the new common raw sensor model
Related show

Commit Message

Jai Luthra Oct. 23, 2026, 10:58 a.m. UTC
Simplify the formatInfo table by switching to the new generic pixel
formats.

For populating the color filter array pattern fields in the TIFF
metadata, read it from the StreamConfiguration.

Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
---
 src/apps/common/dng_writer.cpp | 189 ++++++++++-------------------------------
 1 file changed, 43 insertions(+), 146 deletions(-)

Patch
diff mbox series

diff --git a/src/apps/common/dng_writer.cpp b/src/apps/common/dng_writer.cpp
index 0d9b725b939f..ab2b244b1cdf 100644
--- a/src/apps/common/dng_writer.cpp
+++ b/src/apps/common/dng_writer.cpp
@@ -8,13 +8,16 @@ 
 #include "dng_writer.h"
 
 #include <algorithm>
+#include <array>
 #include <endian.h>
 #include <iostream>
 #include <map>
+#include <optional>
 #include <vector>
 
 #include <tiffio.h>
 
+#include <libcamera/color_filter_array.h>
 #include <libcamera/control_ids.h>
 #include <libcamera/formats.h>
 #include <libcamera/property_ids.h>
@@ -27,9 +30,10 @@  enum CFAPatternColour : uint8_t {
 	CFAPatternBlue = 2,
 };
 
+typedef std::array<CFAPatternColour, 4> CFAPattern;
+
 struct FormatInfo {
 	uint8_t bitsPerSample;
-	CFAPatternColour pattern[4];
 	void (*packScanline)(void *output, const void *input,
 			     unsigned int width);
 	void (*thumbScanline)(const FormatInfo &info, void *output,
@@ -347,176 +351,63 @@  void thumbScanlineIPU3([[maybe_unused]] const FormatInfo &info, void *output,
 }
 
 const std::map<PixelFormat, FormatInfo> formatInfo = {
-	{ formats::SBGGR8, {
+	{ formats::RAW8, {
 		.bitsPerSample = 8,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw8,
 		.thumbScanline = thumbScanlineRaw_CSI2P,
 	} },
-	{ formats::SGBRG8, {
-		.bitsPerSample = 8,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw8,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SGRBG8, {
-		.bitsPerSample = 8,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw8,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SRGGB8, {
-		.bitsPerSample = 8,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw8,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SBGGR10, {
+	{ formats::RAW10, {
 		.bitsPerSample = 10,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw10,
 		.thumbScanline = thumbScanlineRaw,
 	} },
-	{ formats::SGBRG10, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw10,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SGRBG10, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw10,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SRGGB10, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw10,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SBGGR12, {
+	{ formats::RAW12, {
 		.bitsPerSample = 12,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw12,
 		.thumbScanline = thumbScanlineRaw,
 	} },
-	{ formats::SGBRG12, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw12,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SGRBG12, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw12,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SRGGB12, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw12,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SBGGR16, {
+	{ formats::RAW16, {
 		.bitsPerSample = 16,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw16,
 		.thumbScanline = thumbScanlineRaw,
 	} },
-	{ formats::SGBRG16, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw16,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SGRBG16, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw16,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SRGGB16, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw16,
-		.thumbScanline = thumbScanlineRaw,
-	} },
-	{ formats::SBGGR10_CSI2P, {
+	{ formats::RAW10_CSI2P, {
 		.bitsPerSample = 10,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw10_CSI2P,
 		.thumbScanline = thumbScanlineRaw_CSI2P,
 	} },
-	{ formats::SGBRG10_CSI2P, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw10_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SGRBG10_CSI2P, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw10_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SRGGB10_CSI2P, {
-		.bitsPerSample = 10,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw10_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SBGGR12_CSI2P, {
+	{ formats::RAW12_CSI2P, {
 		.bitsPerSample = 12,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
 		.packScanline = packScanlineRaw12_CSI2P,
 		.thumbScanline = thumbScanlineRaw_CSI2P,
 	} },
-	{ formats::SGBRG12_CSI2P, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineRaw12_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SGRBG12_CSI2P, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineRaw12_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SRGGB12_CSI2P, {
-		.bitsPerSample = 12,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
-		.packScanline = packScanlineRaw12_CSI2P,
-		.thumbScanline = thumbScanlineRaw_CSI2P,
-	} },
-	{ formats::SBGGR10_IPU3, {
+	{ formats::RAW10_IPU3, {
 		.bitsPerSample = 16,
-		.pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed },
-		.packScanline = packScanlineIPU3,
-		.thumbScanline = thumbScanlineIPU3,
-	} },
-	{ formats::SGBRG10_IPU3, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen },
-		.packScanline = packScanlineIPU3,
-		.thumbScanline = thumbScanlineIPU3,
-	} },
-	{ formats::SGRBG10_IPU3, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen },
-		.packScanline = packScanlineIPU3,
-		.thumbScanline = thumbScanlineIPU3,
-	} },
-	{ formats::SRGGB10_IPU3, {
-		.bitsPerSample = 16,
-		.pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue },
 		.packScanline = packScanlineIPU3,
 		.thumbScanline = thumbScanlineIPU3,
 	} },
 };
 
+static constexpr std::pair<ColorFilterArray, CFAPattern> patterns[] = {
+	{ ColorFilterArray::BGGR, { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed } },
+	{ ColorFilterArray::GBRG, { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen } },
+	{ ColorFilterArray::GRBG, { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen } },
+	{ ColorFilterArray::RGGB, { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue } },
+};
+
+static std::optional<CFAPattern> findCfaPattern(const std::optional<ColorFilterArray> cfa)
+{
+	if (!cfa)
+		return std::nullopt;
+
+	for (const auto &[key, pattern] : patterns) {
+		if (key.order == cfa.value().order)
+			return pattern;
+	}
+
+	return std::nullopt;
+}
+
 } /* namespace */
 
 int DNGWriter::write(const char *filename, const Camera *camera,
@@ -534,6 +425,12 @@  int DNGWriter::write(const char *filename, const Camera *camera,
 	}
 	const FormatInfo *info = &it->second;
 
+	const auto pattern = findCfaPattern(config.bayerOrder);
+	if (!pattern) {
+		std::cerr << "Unknown color filter array pattern" << std::endl;
+		return -EINVAL;
+	}
+
 	TIFF *tif = TIFFOpen(filename, "w");
 	if (!tif) {
 		std::cerr << "Failed to open tiff file" << std::endl;
@@ -696,9 +593,9 @@  int DNGWriter::write(const char *filename, const Camera *camera,
 	TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
 	TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, cfaRepeatPatternDim);
 	if (TIFFLIB_VERSION < 20201219)
-		TIFFSetField(tif, TIFFTAG_CFAPATTERN, info->pattern);
+		TIFFSetField(tif, TIFFTAG_CFAPATTERN, pattern.value().data());
 	else
-		TIFFSetField(tif, TIFFTAG_CFAPATTERN, 4, info->pattern);
+		TIFFSetField(tif, TIFFTAG_CFAPATTERN, 4, pattern.value().data());
 	TIFFSetField(tif, TIFFTAG_CFAPLANECOLOR, 3, cfaPlaneColor);
 	TIFFSetField(tif, TIFFTAG_CFALAYOUT, 1);
 
@@ -715,14 +612,14 @@  int DNGWriter::write(const char *filename, const Camera *camera,
 		 * Map it to the TIFF tag that is specified in CFA pattern
 		 * order.
 		 */
-		unsigned int green = (info->pattern[0] == CFAPatternRed ||
-				      info->pattern[1] == CFAPatternRed)
+		unsigned int green = (pattern.value()[0] == CFAPatternRed ||
+				      pattern.value()[1] == CFAPatternRed)
 				   ? 0 : 1;
 
 		for (unsigned int i = 0; i < 4; ++i) {
 			unsigned int level;
 
-			switch (info->pattern[i]) {
+			switch (pattern.value()[i]) {
 			case CFAPatternRed:
 				level = levels[0];
 				break;