diff mupdf-source/thirdparty/zxing-cpp/core/src/GridSampler.cpp @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/thirdparty/zxing-cpp/core/src/GridSampler.cpp	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,89 @@
+/*
+* Copyright 2016 Nu-book Inc.
+* Copyright 2016 ZXing authors
+* Copyright 2020 Axel Waggershauser
+*/
+// SPDX-License-Identifier: Apache-2.0
+
+#include "GridSampler.h"
+
+#ifdef PRINT_DEBUG
+#include "LogMatrix.h"
+#include "BitMatrixIO.h"
+#endif
+
+namespace ZXing {
+
+#ifdef PRINT_DEBUG
+LogMatrix log;
+#endif
+
+DetectorResult SampleGrid(const BitMatrix& image, int width, int height, const PerspectiveTransform& mod2Pix)
+{
+	return SampleGrid(image, width, height, {ROI{0, width, 0, height, mod2Pix}});
+}
+
+DetectorResult SampleGrid(const BitMatrix& image, int width, int height, const ROIs& rois)
+{
+#ifdef PRINT_DEBUG
+	LogMatrix log;
+	static int i = 0;
+	LogMatrixWriter lmw(log, image, 5, "grid" + std::to_string(i++) + ".pnm");
+#endif
+	if (width <= 0 || height <= 0)
+		return {};
+
+	for (auto&& [x0, x1, y0, y1, mod2Pix] : rois) {
+		// Precheck the corners of every roi to bail out early if the grid is "obviously" not completely inside the image
+		auto isInside = [&mod2Pix = mod2Pix, &image](int x, int y) { return image.isIn(mod2Pix(centered(PointI(x, y)))); };
+		if (!mod2Pix.isValid() || !isInside(x0, y0) || !isInside(x1 - 1, y0) || !isInside(x1 - 1, y1 - 1) || !isInside(x0, y1 - 1))
+			return {};
+	}
+
+	BitMatrix res(width, height);
+	for (auto&& [x0, x1, y0, y1, mod2Pix] : rois) {
+		for (int y = y0; y < y1; ++y)
+			for (int x = x0; x < x1; ++x) {
+				auto p = mod2Pix(centered(PointI{x, y}));
+				// Due to a "numerical instability" in the PerspectiveTransform generation/application it has been observed
+				// that even though all boundary grid points get projected inside the image, it can still happen that an
+				// inner grid points is not. See #563. A true perspective transformation cannot have this property.
+				// The following check takes 100% care of the issue and turned out to be less of a performance impact than feared.
+				// TODO: Check some mathematical/numercial property of mod2Pix to determine if it is a perspective transforation.
+				if (!image.isIn(p))
+					return {};
+
+#ifdef PRINT_DEBUG
+				log(p, 3);
+#endif
+#if 0
+				int sum = 0;
+				for (int dy = -1; dy <= 1; ++dy)
+					for (int dx = -1; dx <= 1; ++dx)
+						sum += image.get(p + PointF(dx, dy));
+				if (sum >= 5)
+#else
+				if (image.get(p))
+#endif
+					res.set(x, y);
+			}
+	}
+
+#ifdef PRINT_DEBUG
+	printf("width: %d, height: %d\n", width, height);
+//	printf("%s", ToString(res).c_str());
+#endif
+
+	auto projectCorner = [&](PointI p) {
+		for (auto&& [x0, x1, y0, y1, mod2Pix] : rois)
+			if (x0 <= p.x && p.x <= x1 && y0 <= p.y && p.y <= y1)
+				return PointI(mod2Pix(PointF(p)) + PointF(0.5, 0.5));
+
+		return PointI();
+	};
+
+	return {std::move(res),
+			{projectCorner({0, 0}), projectCorner({width, 0}), projectCorner({width, height}), projectCorner({0, height})}};
+	}
+
+} // ZXing