comparison mupdf-source/thirdparty/zxing-cpp/core/src/BinaryBitmap.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
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*
2 * Copyright 2020 Axel Waggershauser
3 */
4 // SPDX-License-Identifier: Apache-2.0
5
6 #include "BinaryBitmap.h"
7
8 #include "BitMatrix.h"
9
10 #include <mutex>
11
12 namespace ZXing {
13
14 struct BinaryBitmap::Cache
15 {
16 std::once_flag once;
17 std::shared_ptr<const BitMatrix> matrix;
18 };
19
20 BitMatrix BinaryBitmap::binarize(const uint8_t threshold) const
21 {
22 BitMatrix res(width(), height());
23
24 if (_buffer.pixStride() == 1 && _buffer.rowStride() == _buffer.width()) {
25 // Specialize for a packed buffer with pixStride 1 to support auto vectorization (16x speedup on AVX2)
26 auto dst = res.row(0).begin();
27 for (auto src = _buffer.data(0, 0), end = _buffer.data(0, height()); src != end; ++src, ++dst)
28 *dst = (*src <= threshold) * BitMatrix::SET_V;
29 } else {
30 auto processLine = [&res, threshold](int y, const auto* src, const int stride) {
31 for (auto& dst : res.row(y)) {
32 dst = (*src <= threshold) * BitMatrix::SET_V;
33 src += stride;
34 }
35 };
36 for (int y = 0; y < res.height(); ++y) {
37 auto src = _buffer.data(0, y) + GreenIndex(_buffer.format());
38 // Specialize the inner loop for strides 1 and 4 to support auto vectorization
39 switch (_buffer.pixStride()) {
40 case 1: processLine(y, src, 1); break;
41 case 4: processLine(y, src, 4); break;
42 default: processLine(y, src, _buffer.pixStride()); break;
43 }
44 }
45 }
46
47 return res;
48 }
49
50 BinaryBitmap::BinaryBitmap(const ImageView& buffer) : _cache(new Cache), _buffer(buffer) {}
51
52 BinaryBitmap::~BinaryBitmap() = default;
53
54 const BitMatrix* BinaryBitmap::getBitMatrix() const
55 {
56 std::call_once(_cache->once, [&](){_cache->matrix = getBlackMatrix();});
57 return _cache->matrix.get();
58 }
59
60 void BinaryBitmap::invert()
61 {
62 if (_cache->matrix) {
63 auto matrix = const_cast<BitMatrix*>(_cache->matrix.get());
64 matrix->flipAll();
65 }
66 _inverted = true;
67 }
68
69 template <typename F>
70 void SumFilter(const BitMatrix& in, BitMatrix& out, F func)
71 {
72 assert(in.height() >= 3);
73
74 const auto* in0 = in.row(0).begin();
75 const auto* in1 = in.row(1).begin();
76 const auto* in2 = in.row(2).begin();
77
78 for (auto *out1 = out.row(1).begin() + 1, *end = out.row(out.height() - 1).begin() - 1; out1 != end; ++in0, ++in1, ++in2, ++out1) {
79 int sum = 0;
80 for (int j = 0; j < 3; ++j)
81 sum += in0[j] + in1[j] + in2[j];
82
83 *out1 = func(sum);
84 }
85 }
86
87 void BinaryBitmap::close()
88 {
89 if (_cache->matrix) {
90 auto& matrix = *const_cast<BitMatrix*>(_cache->matrix.get());
91 BitMatrix tmp(matrix.width(), matrix.height());
92
93 // dilate
94 SumFilter(matrix, tmp, [](int sum) { return (sum > 0 * BitMatrix::SET_V) * BitMatrix::SET_V; });
95 // erode
96 SumFilter(tmp, matrix, [](int sum) { return (sum == 9 * BitMatrix::SET_V) * BitMatrix::SET_V; });
97 }
98 _closed = true;
99 }
100
101 } // ZXing