diff mupdf-source/thirdparty/zxing-cpp/core/src/BitMatrix.h @ 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/BitMatrix.h	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,195 @@
+/*
+* Copyright 2016 Nu-book Inc.
+* Copyright 2016 ZXing authors
+* Copyright 2022 Axel Waggershauser
+*/
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "Matrix.h"
+#include "Point.h"
+#include "Range.h"
+
+#include <cstdint>
+#include <stdexcept>
+#include <vector>
+
+namespace ZXing {
+
+class BitArray;
+class ByteMatrix;
+
+/**
+ * @brief A simple, fast 2D array of bits.
+ */
+class BitMatrix
+{
+	int _width = 0;
+	int _height = 0;
+	using data_t = uint8_t;
+
+	std::vector<data_t> _bits;
+	// There is nothing wrong to support this but disable to make it explicit since we may copy something very big here.
+	// Use copy() below.
+	BitMatrix(const BitMatrix&) = default;
+	BitMatrix& operator=(const BitMatrix&) = delete;
+
+	const data_t& get(int i) const
+	{
+#if 1
+		return _bits.at(i);
+#else
+		return _bits[i];
+#endif
+	}
+
+	data_t& get(int i) { return const_cast<data_t&>(static_cast<const BitMatrix*>(this)->get(i)); }
+
+	bool getTopLeftOnBit(int &left, int& top) const;
+	bool getBottomRightOnBit(int &right, int& bottom) const;
+
+public:
+	static constexpr data_t SET_V = 0xff; // allows playing with SIMD binarization
+	static constexpr data_t UNSET_V = 0;
+	static_assert(bool(SET_V) && !bool(UNSET_V), "SET_V needs to evaluate to true, UNSET_V to false, see iterator usage");
+
+	BitMatrix() = default;
+
+#if defined(__llvm__) || (defined(__GNUC__) && (__GNUC__ > 7))
+	__attribute__((no_sanitize("signed-integer-overflow")))
+#endif
+	BitMatrix(int width, int height) : _width(width), _height(height), _bits(width * height, UNSET_V)
+	{
+		if (width != 0 && Size(_bits) / width != height)
+			throw std::invalid_argument("Invalid size: width * height is too big");
+	}
+
+	explicit BitMatrix(int dimension) : BitMatrix(dimension, dimension) {} // Construct a square matrix.
+
+	BitMatrix(BitMatrix&& other) noexcept = default;
+	BitMatrix& operator=(BitMatrix&& other) noexcept = default;
+
+	BitMatrix copy() const { return *this; }
+
+	Range<data_t*> row(int y) { return {_bits.data() + y * _width, _bits.data() + (y + 1) * _width}; }
+	Range<const data_t*> row(int y) const { return {_bits.data() + y * _width, _bits.data() + (y + 1) * _width}; }
+
+	Range<StrideIter<const data_t*>> col(int x) const
+	{
+		return {{_bits.data() + x + (_height - 1) * _width, -_width}, {_bits.data() + x - _width, -_width}};
+	}
+
+	bool get(int x, int y) const { return get(y * _width + x); }
+	void set(int x, int y, bool val = true) { get(y * _width + x) = val * SET_V; }
+
+	/**
+	* <p>Flips the given bit.</p>
+	*
+	* @param x The horizontal component (i.e. which column)
+	* @param y The vertical component (i.e. which row)
+	*/
+	void flip(int x, int y)
+	{
+		auto& v = get(y * _width + x);
+		v = !v;
+	}
+
+	void flipAll()
+	{
+		for (auto& i : _bits)
+			i = !i * SET_V;
+	}
+
+	/**
+	* <p>Sets a square region of the bit matrix to true.</p>
+	*
+	* @param left The horizontal position to begin at (inclusive)
+	* @param top The vertical position to begin at (inclusive)
+	* @param width The width of the region
+	* @param height The height of the region
+	*/
+	void setRegion(int left, int top, int width, int height);
+
+	void rotate90();
+
+	void rotate180();
+
+	void mirror();
+
+	/**
+	* Find the rectangle that contains all non-white pixels. Useful for detection of 'pure' barcodes.
+	*
+	* @return True iff this rectangle is at least minWidth x minHeight pixels big
+	*/
+	bool findBoundingBox(int &left, int& top, int& width, int& height, int minSize = 1) const;
+
+	int width() const { return _width; }
+
+	int height() const { return _height; }
+
+	bool empty() const { return _bits.empty(); }
+
+	friend bool operator==(const BitMatrix& a, const BitMatrix& b)
+	{
+		return a._width == b._width && a._height == b._height && a._bits == b._bits;
+	}
+
+	template <typename T>
+	bool isIn(PointT<T> p, int b = 0) const noexcept
+	{
+		return b <= p.x && p.x < width() - b && b <= p.y && p.y < height() - b;
+	}
+
+	bool get(PointI p) const { return get(p.x, p.y); }
+	bool get(PointF p) const { return get(PointI(p)); }
+	void set(PointI p, bool v = true) { set(p.x, p.y, v); }
+	void set(PointF p, bool v = true) { set(PointI(p), v); }
+};
+
+void GetPatternRow(const BitMatrix& matrix, int r, std::vector<uint16_t>& pr, bool transpose);
+
+/**
+ * @brief Inflate scales a BitMatrix up and adds a quiet Zone plus padding
+ * @param input matrix to be expanded
+ * @param width new width in bits (pixel)
+ * @param height new height in bits (pixel)
+ * @param quietZone size of quiet zone to add in modules
+ * @return expanded BitMatrix, maybe move(input) if size did not change
+ */
+BitMatrix Inflate(BitMatrix&& input, int width, int height, int quietZone);
+
+/**
+ * @brief Deflate (crop + subsample) a bit matrix
+ * @param input matrix to be shrinked
+ * @param width new width
+ * @param height new height
+ * @param top cropping starts at top row
+ * @param left cropping starts at left col
+ * @param subSampling typically the module size
+ * @return deflated input
+ */
+BitMatrix Deflate(const BitMatrix& input, int width, int height, float top, float left, float subSampling);
+
+template<typename T>
+BitMatrix ToBitMatrix(const Matrix<T>& in, T trueValue = {true})
+{
+	BitMatrix out(in.width(), in.height());
+	for (int y = 0; y < in.height(); ++y)
+		for (int x = 0; x < in.width(); ++x)
+			if (in.get(x, y) == trueValue)
+				out.set(x, y);
+	return out;
+}
+
+template<typename T>
+Matrix<T> ToMatrix(const BitMatrix& in, T black = 0, T white = ~0)
+{
+	Matrix<T> res(in.width(), in.height());
+	for (int y = 0; y < in.height(); ++y)
+		for (int x = 0; x < in.width(); ++x)
+			res.set(x, y, in.get(x, y) ? black : white);
+	return res;
+}
+
+} // ZXing