diff options
Diffstat (limited to 'src/apps/common')
-rw-r--r-- | src/apps/common/dng_writer.cpp | 212 | ||||
-rw-r--r-- | src/apps/common/dng_writer.h | 2 | ||||
-rw-r--r-- | src/apps/common/event_loop.cpp | 2 | ||||
-rw-r--r-- | src/apps/common/event_loop.h | 2 | ||||
-rw-r--r-- | src/apps/common/image.cpp | 2 | ||||
-rw-r--r-- | src/apps/common/image.h | 2 | ||||
-rw-r--r-- | src/apps/common/options.cpp | 2 | ||||
-rw-r--r-- | src/apps/common/options.h | 2 | ||||
-rw-r--r-- | src/apps/common/ppm_writer.cpp | 2 | ||||
-rw-r--r-- | src/apps/common/ppm_writer.h | 2 | ||||
-rw-r--r-- | src/apps/common/stream_options.cpp | 2 | ||||
-rw-r--r-- | src/apps/common/stream_options.h | 2 |
12 files changed, 193 insertions, 41 deletions
diff --git a/src/apps/common/dng_writer.cpp b/src/apps/common/dng_writer.cpp index 82bc065a..9241f23f 100644 --- a/src/apps/common/dng_writer.cpp +++ b/src/apps/common/dng_writer.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Raspberry Pi Ltd * - * dng_writer.cpp - DNG writer + * DNG writer */ #include "dng_writer.h" @@ -126,7 +126,9 @@ struct Matrix3d { float m[9]; }; -void packScanlineSBGGR8(void *output, const void *input, unsigned int width) +namespace { + +void packScanlineRaw8(void *output, const void *input, unsigned int width) { const uint8_t *in = static_cast<const uint8_t *>(input); uint8_t *out = static_cast<uint8_t *>(output); @@ -134,7 +136,66 @@ void packScanlineSBGGR8(void *output, const void *input, unsigned int width) std::copy(in, in + width, out); } -void packScanlineSBGGR10P(void *output, const void *input, unsigned int width) +void packScanlineRaw10(void *output, const void *input, unsigned int width) +{ + const uint16_t *in = static_cast<const uint16_t *>(input); + uint8_t *out = static_cast<uint8_t *>(output); + + for (unsigned int i = 0; i < width; i += 4) { + *out++ = (in[0] & 0x3fc) >> 2; + *out++ = (in[0] & 0x003) << 6 | (in[1] & 0x3f0) >> 4; + *out++ = (in[1] & 0x00f) << 4 | (in[2] & 0x3c0) >> 6; + *out++ = (in[2] & 0x03f) << 2 | (in[3] & 0x300) >> 8; + *out++ = (in[3] & 0x0ff); + in += 4; + } +} + +void packScanlineRaw12(void *output, const void *input, unsigned int width) +{ + const uint16_t *in = static_cast<const uint16_t *>(input); + uint8_t *out = static_cast<uint8_t *>(output); + + for (unsigned int i = 0; i < width; i += 2) { + *out++ = (in[0] & 0xff0) >> 4; + *out++ = (in[0] & 0x00f) << 4 | (in[1] & 0xf00) >> 8; + *out++ = (in[1] & 0x0ff); + in += 2; + } +} + +void packScanlineRaw16(void *output, const void *input, unsigned int width) +{ + const uint16_t *in = static_cast<const uint16_t *>(input); + uint16_t *out = static_cast<uint16_t *>(output); + + std::copy(in, in + width, out); +} + +/* Thumbnail function for raw data with each pixel aligned to 16bit. */ +void thumbScanlineRaw(const FormatInfo &info, void *output, const void *input, + unsigned int width, unsigned int stride) +{ + const uint16_t *in = static_cast<const uint16_t *>(input); + const uint16_t *in2 = static_cast<const uint16_t *>(input) + stride / 2; + uint8_t *out = static_cast<uint8_t *>(output); + + /* Shift down to 8. */ + unsigned int shift = info.bitsPerSample - 8; + + /* Simple averaging that produces greyscale RGB values. */ + for (unsigned int x = 0; x < width; x++) { + uint16_t value = (in[0] + in[1] + in2[0] + in2[1]) >> 2; + value = value >> shift; + *out++ = value; + *out++ = value; + *out++ = value; + in += 16; + in2 += 16; + } +} + +void packScanlineRaw10_CSI2P(void *output, const void *input, unsigned int width) { const uint8_t *in = static_cast<const uint8_t *>(input); uint8_t *out = static_cast<uint8_t *>(output); @@ -150,7 +211,7 @@ void packScanlineSBGGR10P(void *output, const void *input, unsigned int width) } } -void packScanlineSBGGR12P(void *output, const void *input, unsigned int width) +void packScanlineRaw12_CSI2P(void *output, const void *input, unsigned int width) { const uint8_t *in = static_cast<const uint8_t *>(input); uint8_t *out = static_cast<uint8_t *>(output); @@ -164,7 +225,7 @@ void packScanlineSBGGR12P(void *output, const void *input, unsigned int width) } } -void thumbScanlineSBGGRxxP(const FormatInfo &info, void *output, +void thumbScanlineRaw_CSI2P(const FormatInfo &info, void *output, const void *input, unsigned int width, unsigned int stride) { @@ -282,78 +343,150 @@ void thumbScanlineIPU3([[maybe_unused]] const FormatInfo &info, void *output, } } -static const std::map<PixelFormat, FormatInfo> formatInfo = { +const std::map<PixelFormat, FormatInfo> formatInfo = { { formats::SBGGR8, { .bitsPerSample = 8, .pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed }, - .packScanline = packScanlineSBGGR8, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw8, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SGBRG8, { .bitsPerSample = 8, .pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen }, - .packScanline = packScanlineSBGGR8, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw8, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SGRBG8, { .bitsPerSample = 8, .pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen }, - .packScanline = packScanlineSBGGR8, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw8, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SRGGB8, { .bitsPerSample = 8, .pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue }, - .packScanline = packScanlineSBGGR8, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw8, + .thumbScanline = thumbScanlineRaw_CSI2P, + } }, + { formats::SBGGR10, { + .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, { + .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, { + .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, { .bitsPerSample = 10, .pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed }, - .packScanline = packScanlineSBGGR10P, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw10_CSI2P, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SGBRG10_CSI2P, { .bitsPerSample = 10, .pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen }, - .packScanline = packScanlineSBGGR10P, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw10_CSI2P, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SGRBG10_CSI2P, { .bitsPerSample = 10, .pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen }, - .packScanline = packScanlineSBGGR10P, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw10_CSI2P, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SRGGB10_CSI2P, { .bitsPerSample = 10, .pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue }, - .packScanline = packScanlineSBGGR10P, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw10_CSI2P, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SBGGR12_CSI2P, { .bitsPerSample = 12, .pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed }, - .packScanline = packScanlineSBGGR12P, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw12_CSI2P, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SGBRG12_CSI2P, { .bitsPerSample = 12, .pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen }, - .packScanline = packScanlineSBGGR12P, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw12_CSI2P, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SGRBG12_CSI2P, { .bitsPerSample = 12, .pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen }, - .packScanline = packScanlineSBGGR12P, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw12_CSI2P, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SRGGB12_CSI2P, { .bitsPerSample = 12, .pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue }, - .packScanline = packScanlineSBGGR12P, - .thumbScanline = thumbScanlineSBGGRxxP, + .packScanline = packScanlineRaw12_CSI2P, + .thumbScanline = thumbScanlineRaw_CSI2P, } }, { formats::SBGGR10_IPU3, { .bitsPerSample = 16, @@ -381,6 +514,8 @@ static const std::map<PixelFormat, FormatInfo> formatInfo = { } }, }; +} /* namespace */ + int DNGWriter::write(const char *filename, const Camera *camera, const StreamConfiguration &config, const ControlList &metadata, @@ -522,6 +657,23 @@ int DNGWriter::write(const char *filename, const Camera *camera, TIFFWriteDirectory(tif); + /* + * Workaround for a bug introduced in libtiff version 4.5.1 and no fix + * released. In these versions the CFA* tags were missing in the field + * info. + * Introduced by: https://gitlab.com/libtiff/libtiff/-/commit/738e04099b13192bb1f654e74e9b5829313f3161 + * Fixed by: https://gitlab.com/libtiff/libtiff/-/commit/49856998c3d82e65444b47bb4fb11b7830a0c2be + */ + if (!TIFFFindField(tif, TIFFTAG_CFAREPEATPATTERNDIM, TIFF_ANY)) { + static const TIFFFieldInfo infos[] = { + { TIFFTAG_CFAREPEATPATTERNDIM, 2, 2, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, const_cast<char *>("CFARepeatPatternDim") }, + { TIFFTAG_CFAPATTERN, -1, -1, TIFF_BYTE, FIELD_CUSTOM, + 1, 1, const_cast<char *>("CFAPattern") }, + }; + TIFFMergeFieldInfo(tif, infos, 2); + } + /* Create a new IFD for the RAW image. */ const uint16_t cfaRepeatPatternDim[] = { 2, 2 }; const uint8_t cfaPlaneColor[] = { diff --git a/src/apps/common/dng_writer.h b/src/apps/common/dng_writer.h index 38f38f62..917713e6 100644 --- a/src/apps/common/dng_writer.h +++ b/src/apps/common/dng_writer.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Raspberry Pi Ltd * - * dng_writer.h - DNG writer + * DNG writer */ #pragma once diff --git a/src/apps/common/event_loop.cpp b/src/apps/common/event_loop.cpp index cb83845c..f7f9afa0 100644 --- a/src/apps/common/event_loop.cpp +++ b/src/apps/common/event_loop.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * event_loop.cpp - cam - Event loop + * cam - Event loop */ #include "event_loop.h" diff --git a/src/apps/common/event_loop.h b/src/apps/common/event_loop.h index ef79e8e5..ef129b9a 100644 --- a/src/apps/common/event_loop.h +++ b/src/apps/common/event_loop.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * event_loop.h - cam - Event loop + * cam - Event loop */ #pragma once diff --git a/src/apps/common/image.cpp b/src/apps/common/image.cpp index fe2cc6da..a2a0f58f 100644 --- a/src/apps/common/image.cpp +++ b/src/apps/common/image.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Ideas on Board Oy * - * image.cpp - Multi-planar image with access to pixel data + * Multi-planar image with access to pixel data */ #include "image.h" diff --git a/src/apps/common/image.h b/src/apps/common/image.h index 7953b177..e47e446b 100644 --- a/src/apps/common/image.h +++ b/src/apps/common/image.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2021, Ideas on Board Oy * - * image.h - Multi-planar image with access to pixel data + * Multi-planar image with access to pixel data */ #pragma once diff --git a/src/apps/common/options.cpp b/src/apps/common/options.cpp index 4f7e8691..ab19aa3d 100644 --- a/src/apps/common/options.cpp +++ b/src/apps/common/options.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * options.cpp - cam - Options parsing + * cam - Options parsing */ #include <assert.h> diff --git a/src/apps/common/options.h b/src/apps/common/options.h index 4ddd4987..9771aa7a 100644 --- a/src/apps/common/options.h +++ b/src/apps/common/options.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * options.h - cam - Options parsing + * cam - Options parsing */ #pragma once diff --git a/src/apps/common/ppm_writer.cpp b/src/apps/common/ppm_writer.cpp index a8ccf67a..d6c8641d 100644 --- a/src/apps/common/ppm_writer.cpp +++ b/src/apps/common/ppm_writer.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2024 Red Hat, Inc. * - * ppm_writer.cpp - PPM writer + * PPM writer */ #include "ppm_writer.h" diff --git a/src/apps/common/ppm_writer.h b/src/apps/common/ppm_writer.h index 4c38f5ce..8c8d2e15 100644 --- a/src/apps/common/ppm_writer.h +++ b/src/apps/common/ppm_writer.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2024, Red Hat, Inc. * - * ppm_writer.h - PPM writer + * PPM writer */ #pragma once diff --git a/src/apps/common/stream_options.cpp b/src/apps/common/stream_options.cpp index 663b979a..99239e07 100644 --- a/src/apps/common/stream_options.cpp +++ b/src/apps/common/stream_options.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Raspberry Pi Ltd * - * stream_options.cpp - Helper to parse options for streams + * Helper to parse options for streams */ #include "stream_options.h" diff --git a/src/apps/common/stream_options.h b/src/apps/common/stream_options.h index a5f3bde0..a93f104c 100644 --- a/src/apps/common/stream_options.h +++ b/src/apps/common/stream_options.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2020, Raspberry Pi Ltd * - * stream_options.h - Helper to parse options for streams + * Helper to parse options for streams */ #pragma once |