@@ -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;
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(-)