From 500f1e9eaeca29b255d0364e1383d70ade1d1177 Mon Sep 17 00:00:00 2001
From: Martin Jansa <martin.jansa@gmail.com>
Date: Tue, 30 Jan 2024 12:02:09 +0000
Subject: [PATCH] Revert "Support compressed pixel formats when saving DNGs"

This reverts commit a85aed7603a0b69a6685d3f81ee860246d5b1621.

This requires rpi specific fork of libcamera to provide e.g.
formats::RGGB16_PISP_COMP1
added in:
https://github.com/raspberrypi/libcamera/commit/fb3cb844f2117f30d3eeece99d6ce4d02624e492
but not included in libcamera from meta-oe:
https://git.openembedded.org/meta-openembedded/commit/?id=711c6fbce39df685225bca081c5f42bae2de658b

See https://github.com/raspberrypi/rpicam-apps/issues/627

Upstream-Status: Pending
---
 image/dng.cpp | 205 ++++++++------------------------------------------
 1 file changed, 33 insertions(+), 172 deletions(-)

diff --git a/image/dng.cpp b/image/dng.cpp
index 7692f92..fc10439 100644
--- a/image/dng.cpp
+++ b/image/dng.cpp
@@ -33,47 +33,40 @@ struct BayerFormat
 	int bits;
 	char const *order;
 	bool packed;
-	bool compressed;
 };
 
 static const std::map<PixelFormat, BayerFormat> bayer_formats =
 {
-	{ formats::SRGGB10_CSI2P, { "RGGB-10", 10, TIFF_RGGB, true, false } },
-	{ formats::SGRBG10_CSI2P, { "GRBG-10", 10, TIFF_GRBG, true, false } },
-	{ formats::SBGGR10_CSI2P, { "BGGR-10", 10, TIFF_BGGR, true, false } },
-	{ formats::SGBRG10_CSI2P, { "GBRG-10", 10, TIFF_GBRG, true, false } },
-
-	{ formats::SRGGB10, { "RGGB-10", 10, TIFF_RGGB, false, false } },
-	{ formats::SGRBG10, { "GRBG-10", 10, TIFF_GRBG, false, false } },
-	{ formats::SBGGR10, { "BGGR-10", 10, TIFF_BGGR, false, false } },
-	{ formats::SGBRG10, { "GBRG-10", 10, TIFF_GBRG, false, false } },
-
-	{ formats::SRGGB12_CSI2P, { "RGGB-12", 12, TIFF_RGGB, true, false } },
-	{ formats::SGRBG12_CSI2P, { "GRBG-12", 12, TIFF_GRBG, true, false } },
-	{ formats::SBGGR12_CSI2P, { "BGGR-12", 12, TIFF_BGGR, true, false } },
-	{ formats::SGBRG12_CSI2P, { "GBRG-12", 12, TIFF_GBRG, true, false } },
-
-	{ formats::SRGGB12, { "RGGB-12", 12, TIFF_RGGB, false, false } },
-	{ formats::SGRBG12, { "GRBG-12", 12, TIFF_GRBG, false, false } },
-	{ formats::SBGGR12, { "BGGR-12", 12, TIFF_BGGR, false, false } },
-	{ formats::SGBRG12, { "GBRG-12", 12, TIFF_GBRG, false, false } },
-
-	{ formats::SRGGB16, { "RGGB-16", 16, TIFF_RGGB, false, false } },
-	{ formats::SGRBG16, { "GRBG-16", 16, TIFF_GRBG, false, false } },
-	{ formats::SBGGR16, { "BGGR-16", 16, TIFF_BGGR, false, false } },
-	{ formats::SGBRG16, { "GBRG-16", 16, TIFF_GBRG, false, false } },
-
-	{ formats::R10_CSI2P, { "BGGR-10", 10, TIFF_BGGR, true, false } },
-	{ formats::R10, { "BGGR-10", 10, TIFF_BGGR, false, false } },
+	{ formats::SRGGB10_CSI2P, { "RGGB-10", 10, TIFF_RGGB, true } },
+	{ formats::SGRBG10_CSI2P, { "GRBG-10", 10, TIFF_GRBG, true } },
+	{ formats::SBGGR10_CSI2P, { "BGGR-10", 10, TIFF_BGGR, true } },
+	{ formats::SGBRG10_CSI2P, { "GBRG-10", 10, TIFF_GBRG, true } },
+
+	{ formats::SRGGB10, { "RGGB-10", 10, TIFF_RGGB, false } },
+	{ formats::SGRBG10, { "GRBG-10", 10, TIFF_GRBG, false } },
+	{ formats::SBGGR10, { "BGGR-10", 10, TIFF_BGGR, false } },
+	{ formats::SGBRG10, { "GBRG-10", 10, TIFF_GBRG, false } },
+
+	{ formats::SRGGB12_CSI2P, { "RGGB-12", 12, TIFF_RGGB, true } },
+	{ formats::SGRBG12_CSI2P, { "GRBG-12", 12, TIFF_GRBG, true } },
+	{ formats::SBGGR12_CSI2P, { "BGGR-12", 12, TIFF_BGGR, true } },
+	{ formats::SGBRG12_CSI2P, { "GBRG-12", 12, TIFF_GBRG, true } },
+
+	{ formats::SRGGB12, { "RGGB-12", 12, TIFF_RGGB, false } },
+	{ formats::SGRBG12, { "GRBG-12", 12, TIFF_GRBG, false } },
+	{ formats::SBGGR12, { "BGGR-12", 12, TIFF_BGGR, false } },
+	{ formats::SGBRG12, { "GBRG-12", 12, TIFF_GBRG, false } },
+
+	{ formats::SRGGB16, { "RGGB-16", 16, TIFF_RGGB, false } },
+	{ formats::SGRBG16, { "GRBG-16", 16, TIFF_GRBG, false } },
+	{ formats::SBGGR16, { "BGGR-16", 16, TIFF_BGGR, false } },
+	{ formats::SGBRG16, { "GBRG-16", 16, TIFF_GBRG, false } },
+
+	{ formats::R10_CSI2P, { "BGGR-10", 10, TIFF_BGGR, true } },
+	{ formats::R10, { "BGGR-10", 10, TIFF_BGGR, false } },
 	// Currently not in the main libcamera branch
 	//{ formats::R12_CSI2P, { "BGGR-12", 12, TIFF_BGGR, true } },
-	{ formats::R12, { "BGGR-12", 12, TIFF_BGGR, false, false } },
-
-	/* PiSP compressed formats. */
-	{ formats::RGGB16_PISP_COMP1, { "RGGB-16-PISP", 16, TIFF_RGGB, false, true } },
-	{ formats::GRBG16_PISP_COMP1, { "GRBG-16-PISP", 16, TIFF_GRBG, false, true } },
-	{ formats::GBRG16_PISP_COMP1, { "GBRG-16-PISP", 16, TIFF_GBRG, false, true } },
-	{ formats::BGGR16_PISP_COMP1, { "BGGR-16-PISP", 16, TIFF_BGGR, false, true } },
+	{ formats::R12, { "BGGR-12", 12, TIFF_BGGR, false } },
 };
 
 static void unpack_10bit(uint8_t const *src, StreamInfo const &info, uint16_t *dest)
