comparison mupdf-source/thirdparty/zxing-cpp/core/src/BitMatrix.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 2016 Nu-book Inc.
3 * Copyright 2016 ZXing authors
4 */
5 // SPDX-License-Identifier: Apache-2.0
6
7 #include "BitMatrix.h"
8
9 #include "Pattern.h"
10
11 #include <algorithm>
12 #include <stdexcept>
13 #include <utility>
14
15 namespace ZXing {
16
17 void
18 BitMatrix::setRegion(int left, int top, int width, int height)
19 {
20 if (top < 0 || left < 0) {
21 throw std::invalid_argument("BitMatrix::setRegion(): Left and top must be nonnegative");
22 }
23 if (height < 1 || width < 1) {
24 throw std::invalid_argument("BitMatrix::setRegion(): Height and width must be at least 1");
25 }
26 int right = left + width;
27 int bottom = top + height;
28 if (bottom > _height || right > _width) {
29 throw std::invalid_argument("BitMatrix::setRegion(): The region must fit inside the matrix");
30 }
31 for (int y = top; y < bottom; y++) {
32 auto offset = y * _width;
33 for (int x = left; x < right; x++) {
34 _bits[offset + x] = SET_V;
35 }
36 }
37 }
38
39 void
40 BitMatrix::rotate90()
41 {
42 BitMatrix result(height(), width());
43 for (int x = 0; x < width(); ++x) {
44 for (int y = 0; y < height(); ++y) {
45 if (get(x, y)) {
46 result.set(y, width() - x - 1);
47 }
48 }
49 }
50 *this = std::move(result);
51 }
52
53 void
54 BitMatrix::rotate180()
55 {
56 std::reverse(_bits.begin(), _bits.end());
57 }
58
59 void
60 BitMatrix::mirror()
61 {
62 for (int x = 0; x < _width; x++) {
63 for (int y = x + 1; y < _height; y++) {
64 if (get(x, y) != get(y, x)) {
65 flip(y, x);
66 flip(x, y);
67 }
68 }
69 }
70 }
71
72 bool
73 BitMatrix::findBoundingBox(int &left, int& top, int& width, int& height, int minSize) const
74 {
75 int right, bottom;
76 if (!getTopLeftOnBit(left, top) || !getBottomRightOnBit(right, bottom) || bottom - top + 1 < minSize)
77 return false;
78
79 for (int y = top; y <= bottom; y++ ) {
80 for (int x = 0; x < left; ++x)
81 if (get(x, y)) {
82 left = x;
83 break;
84 }
85 for (int x = _width-1; x > right; x--)
86 if (get(x, y)) {
87 right = x;
88 break;
89 }
90 }
91
92 width = right - left + 1;
93 height = bottom - top + 1;
94 return width >= minSize && height >= minSize;
95 }
96
97 static auto isSet = [](auto v) { return bool(v); };
98
99 bool
100 BitMatrix::getTopLeftOnBit(int& left, int& top) const
101 {
102 int bitsOffset = (int)std::distance(_bits.begin(), std::find_if(_bits.begin(), _bits.end(), isSet));
103 if (bitsOffset == Size(_bits)) {
104 return false;
105 }
106 top = bitsOffset / _width;
107 left = (bitsOffset % _width);
108 return true;
109 }
110
111 bool
112 BitMatrix::getBottomRightOnBit(int& right, int& bottom) const
113 {
114 int bitsOffset = Size(_bits) - 1 - (int)std::distance(_bits.rbegin(), std::find_if(_bits.rbegin(), _bits.rend(), isSet));
115 if (bitsOffset < 0) {
116 return false;
117 }
118
119 bottom = bitsOffset / _width;
120 right = (bitsOffset % _width);
121 return true;
122 }
123
124 void GetPatternRow(const BitMatrix& matrix, int r, std::vector<uint16_t>& pr, bool transpose)
125 {
126 if (transpose)
127 GetPatternRow(matrix.col(r), pr);
128 else
129 GetPatternRow(matrix.row(r), pr);
130 }
131
132 BitMatrix Inflate(BitMatrix&& input, int width, int height, int quietZone)
133 {
134 const int codeWidth = input.width();
135 const int codeHeight = input.height();
136 const int outputWidth = std::max(width, codeWidth + 2 * quietZone);
137 const int outputHeight = std::max(height, codeHeight + 2 * quietZone);
138
139 if (input.width() == outputWidth && input.height() == outputHeight)
140 return std::move(input);
141
142 const int scale = std::min((outputWidth - 2*quietZone) / codeWidth, (outputHeight - 2*quietZone) / codeHeight);
143 // Padding includes both the quiet zone and the extra white pixels to
144 // accommodate the requested dimensions.
145 const int leftPadding = (outputWidth - (codeWidth * scale)) / 2;
146 const int topPadding = (outputHeight - (codeHeight * scale)) / 2;
147
148 BitMatrix result(outputWidth, outputHeight);
149
150 for (int inputY = 0, outputY = topPadding; inputY < input.height(); ++inputY, outputY += scale) {
151 for (int inputX = 0, outputX = leftPadding; inputX < input.width(); ++inputX, outputX += scale) {
152 if (input.get(inputX, inputY))
153 result.setRegion(outputX, outputY, scale, scale);
154 }
155 }
156
157 return result;
158 }
159
160 BitMatrix Deflate(const BitMatrix& input, int width, int height, float top, float left, float subSampling)
161 {
162 BitMatrix result(width, height);
163
164 for (int y = 0; y < result.height(); y++) {
165 auto yOffset = top + y * subSampling;
166 for (int x = 0; x < result.width(); x++) {
167 if (input.get(PointF(left + x * subSampling, yOffset)))
168 result.set(x, y);
169 }
170 }
171
172 return result;
173 }
174
175 } // ZXing