Ocean
Loading...
Searching...
No Matches
MicroQRCodeEncoder.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#pragma once
9
11
13
15
16#include "ocean/math/Vector2.h"
17
18#include <cctype>
19
20namespace Ocean
21{
22
23namespace CV
24{
25
26namespace Detector
27{
28
29namespace QRCodes
30{
31
32/**
33 * This class implements an encoder and decoder for QR codes.
34 * @ingroup cvdetectorqrcodes
35 */
36class OCEAN_CV_DETECTOR_QRCODES_EXPORT MicroQRCodeEncoder : public QRCodeEncoderBase
37{
38 public:
39
40 /**
41 * Enum for the mask patterns used to shuffle modules of a Micro QR code.
42 * The values of the enum items correspond to the standard-defined bit sequences for the masks (2 bits long)
43 */
44 enum MaskingPattern : uint32_t
45 {
46 /// Masking condition: i mod 2 = 0
47 MP_PATTERN_0 = 0b00u,
48
49 /// Masking condition: ((i div 2) + (j div 3)) mod 2 = 0
50 MP_PATTERN_1 = 0b01u,
51
52 /// Masking condition: ((i j) mod 2 + (i j) mod 3) mod 2 = 0
53 MP_PATTERN_2 = 0b10u,
54
55 /// Masking condition: ((i j) mod 3 + (i+j) mod 2) mod 2 = 0
56 MP_PATTERN_3 = 0b11u,
57
58 /// Denotes unknown masking patterns (not part of the standard)
59 MP_PATTERN_UNKNOWN = uint32_t(-1)
60 };
61
62 static constexpr uint32_t INVALID_VALUE = uint32_t(-1);
63
64 public:
65
66 /**
67 * Encode text and store it in a QR code, will automatically choose the most efficient encodation mode
68 * @param text The text/data to be encoded as a QR code
69 * @param errorCorrectionCapacity Specifies the level of possible error correction
70 * @param qrcode The Micro QR code that will store the encoded data
71 * @return `SC_SUCCESS` on success, otherwise it will return a status indicating the reason for failure
72 */
73 static QRCodeEncoderBase::StatusCode encodeText(const std::string& text, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, MicroQRCode& qrcode);
74
75 /**
76 * Encode binary data and store it in a QR code, will always use the byte encodation mode
77 * @param data The data to be encoded as a QR code
78 * @param errorCorrectionCapacity Specifies the level of possible error correction
79 * @param qrcode The Micro QR code that will store the encoded data
80 * @return `SC_SUCCESS` on success, otherwise it will return a status indicating the reason for failure
81 */
82 static QRCodeEncoderBase::StatusCode encodeBinary(const std::vector<uint8_t>& data, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, MicroQRCode& qrcode);
83
84 /**
85 * Encodes the error correction level and the index of the masking pattern as a sequence of 15 bits with error correction ((15, 5) BCH code).
86 * @param version The version of the Micro QR code that will be encoded
87 * @param errorCorrectionCapacity An error correction capacity that will be decoded
88 * @param maskingPattern The masking pattern that will be encoded
89 * @return The error correction level and masking pattern encoded as a sequence of 15 bits
90 */
91 static inline uint32_t encodeFormat(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const MaskingPattern maskingPattern);
92
93 /**
94 * Decodes a sequence of 15 bits and extracts the encoded error correction level and index of the masking pattern
95 * Note: the format bit sequence can contain up to 3 bit error. More bit errors will cause this function to fail because the result would be ambiguous.
96 * @param formatBits A sequence of 15 bits containing the format information, range: [0, 2^15)
97 * @param version The version extracted from the bit sequence
98 * @param errorCorrectionCapacity The error correction capacity extracted from the bit sequence
99 * @param maskingPattern The masking pattern extracted from the bit sequence
100 * @return True if the sequence was decoded successfully, otherwise false
101 */
102 static inline bool decodeFormatBits(const uint32_t formatBits, unsigned int& version, MicroQRCode::ErrorCorrectionCapacity& errorCorrectionCapacity, MaskingPattern& maskingPattern);
103
104 /**
105 * Encodes the format information as a sequence of 15 bits with error correction ((15, 5) BCH code).
106 * @param format The format bit sequence consisting of the concatenated error correction capacity (2 bits) and masking pattern (3 bits), range: [0, 32)
107 * @return The error correction level and masking pattern encoded as a sequence of 15 bits
108 * @sa encodeFormat(const ErrorCorrectionCapacity, const MaskingPattern)
109 */
110 static inline uint32_t encodeFormatBits(const uint32_t format);
111
112 protected:
113
114 /**
115 * Helper function to initialize a Micro QR code instance
116 * @param version The version of this Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
117 * @param errorCorrectionCapacity The error correction level that will be used to generate the error-corrected codewords stored in this Micro QR code
118 * @param rawCodewords The encoded codewords. The size must fit exactly into the selected version of this Micro QR code
119 * @param mask The index of the bit shuffle masked that was used to generate the modules of this Micro QR code
120 * @param modules The resulting modules of the Micro QR code
121 */
122 static void addErrorCorrectionAndCreateQRCode(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const Codewords& rawCodewords, MaskingPattern mask, std::vector<uint8_t>& modules);
123
124 /**
125 * Encodes segments and writes them into a Micro QR code
126 * @param segments The raw segements that will be encoded and written into the Micro QR code instance, `qrcode`
127 * @param errorCorrectionCapacity The desired level of error recovery capacity. Note: if `maximizeErrorCorrectionCapacity` is true, this function will increase this level as long as it doesn't increase the size of the smallest Micro QR code that can fit the data
128 * @param modules The resulting modules of the Micro QR code
129 * @param version The resulting version of the Micro QR code
130 * @param finalErrorCorrectionCapacity The resulting error correction capacity that the Micro QR code will finally have
131 * @param minVersion The minimum version that the final Micro QR code is supposed to have, range: [1, maxVersion]
132 * @param maxVersion The maximum version that the final Micro QR code is supposed to have, range: [minVersion, 4]. Note: if this value is chosen too small, the initialization may fail
133 * @param mask The index of the bit shuffle mask that is to be used, range: [0, 3] or (unsigned int)(-1). The latter value will cause this function to automatically select the optimal mask (cf. ISO/IEC 18004:2015, Section 7.8.3)
134 * @param maximizeErrorCorrectionCapacity If true, this function will try to maximize the error correction level as long as it doesn't increase the size of the smallest Micro QR code that can fit the data, cf. `errorCorrectionCapacity`
135 * @return `SC_SUCCESS` on success, otherwise it will return a status indicating the reason for failure
136 */
137 static QRCodeEncoderBase::StatusCode encodeSegments(const Segments& segments, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, std::vector<uint8_t>& modules, unsigned int& version, MicroQRCode::ErrorCorrectionCapacity& finalErrorCorrectionCapacity, unsigned int minVersion = 1u, unsigned int maxVersion = MicroQRCode::MAX_VERSION, const MaskingPattern mask = MP_PATTERN_UNKNOWN, const bool maximizeErrorCorrectionCapacity = true);
138
139 /**
140 * Returns the number of modules that can be used to store data for a given Micro QR code version
141 * This is the number of all modules less the number of function modules (finder pattern, timing pattern, version and format information, and separators)
142 * @param version The version of a Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
143 * @return The number of modules that can be used to store data
144 */
145 static inline unsigned int totalNumberRawDataModules(const unsigned int version);
146
147 /**
148 * Return the number of codeword bits for a specified version and error correction level
149 * @param version The version of a Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
150 * @param errorCorrectionCapacity The error correction capacity, must be valid given for the version, cf. ISO/IEC 18004:2015, Table 2
151 * @return The total number of codeword bits that fit into such a Micro QR code
152 */
153 static inline unsigned int totalNumberDataCodewordBits(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity);
154
155 /**
156 * Gets the symbol number for the version and error correction capacity
157 * @param version The version of the Micro QR code, range [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
158 * @param errorCorrectionCapacity The error correction capacity, must be valid given for the version, cf. ISO/IEC 18004:2015, Table 2
159 * @return The symbol number corresponding to the version and error correction capacity
160 */
161 static inline uint32_t getSymbolNumber(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity);
162
163 /**
164 * Return the number of codeword bits for a specified version and error correction level
165 * @param version The version of the Micro QR code, range [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
166 * @param errorCorrectionCapacity The error correction capacity, must be valid given for the version, cf. ISO/IEC 18004:2015, Table 2
167 * @return The total number of codewords used for error correction
168 */
169 static inline unsigned int totalNumberErrorCorrectionCodewords(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity);
170
171 /**
172 * Computes the number of bits used given some data (segments) for a specified version of a QR code (this number varies depending on the version, i.e. bits per character)
173 * @param segments The segments for which the number of bits will be computed
174 * @param version The version of a QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
175 * @param bitsUsed The total number of bits the `segments` will need in a QR code of version `version`
176 * @return True on success, otherwise false (e.g. because of an overflow)
177 */
178 static inline bool computeTotalBitsUsed(const Segments& segments, const unsigned int version, unsigned int& bitsUsed);
179
180 /**
181 * Generates the error correction codewords appends to the raw codewords
182 * @param codewords The raw code words for which the error code will be generated, must be valid
183 * @param version The version of the designated Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
184 * @param errorCorrectionCapacity The level of error correction to be used
185 * @return The error-corrected codewords
186 */
187 static Codewords addErrorCorrection(const Codewords& codewords, const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity);
188
189 /**
190 * Applies a data shuffle mask to the specified modules
191 * Note: Calling this function on the same data and with the same parameters a second time will undo the changes from the first time (because of the XOR used internally)
192 * @param modules The modules that will be shuffled, must be valid
193 * @param version The version of the designated Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
194 * @param functionPatternMask The binary mask that indicates the location of function patterns (finder patern, etc.), which should not be shuffled, cf. `setFunctionPatterns()`
195 * @param mask The index of the shuffle mask, range: [0, 3]
196 * @sa setFunctionPatterns()
197 */
198 static void applyMaskPattern(std::vector<uint8_t>& modules, const unsigned int version, const std::vector<uint8_t>& functionPatternMask, const MaskingPattern mask);
199
200 /**
201 * Computes a score (fitness value) for a module configuration, cf. ISO/IEC 18004:2015, Section 7.8.3.2
202 * The result of this function is used to determine the optimal shuffle mask that is used to generate the Micro QR code
203 * @param modules The modules of the designated Micro QR code, must be valid
204 * @param version The version of the designated Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
205 * @return The score for this configuration of modules
206 */
207 static unsigned int computeMaskPatternScore(const std::vector<uint8_t>& modules, const unsigned int version);
208
209 /**
210 * Sets (draws) the modules (bits) of all function patterns
211 * Function patterns include: finder pattern, timing patterns, version and format information, and separators
212 *
213 * This function:
214 * 1. sets the function pattern in the modules (final bit matrix).
215 * 2. returns a binary mask denoting those bits (pixels) which are function patterns, i.e. which cannot store data and must not be overwritten.
216 *
217 * The other set*-functions use this mask in order to avoid overwriting function patterns.
218 *
219 * @param modules The modules where the codewords will be written to, must be valid and of size `MicroQRCode::modulesPerSide(version) * MicroQRCode::modulesPerSide(version)`
220 * @param version The version of the designated Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
221 * @param errorCorrectionCapacity The level of error correction for the designated Micro QR code
222 * @return A binary mask that will denote all locations of the modules with function patterns (pixel value = 255) and data modules (pixel value = 0), the size will be same as for `modules`
223 */
224 static std::vector<uint8_t> setFunctionPatterns(std::vector<uint8_t>& modules, const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity);
225
226 /**
227 * Sets (draws) the codewords (zig-zag scan)
228 * Note: the size of the codewords must match exactly the version and level of error correction
229 * @param modules The modules where the codewords will be written to, must be valid and of size `MicroQRCode::modulesPerSide(version) * MicroQRCode::modulesPerSide(version)`
230 * @param codewords The modules where the codewords will be written to, must be valid
231 * @param version The version of the designated Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION], must match the size of `modules`
232 * @param errorCorrectionCapacity The level of error correction used to generate this Micro QR code
233 * @param functionPatternMask The mask that is used to identify all function patterns in the Micro QR code (and to not overwrite them), cf. `setFunctionPatterns()`
234 * @sa setFunctionPatterns()
235 */
236 static void setCodewords(std::vector<uint8_t>& modules, const Codewords& codewords, const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const std::vector<uint8_t>& functionPatternMask);
237
238 /**
239 * Sets (draws) the format information (15 bits) into the modules of a Micro QR code
240 * Note: format information = `s2 s1 s0 | m1 m0`, where `si` are the bits for the symbol number (cf. ISO/IEC 18004:2015, Table 13) and `mj` are the bits for the bit shuffle mask
241 * @param[in,out] modules The modules where the format information will be written to, must be valid and of size `MicroQRCode::modulesPerSide(version) * MicroQRCode::modulesPerSide(version)`
242 * @param version The version of the designated Micro QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION], must match the size of `modules`
243 * @param errorCorrectionCapacity The level of error correction used to generate this Micro QR code
244 * @param mask The index of the bit shuffle mask used to generate this Micro QR code, range: [0, 3]
245 * @param functionPatternMask The mask that is used to identify all function patterns in the Micro QR code (and to not overwrite them), cf. `setFunctionPatterns()`
246 * @sa setFunctionPatterns()
247 */
248 static void setFormatInformation(std::vector<uint8_t>& modules, const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const MaskingPattern mask, std::vector<uint8_t>& functionPatternMask);
249
250 /**
251 * Sets (draws) the version information (2x15 bits) into the modules of a QR code
252 * @param [in,out] modules The modules where the version information will be written to, must be valid and of size `MicroQRCode::modulesPerSide(version) * MicroQRCode::modulesPerSide(version)`
253 * @param version The version of the designated QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION], must match the size of `module`
254 * @param functionPatternMask The mask that is used to identify all function pattern in the QR code (and to not overwrite them), cf. `setFunctionPatterns()`
255 * @sa setFunctionPatterns()
256 */
257 static void setVersionInformation(std::vector<uint8_t>& modules, const unsigned int version, std::vector<uint8_t>& functionPatternMask);
258
259 /**
260 * Returns the bit sequence identifying the encodation mode set (up to 4 bits long, cf. ISO/IEC 18004:2015, Table 2)
261 * @return The bit sequence of the encodation mode used
262 */
263 static inline unsigned int encodationModeIndicatorBitSequence(const MicroQRCode::EncodingMode mode);
264
265 /**
266 * Returns the number of bits per character for a specific version and encodation mode, cf. ISO/IEC 18004:2015, Table 3
267 * @param version Version number of a QR code, range: [MicroQRCode::MIN_VERSION, MicroQRCode::MAX_VERSION]
268 * @param mode The encodation mode, must be valid given the version (minimum M2 for alphanumeric, minimum M3 for byte and kanji)
269 * @return The number of bits per character (zero for invalid combinations of version and mode)
270 */
271 static inline unsigned int getBitsInCharacterCountIndicator(const unsigned int version, const MicroQRCode::EncodingMode mode);
272};
273
275{
276 static_assert(int(MicroQRCode::EM_NUMERIC) == 0 && int(MicroQRCode::EM_ALPHANUMERIC) == 1 && int(MicroQRCode::EM_BYTE) == 2 && int(MicroQRCode::EM_KANJI) == 3, "Unexpected order of enums");
277 ocean_assert((unsigned int)mode < 4u);
278
279 constexpr unsigned int encodationModeBitSequences[4] =
280 {
281 0b000u, // MicroQRCode::EM_NUMERIC
282 0b001u, // MicroQRCode::EM_ALPHANUMERIC
283 0b010u, // MicroQRCode::EM_BYTE
284 0b011u, // MicroQRCode::EM_KANJI
285 };
286
287 ocean_assert(encodationModeBitSequences[(unsigned int)mode] >> 3u == 0u);
288 return encodationModeBitSequences[(unsigned int)mode];
289}
290
291inline unsigned int MicroQRCodeEncoder::getBitsInCharacterCountIndicator(const unsigned int version, const MicroQRCode::EncodingMode mode)
292{
293 static_assert(int(MicroQRCode::EM_NUMERIC) == 0 && int(MicroQRCode::EM_ALPHANUMERIC) == 1 && int(MicroQRCode::EM_BYTE) == 2 && int(MicroQRCode::EM_KANJI) == 3, "Unexpected order of enums");
294 ocean_assert(version >= MicroQRCode::MIN_VERSION && version <= MicroQRCode::MAX_VERSION);
295 ocean_assert((unsigned int)mode < 4u);
296
297 constexpr unsigned int characterCountIndicators[16] =
298 {
299 // Cf. ISO/IEC 18004:2015, Table 3
300 // M1
301 // | M2
302 // | | M3
303 // | | | M4
304 // | | | |
305 3u, 4u, 5u, 6u, // Numeric
306 0u, 3u, 4u, 5u, // Alphanumeric
307 0u, 0u, 4u, 5u, // Byte
308 0u, 0u, 3u, 4u // Kanji
309 };
310
311 const unsigned int column = version - 1u;
312 ocean_assert(column < 4u);
313
314 return characterCountIndicators[(unsigned int)mode * 4u + column];
315}
316
317inline uint32_t MicroQRCodeEncoder::encodeFormat(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const MaskingPattern maskingPattern)
318{
319 ocean_assert(version >= MicroQRCode::MIN_VERSION && version <= MicroQRCode::MAX_VERSION);
320 ocean_assert(errorCorrectionCapacity != MicroQRCode::ECC_INVALID && errorCorrectionCapacity != MicroQRCode::ECC_30);
321 ocean_assert(maskingPattern >> 2u == 0u);
322
323 return encodeFormatBits(getSymbolNumber(version, errorCorrectionCapacity) << 2u | maskingPattern);
324}
325
326inline bool MicroQRCodeEncoder::decodeFormatBits(const uint32_t formatBits, unsigned int& version, MicroQRCode::ErrorCorrectionCapacity& errorCorrectionCapacity, MaskingPattern& maskingPattern)
327{
328 ocean_assert(formatBits >> 15u == 0u);
329
330 uint32_t minDistanceFormat = uint32_t(-1);
331 uint32_t minDistance = uint32_t(-1);
332 uint32_t minDistanceCounter = 0u;
333
334 for (uint32_t referenceFormat = 0u; referenceFormat < 32u; ++referenceFormat)
335 {
336 const uint32_t referenceFormatBits = encodeFormatBits(referenceFormat);
337 const uint32_t distance = computeHammingWeight(formatBits ^ referenceFormatBits);
338
339 if (distance < minDistance)
340 {
341 minDistance = distance;
342 minDistanceFormat = referenceFormat;
343 minDistanceCounter = 1u;
344 }
345 else if (distance == minDistance)
346 {
347 minDistanceCounter++;
348 }
349 }
350
351 // Check if the result is unambiguous, i.e. if at least two reference formats have the same Hamming distance the input format cannot be decoded unambiguously (>= 4 bits wrong).
352
353 if (minDistanceCounter != 1u || minDistance >= 4u)
354 {
355 return false;
356 }
357
358 ocean_assert(minDistance != uint32_t(-1) && minDistanceFormat != uint32_t(-1));
359 ocean_assert(minDistanceFormat >> 5u == 0u);
360
361 switch (minDistanceFormat >> 2u)
362 {
363 case 0u:
364 version = 1u;
365 errorCorrectionCapacity = MicroQRCode::ECC_DETECTION_ONLY;
366 break;
367
368 case 1u:
369 version = 2u;
370 errorCorrectionCapacity = MicroQRCode::ECC_07;
371 break;
372
373 case 2u:
374 version = 2u;
375 errorCorrectionCapacity = MicroQRCode::ECC_15;
376 break;
377
378 case 3u:
379 version = 3u;
380 errorCorrectionCapacity = MicroQRCode::ECC_07;
381 break;
382
383 case 4u:
384 version = 3u;
385 errorCorrectionCapacity = MicroQRCode::ECC_15;
386 break;
387
388 case 5u:
389 version = 4u;
390 errorCorrectionCapacity = MicroQRCode::ECC_07;
391 break;
392
393 case 6u:
394 version = 4u;
395 errorCorrectionCapacity = MicroQRCode::ECC_15;
396 break;
397
398 case 7u:
399 version = 4u;
400 errorCorrectionCapacity = MicroQRCode::ECC_25;
401 break;
402
403 default:
404 ocean_assert(false && "Never be here!");
405 return false;
406 break;
407 }
408
409 maskingPattern = MaskingPattern(minDistanceFormat & 0b00011u);
410
411 return true;
412}
413
414inline uint32_t MicroQRCodeEncoder::encodeFormatBits(const uint32_t format)
415{
416 ocean_assert(format >> 5u == 0u);
417
418 // Details in ISO/IEC 18004:2015, Annex C
419 //
420 // Compute the remainder of polynomial long division with a (15, 5) BCH code using the generator
421 // polynomial G(x) = x^10 + x^8 + x^5 + x^4 + x^2 + x + 1 ~ 10100110111.
422
423 const uint32_t remainder = computePolynomialDivisonRemainderBCH<15u, 5u, 0b10100110111u>(format << 10u);
424
425 // Append the remainder to the format and XOR it with 100010001000101
426 const uint32_t formatBitsUnmasked = (format << 10u) ^ remainder;
427 const uint32_t formatBitsMasked = formatBitsUnmasked ^ 0b100010001000101u;
428 ocean_assert(formatBitsMasked >> 15u == 0u);
429
430 return formatBitsMasked;
431}
432
433inline unsigned int MicroQRCodeEncoder::totalNumberRawDataModules(const unsigned int version)
434{
435 ocean_assert(version >= MicroQRCode::MIN_VERSION && version <= MicroQRCode::MAX_VERSION);
436
437 // cf. ISO/IEC 18004:2015, Table 1
438 static constexpr unsigned int rawDataModuleTable[4] = {36u, 80, 132u, 192u};
439
440 const unsigned int rawDataModules = rawDataModuleTable[version - 1];
441
442 ocean_assert(rawDataModules < MicroQRCode::modulesPerSide(version) * MicroQRCode::modulesPerSide(version));
443 return rawDataModules;
444}
445
446inline unsigned int MicroQRCodeEncoder::totalNumberErrorCorrectionCodewords(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity)
447{
448 /// Number of error correction codewords, indexed by symbol number, cf. ISO/IEC 18004:2015, Table 2 and Table 9, column 4
449 static constexpr int8_t ECC_CODEWORDS[8] = {2, 5, 6, 6, 8, 8, 10, 14};
450
451 return ECC_CODEWORDS[getSymbolNumber(version, errorCorrectionCapacity)];
452}
453
454inline unsigned int MicroQRCodeEncoder::totalNumberDataCodewordBits(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity)
455{
456 return (totalNumberRawDataModules(version) - totalNumberErrorCorrectionCodewords(version, errorCorrectionCapacity) * 8u);
457}
458
459inline bool MicroQRCodeEncoder::computeTotalBitsUsed(const Segments& segments, const unsigned int version, unsigned int& bitsUsed)
460{
461 ocean_assert(version >= MicroQRCode::MIN_VERSION && version <= MicroQRCode::MAX_VERSION);
462
463 bitsUsed = 0u;
464
465 for (const Segment& segment : segments)
466 {
467 // Length of mode indicator varies by version, cf. ISO/IEC 18004:2015, Table 2
468 const unsigned int modeIndicatorBits = version - 1u;
469 const unsigned int characterCountBits = getBitsInCharacterCountIndicator(version, segment.encodationMode());
470
471 // Make sure the segment fits into the field's bit width and the sum will not overflow.
472 if (segment.characters() >= (1u << characterCountBits)
473 || (modeIndicatorBits + characterCountBits) > (NumericT<unsigned int>::maxValue() - bitsUsed)
474 || segment.bitBuffer().size() > (NumericT<unsigned int>::maxValue() - bitsUsed))
475 {
476 return false;
477 }
478
479 bitsUsed += modeIndicatorBits + characterCountBits;
480 bitsUsed += (unsigned int)segment.bitBuffer().size();
481 }
482
483 return true;
484}
485
486inline uint32_t MicroQRCodeEncoder::getSymbolNumber(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity)
487{
488 ocean_assert(version >= MicroQRCode::MIN_VERSION && version <= MicroQRCode::MAX_VERSION);
489
490 switch(errorCorrectionCapacity)
491 {
493 ocean_assert(version == 1u);
494 if (version == 1u)
495 {
496 return 0u;
497 }
498 break;
500 ocean_assert(version >= 2u && version <= MicroQRCode::MAX_VERSION);
501 if (version >= 2u && version <= MicroQRCode::MAX_VERSION)
502 {
503 return 2u * version - 3u;
504 }
505 break;
507 ocean_assert(version >= 2u && version <= MicroQRCode::MAX_VERSION);
508 if (version >= 2u && version <= MicroQRCode::MAX_VERSION)
509 {
510 return 2u * version - 2u;
511 }
512 break;
514 ocean_assert(version == MicroQRCode::MAX_VERSION);
515 if (version == MicroQRCode::MAX_VERSION)
516 {
517 return 7u;
518 }
519 break;
520 default:
521 break;
522 }
523
524 ocean_assert(false && "Never be here!");
525 return INVALID_VALUE;
526}
527
528} // namespace QRCodes
529
530} // namespace Detector
531
532} // namespace CV
533
534} // namespace Ocean
This class implements an encoder and decoder for QR codes.
Definition MicroQRCodeEncoder.h:37
static void applyMaskPattern(std::vector< uint8_t > &modules, const unsigned int version, const std::vector< uint8_t > &functionPatternMask, const MaskingPattern mask)
Applies a data shuffle mask to the specified modules Note: Calling this function on the same data and...
static void setFormatInformation(std::vector< uint8_t > &modules, const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const MaskingPattern mask, std::vector< uint8_t > &functionPatternMask)
Sets (draws) the format information (15 bits) into the modules of a Micro QR code Note: format inform...
static bool computeTotalBitsUsed(const Segments &segments, const unsigned int version, unsigned int &bitsUsed)
Computes the number of bits used given some data (segments) for a specified version of a QR code (thi...
Definition MicroQRCodeEncoder.h:459
static unsigned int totalNumberErrorCorrectionCodewords(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity)
Return the number of codeword bits for a specified version and error correction level.
Definition MicroQRCodeEncoder.h:446
static QRCodeEncoderBase::StatusCode encodeText(const std::string &text, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, MicroQRCode &qrcode)
Encode text and store it in a QR code, will automatically choose the most efficient encodation mode.
static void setVersionInformation(std::vector< uint8_t > &modules, const unsigned int version, std::vector< uint8_t > &functionPatternMask)
Sets (draws) the version information (2x15 bits) into the modules of a QR code.
static void addErrorCorrectionAndCreateQRCode(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const Codewords &rawCodewords, MaskingPattern mask, std::vector< uint8_t > &modules)
Helper function to initialize a Micro QR code instance.
static Codewords addErrorCorrection(const Codewords &codewords, const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity)
Generates the error correction codewords appends to the raw codewords.
MaskingPattern
Enum for the mask patterns used to shuffle modules of a Micro QR code.
Definition MicroQRCodeEncoder.h:45
static std::vector< uint8_t > setFunctionPatterns(std::vector< uint8_t > &modules, const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity)
Sets (draws) the modules (bits) of all function patterns Function patterns include: finder pattern,...
static QRCodeEncoderBase::StatusCode encodeSegments(const Segments &segments, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, std::vector< uint8_t > &modules, unsigned int &version, MicroQRCode::ErrorCorrectionCapacity &finalErrorCorrectionCapacity, unsigned int minVersion=1u, unsigned int maxVersion=MicroQRCode::MAX_VERSION, const MaskingPattern mask=MP_PATTERN_UNKNOWN, const bool maximizeErrorCorrectionCapacity=true)
Encodes segments and writes them into a Micro QR code.
static uint32_t encodeFormatBits(const uint32_t format)
Encodes the format information as a sequence of 15 bits with error correction ((15,...
Definition MicroQRCodeEncoder.h:414
static constexpr uint32_t INVALID_VALUE
Definition MicroQRCodeEncoder.h:62
static uint32_t encodeFormat(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const MaskingPattern maskingPattern)
Encodes the error correction level and the index of the masking pattern as a sequence of 15 bits with...
Definition MicroQRCodeEncoder.h:317
static QRCodeEncoderBase::StatusCode encodeBinary(const std::vector< uint8_t > &data, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, MicroQRCode &qrcode)
Encode binary data and store it in a QR code, will always use the byte encodation mode.
static bool decodeFormatBits(const uint32_t formatBits, unsigned int &version, MicroQRCode::ErrorCorrectionCapacity &errorCorrectionCapacity, MaskingPattern &maskingPattern)
Decodes a sequence of 15 bits and extracts the encoded error correction level and index of the maskin...
Definition MicroQRCodeEncoder.h:326
static void setCodewords(std::vector< uint8_t > &modules, const Codewords &codewords, const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity, const std::vector< uint8_t > &functionPatternMask)
Sets (draws) the codewords (zig-zag scan) Note: the size of the codewords must match exactly the vers...
static unsigned int computeMaskPatternScore(const std::vector< uint8_t > &modules, const unsigned int version)
Computes a score (fitness value) for a module configuration, cf.
static uint32_t getSymbolNumber(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity)
Gets the symbol number for the version and error correction capacity.
Definition MicroQRCodeEncoder.h:486
static unsigned int totalNumberDataCodewordBits(const unsigned int version, const MicroQRCode::ErrorCorrectionCapacity errorCorrectionCapacity)
Return the number of codeword bits for a specified version and error correction level.
Definition MicroQRCodeEncoder.h:454
static unsigned int getBitsInCharacterCountIndicator(const unsigned int version, const MicroQRCode::EncodingMode mode)
Returns the number of bits per character for a specific version and encodation mode,...
Definition MicroQRCodeEncoder.h:291
static unsigned int totalNumberRawDataModules(const unsigned int version)
Returns the number of modules that can be used to store data for a given Micro QR code version This i...
Definition MicroQRCodeEncoder.h:433
static unsigned int encodationModeIndicatorBitSequence(const MicroQRCode::EncodingMode mode)
Returns the bit sequence identifying the encodation mode set (up to 4 bits long, cf.
Definition MicroQRCodeEncoder.h:274
Definition of a Micro QR code.
Definition MicroQRCode.h:35
static constexpr unsigned int MIN_VERSION
Indicates the smallest valid version number of Micro QR codes.
Definition MicroQRCode.h:42
unsigned int modulesPerSide() const override
Returns the number of modules per side of the Micro QR code.
Definition MicroQRCode.h:176
static constexpr unsigned int MAX_VERSION
Indicates the largest valid version number of Micro QR codes.
Definition MicroQRCode.h:45
EncodingMode
Definition of encoding modes.
Definition QRCodeBase.h:72
@ EM_ALPHANUMERIC
Mode that supports A-Z, 0-9 and a few others, cf. ALPHANUMERIC_CHARSET
Definition QRCodeBase.h:76
@ EM_NUMERIC
Mode that supports digits 0-9.
Definition QRCodeBase.h:74
@ EM_BYTE
Mode that represents data as a sequence of bytes.
Definition QRCodeBase.h:78
@ EM_KANJI
Mode that handles Kanji characters in accordance with the Shift JIS system based on JIS X 0208.
Definition QRCodeBase.h:83
ErrorCorrectionCapacity
Enumeration of the levels of error correction The value of the enums correspond to the standard-defin...
Definition QRCodeBase.h:53
@ ECC_15
Indicates that 15% of the modules reserved error correction.
Definition QRCodeBase.h:57
@ ECC_30
Indicates that 30% of the modules reserved error correction.
Definition QRCodeBase.h:61
@ ECC_25
Indicates that 25% of the modules reserved error correction.
Definition QRCodeBase.h:59
@ ECC_INVALID
Indicator for an invalid error correction capacity.
Definition QRCodeBase.h:65
@ ECC_07
Indicates that 7% of the modules reserved error correction.
Definition QRCodeBase.h:55
@ ECC_DETECTION_ONLY
Indicates that the capacity is limited to error detection only (used only by Micro QR Code version M1...
Definition QRCodeBase.h:63
Definition of the segment class A sequence is a sequence of data encoded according to the rules of on...
Definition QRCodeEncoderBase.h:79
This class implements basic QRCodeEncoder functionality.
Definition QRCodeEncoderBase.h:35
static uint32_t computeHammingWeight(uint32_t value)
Determines the number of 1-bits in an integer value (Hamming weight)
Definition QRCodeEncoderBase.h:367
std::vector< Segment > Segments
Typedef for a vector of segments.
Definition QRCodeEncoderBase.h:51
StatusCode
Enum for the error codes returned by the encoding functions.
Definition QRCodeEncoderBase.h:57
std::vector< Codeword > Codewords
Vector of codewords.
Definition QRCodeEncoderBase.h:42
This class provides basic numeric functionalities.
Definition Numeric.h:57
std::vector< QRCode > QRCodes
Definition of a vector of QR codes.
Definition QRCode.h:28
The namespace covering the entire Ocean framework.
Definition Accessor.h:15