@@ -124,129 +117,6 @@ static void unpack_16bit(uint8_t const *src, StreamInfo const &info, uint16_t *d
 	}
 }
 
-// We always use these compression parameters.
-#define COMPRESS_OFFSET 2048
-#define COMPRESS_MODE 1
-
-static uint16_t postprocess(uint16_t a)
-{
-	if (COMPRESS_MODE & 2)
-	{
-		if (COMPRESS_MODE == 3 && a < 0x4000)
-			a = a >> 2;
-		else if (a < 0x1000)
-			a = a >> 4;
-		else if (a < 0x1800)
-			a = (a - 0x800) >> 3;
-		else if (a < 0x3000)
-			a = (a - 0x1000) >> 2;
-		else if (a < 0x6000)
-			a = (a - 0x2000) >> 1;
-		else if (a < 0xC000)
-			a = (a - 0x4000);
-		else
-			a = 2 * (a - 0x8000);
-	}
-
-	return std::min(0xFFFF, a + COMPRESS_OFFSET);
-}
-
-static uint16_t dequantize(uint16_t q, int qmode)
-{
-	switch (qmode)
-	{
-	case 0:
-		return (q < 320) ? 16 * q : 32 * (q - 160);
-
-	case 1:
-		return 64 * q;
-
-	case 2:
-		return 128 * q;
-
-	default:
-		return (q < 94) ? 256 * q : std::min(0xFFFF, 512 * (q - 47));
-	}
-}
-
-static void subBlockFunction(uint16_t *d, uint32_t w)
-{
-	int q[4];
-
-	int qmode = (w & 3);
-	if (qmode < 3)
-	{
-		int field0 = (w >> 2) & 511;
-		int field1 = (w >> 11) & 127;
-		int field2 = (w >> 18) & 127;
-		int field3 = (w >> 25) & 127;
-		if (qmode == 2 && field0 >= 384)
-		{
-			q[1] = field0;
-			q[2] = field1 + 384;
-		}
-		else
-		{
-			q[1] = (field1 >= 64) ? field0 : field0 + 64 - field1;
-			q[2] = (field1 >= 64) ? field0 + field1 - 64 : field0;
-		}
-		int p1 = std::max(0, q[1] - 64);
-		if (qmode == 2)
-			p1 = std::min(384, p1);
-		int p2 = std::max(0, q[2] - 64);
-		if (qmode == 2)
-			p2 = std::min(384, p2);
-		q[0] = p1 + field2;
-		q[3] = p2 + field3;
-	}
-	else
-	{
-		int pack0 = (w >> 2) & 32767;
-		int pack1 = (w >> 17) & 32767;
-		q[0] = (pack0 & 15) + 16 * ((pack0 >> 8) / 11);
-		q[1] = (pack0 >> 4) % 176;
-		q[2] = (pack1 & 15) + 16 * ((pack1 >> 8) / 11);
-		q[3] = (pack1 >> 4) % 176;
-	}
-
-	d[0] = dequantize(q[0], qmode);
-	d[2] = dequantize(q[1], qmode);
-	d[4] = dequantize(q[2], qmode);
-	d[6] = dequantize(q[3], qmode);
-}
-
-static void uncompress(uint8_t const *src, StreamInfo const &info, uint16_t *dest)
-{
-	// In all cases, the *decompressed* image must be a multiple of 8 columns wide.
-	unsigned int buf_stride_pixels = (info.width + 7) & ~7;
-	for (unsigned int y = 0; y < info.height; ++y)
-	{
-		uint16_t *dp = dest + y * buf_stride_pixels;
-		uint8_t const *sp = src + y * info.stride;
-
-		for (unsigned int x = 0; x < info.width; x+=8)
-		{
-			if (COMPRESS_MODE & 1)
-			{
-				uint32_t w0 = 0, w1 = 0;
-				for (int b = 0; b < 4; ++b)
-					w0 |= (*sp++) << (b * 8);
-				for (int b = 0; b < 4; ++b)
-					w1 |= (*sp++) << (b * 8);
-				subBlockFunction(dp, w0);
-				subBlockFunction(dp + 1, w1);
-				for (int i = 0; i < 8; ++i, ++dp)
-					*dp = postprocess(*dp);
-			}
-			else
-			{
-				for (int i = 0; i < 8; ++i)
-					*dp++ = postprocess((*sp++) << 8);
-			}
-		}
-	}
-}
-
 struct Matrix
 {
 Matrix(float m0, float m1, float m2,
@@ -307,16 +177,8 @@ void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, StreamInfo const
 	BayerFormat const &bayer_format = it->second;
 	LOG(1, "Bayer format is " << bayer_format.name);
 
-	// Decompression will require a buffer that's 8 pixels aligned.
-	unsigned int buf_stride_pixels = info.width;
-	unsigned int buf_stride_pixels_padded = (buf_stride_pixels + 7) & ~7;
-	std::vector<uint16_t> buf(buf_stride_pixels_padded * info.height);
-	if (bayer_format.compressed)
-	{
-		uncompress(mem[0].data(), info, &buf[0]);
-		buf_stride_pixels = buf_stride_pixels_padded;
-	}
-	else if (bayer_format.packed)
+	std::vector<uint16_t> buf(info.width * info.height);
+	if (bayer_format.packed)
 	{
 		switch (bayer_format.bits)
 		{
@@ -444,9 +306,8 @@ void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, StreamInfo const
 		{
 			for (unsigned int x = 0; x < (info.width >> 4); x++)
 			{
-				unsigned int off = (y * buf_stride_pixels + x) << 4;
-				uint32_t grey =
-					buf[off] + buf[off + 1] + buf[off + buf_stride_pixels] + buf[off + buf_stride_pixels + 1];
+				unsigned int off = (y * info.width + x) << 4;
+				uint32_t grey = buf[off] + buf[off + 1] + buf[off + info.width] + buf[off + info.width + 1];
 				grey = (grey << 14) >> bayer_format.bits;
 				grey = sqrt((double)grey); // simple "gamma correction"
 				thumb_buf[3 * x] = thumb_buf[3 * x + 1] = thumb_buf[3 * x + 2] = grey;
@@ -478,7 +339,7 @@ void dng_save(std::vector<libcamera::Span<uint8_t>> const &mem, StreamInfo const
 
 		for (unsigned int y = 0; y < info.height; y++)
 		{
-			if (TIFFWriteScanline(tif, &buf[buf_stride_pixels * y], y, 0) != 1)
+			if (TIFFWriteScanline(tif, &buf[info.width * y], y, 0) != 1)
 				throw std::runtime_error("error writing DNG image data");
 		}
 
