Ocean
QRCodeBase.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 
12 #include <algorithm>
13 #include <cstdint>
14 
15 namespace Ocean
16 {
17 
18 namespace CV
19 {
20 
21 namespace Detector
22 {
23 
24 namespace QRCodes
25 {
26 
27 /**
28  * Base class for QR code implementations
29  * @ingroup cvdetectorqrcodes
30  */
32 {
33  public:
34 
35  /**
36  * Definition of available types of codes
37  */
38  enum CodeType : unsigned int
39  {
40  /// Default value of undefined or invalid code types
42  /// Indicates a standard QR codes
44  /// Indicates a Micro QR codes
46  };
47 
48  /**
49  * Enumeration of the levels of error correction
50  * The value of the enums correspond to the standard-defined bit sequences (2 bits long)
51  */
52  enum ErrorCorrectionCapacity : uint32_t
53  {
54  /// Indicates that 7% of the modules reserved error correction
55  ECC_07 = 0b01u,
56  /// Indicates that 15% of the modules reserved error correction
57  ECC_15 = 0b00u,
58  /// Indicates that 25% of the modules reserved error correction
59  ECC_25 = 0b11u,
60  /// Indicates that 30% of the modules reserved error correction
61  ECC_30 = 0b10u,
62  /// Indicates that the capacity is limited to error detection only (used only by Micro QR Code version M1)
64  /// Indicator for an invalid error correction capacity
65  ECC_INVALID = uint32_t(-1),
66  };
67 
68  /**
69  * Definition of encoding modes
70  */
71  enum EncodingMode : uint32_t
72  {
73  /// Mode that supports digits 0-9
74  EM_NUMERIC = 0u,
75  /// Mode that supports A-Z, 0-9 and a few others, cf. `ALPHANUMERIC_CHARSET`
77  /// Mode that represents data as a sequence of bytes
79 
80  // Modes below this line are currently not supported
81 
82  /// Mode that handles Kanji characters in accordance with the Shift JIS system based on JIS X 0208
84  /// Mode that allows the output data stream to have interpretations different from that of the default character set.
86  /// Structured Append mode is used to split the encodation of the data from a message over a number of QR Code symbols.
88  /// Mode that is used for messages containing data formatted either in accordance with the UCC/EAN Application Identifiers standard
90 
91  /// Indicator for an invalid encoding mode
92  EM_INVALID_ENCODING_MODE = uint32_t(-1),
93  };
94 
95  public:
96 
97  /**
98  * Destructs a QR code instance
99  */
100  virtual ~QRCodeBase() = default;
101 
102  /**
103  * Returns whether this is a valid QR code instance
104  * @return True if this is a valid QR code instance, otherwise false
105  */
106  virtual inline bool isValid() const = 0;
107 
108  /**
109  * Returns the type or variant of this code.
110  * @returns The code type
111  */
112  inline CodeType codeType() const;
113 
114  /**
115  * Returns a constant reference to the plain data of the QR code
116  * @return The constant reference
117  * @sa dataAlphanumeric()
118  */
119  inline const std::vector<uint8_t>& data() const;
120 
121  /**
122  * Return the plain data of the QR code as a string, if possible
123  * @return The data as string if the encoding mode is `EM_NUMERIC` or `EM_ALPHANUMERIC`, otherwise an empty string is returned
124  * @sa data()
125  */
126  inline std::string dataString() const;
127 
128  /**
129  * Returns the modules of this QR code
130  * The modules are stored in a vector and will have `modulesPerSide() * modulesPerSide()` elements (row-wise order)
131  * @return The vector modules
132  */
133  inline const std::vector<uint8_t>& modules() const;
134 
135  /**
136  * Returns the encoding mode of the QR code
137  * @return The encoding mode
138  */
139  inline EncodingMode encodingMode() const;
140 
141  /**
142  * Returns the error correction capacity of the QR code
143  * @return The error correction capacity
144  */
146 
147  /**
148  * Returns the version of the QR code
149  * @return The version number
150  */
151  inline unsigned int version() const;
152 
153  /**
154  * Returns the version of the QR code as a string
155  * @return The version string
156  */
157  virtual inline std::string versionString() const;
158 
159  /**
160  * Returns the number of modules per side of the QR code
161  * @return The number of modules per side
162  */
163  virtual inline unsigned int modulesPerSide() const = 0;
164 
165  /**
166  * Checks if another code is identical to this one.
167  * @param otherCode The code that will be compared against for identity, must be valid.
168  * @param ignoreModules True, identical modules in both codes will not be required, otherwise they will.
169  * @return True if both codes are identical, otherwise false.
170  */
171  inline bool isSame(const QRCodeBase& otherCode, const bool ignoreModules) const;
172 
173  /**
174  * Checks for equality with another QR code
175  * Two QR codes are equal iff they store identical data, use the same configuration, and have identical modules
176  * @returns True if both QR codes are equal, otherwise false
177  */
178  inline bool operator==(const QRCodeBase& otherCode) const;
179 
180  /**
181  * Checks for inequality with another QR code
182  * @returns True if both QR codes are not equal, otherwise false
183  */
184  inline bool operator!=(const QRCodeBase& otherCode) const;
185 
186  /**
187  * Translates an encoding mode enum into a human-readable string
188  * @param encodingMode The encoding mode that will be converted into a string
189  * @return The translated encoding mode
190  */
191  static inline std::string translateEncodingMode(const EncodingMode encodingMode);
192 
193  /**
194  * Translates an error correction capacity enum into a human-readable string
195  * @param errorCorrectionCapacity The error correction capacity that will be converted into a string
196  * @return The translated error correction capacity
197  */
199 
200  /**
201  * Returns the integer value of an error correction capacity
202  * @param errorCorrectionCapacity The error correction capacity that will be converted into an integer
203  * @return The value of the error correction capacity
204  */
206 
207  /**
208  * Translate the code type into a human-readable string
209  * @param codeType The code type that will be translated into a human-readable string
210  * @return The human-readable string
211  */
212  static inline std::string translateCodeType(const CodeType codeType);
213 
214  protected:
215 
216  /**
217  * Creates an invalid QR code instance
218  */
219  QRCodeBase() = default;
220 
221  /**
222  * Creates an QR code instance
223  * @param codeType The type or variant of this codes, must not be `CT_UNDEFINED`.
224  * @param data The plain data of this QR code, must be valid
225  * @param encodingMode The encoding mode that was used to encode the data, must not be `EM_INVALID_ENCODING_MODE`
226  * @param errorCorrectionCapacity The error correction capacity that was used to generate this QR code, must not be `ECC_INVALID`
227  * @param modules The modules of the QR code that store the data, must be valid
228  * @param version The version of the QR code, range: [1, 40]
229  * @sa QRCodeEncoder, QRCodeDecoder
230  */
231  inline explicit QRCodeBase(const CodeType codeType, std::vector<uint8_t>&& data, const EncodingMode encodingMode, const ErrorCorrectionCapacity errorCorrectionCapacity, std::vector<uint8_t>&& modules, const unsigned int version);
232 
233  /**
234  * Copy constructor
235  */
236  inline QRCodeBase(const QRCodeBase& otherCode) = default;
237 
238  /**
239  * Copy assignment operator
240  */
241  inline QRCodeBase& operator=(const QRCodeBase& otherCode) = default;
242 
243  protected:
244 
245  /// The variant of this QR code
247 
248  /// The plain data
249  std::vector<uint8_t> data_;
250 
251  /// The encoding mode that was used to generate this QR code
253 
254  /// The error correction capacity that was used to generated this QR code
256 
257  /// The modules of the QR code that store the data
258  std::vector<uint8_t> modules_;
259 
260  /// The version of the QR code
261  unsigned int version_ = 0u;
262 };
263 
264 inline QRCodeBase::QRCodeBase(const CodeType codeType, std::vector<uint8_t>&& data, const EncodingMode encodingMode, const ErrorCorrectionCapacity errorCorrectionCapacity, std::vector<uint8_t>&& modules, const unsigned int version) :
265  codeType_(codeType),
266  data_(std::move(data)),
267  encodingMode_(encodingMode),
268  errorCorrectionCapacity_(errorCorrectionCapacity),
269  modules_(std::move(modules)),
270  version_(version)
271 {
272  ocean_assert(codeType_ != CT_UNDEFINED);
273 }
274 
276 {
277  return codeType_;
278 }
279 
280 inline const std::vector<uint8_t>& QRCodeBase::data() const
281 {
282  return data_;
283 }
284 
285 inline std::string QRCodeBase::dataString() const
286 {
287  return std::string(data_.begin(), data_.end());
288 }
289 
290 inline const std::vector<uint8_t>& QRCodeBase::modules() const
291 {
292  return modules_;
293 }
294 
296 {
297  return encodingMode_;
298 }
299 
301 {
303 }
304 
305 inline unsigned int QRCodeBase::version() const
306 {
307  return version_;
308 }
309 
310 inline std::string QRCodeBase::versionString() const
311 {
312  return std::to_string(version_);
313 }
314 
315 inline bool QRCodeBase::isSame(const QRCodeBase& otherCode, const bool ignoreModules) const
316 {
317  if (isValid() != otherCode.isValid())
318  {
319  return false;
320  }
321 
322  if (codeType() != otherCode.codeType())
323  {
324  return false;
325  }
326 
327  if (version() != otherCode.version())
328  {
329  return false;
330  }
331 
332  if (encodingMode() != otherCode.encodingMode())
333  {
334  return false;
335  }
336 
338  {
339  return false;
340  }
341 
342  if (modulesPerSide() != otherCode.modulesPerSide())
343  {
344  return false;
345  }
346 
347  if (data_.size() != otherCode.data().size())
348  {
349  return false;
350  }
351  else if (!std::equal(data_.begin(), data_.end(), otherCode.data().begin()))
352  {
353  return false;
354  }
355 
356  if (!ignoreModules)
357  {
358  if (modules_.size() != otherCode.modules().size())
359  {
360  return false;
361  }
362  else if (!std::equal(modules_.begin(), modules_.end(), otherCode.modules().begin()))
363  {
364  return false;
365  }
366  }
367 
368  return true;
369 }
370 
371 inline bool QRCodeBase::operator==(const QRCodeBase& otherCode) const
372 {
373  return isSame(otherCode, /* ignoreModules */ false);
374 }
375 
376 inline bool QRCodeBase::operator!=(const QRCodeBase& otherCode) const
377 {
378  return !(*this == otherCode);
379 }
380 
381 inline std::string QRCodeBase::translateEncodingMode(const QRCodeBase::EncodingMode encodingMode)
382 {
383  switch (encodingMode)
384  {
385  case EM_NUMERIC:
386  return "NUMERIC";
387 
388  case EM_ALPHANUMERIC:
389  return "ALPHANUMERIC";
390 
391  case EM_BYTE:
392  return "BYTE";
393 
394  case EM_KANJI:
395  return "KANJI";
396 
397  case EM_ECI:
398  return "ECI";
399 
401  return "STRUCTURED_APPEND";
402 
403  case EM_FNC1:
404  return "FNC1";
405 
407  return "INVALID";
408  }
409 
410  ocean_assert(false && "Never be here!");
411  return "Unknown encoding mode";
412 }
413 
415 {
416  switch (errorCorrectionCapacity)
417  {
418  case ECC_07:
419  return "07";
420 
421  case ECC_15:
422  return "15";
423 
424  case ECC_25:
425  return "25";
426 
427  case ECC_30:
428  return "30";
429 
430  case ECC_DETECTION_ONLY:
431  return "DETECTION_ONLY";
432 
433  case ECC_INVALID:
434  return "INVALID";
435  }
436 
437  ocean_assert(false && "Never be here!");
438  return "Unknown error correction capacity";
439 }
440 
441 inline unsigned int QRCodeBase::getErrorCorrectionCapacityValue(const ErrorCorrectionCapacity errorCorrectionCapacity)
442 {
443  switch (errorCorrectionCapacity)
444  {
445  case ECC_07:
446  return 7u;
447 
448  case ECC_15:
449  return 15u;
450 
451  case ECC_25:
452  return 25u;
453 
454  case ECC_30:
455  return 30u;
456 
457  case ECC_DETECTION_ONLY:
458  return 0u;
459 
460  case ECC_INVALID:
461  // Handled below
462  break;
463  }
464 
465  ocean_assert(false && "Never be here!");
466  return 0u;
467 }
468 
469 inline std::string QRCodeBase::translateCodeType(const CodeType codeType)
470 {
471  switch (codeType)
472  {
473  case CT_UNDEFINED:
474  return "UNDEFINED";
475 
476  case CT_STANDARD:
477  return "STANDARD";
478 
479  case CT_MICRO:
480  return "MICRO";
481  }
482 
483  ocean_assert(false && "Never be here!");
484  return "";
485 }
486 
487 } // namespace QRCodes
488 
489 } // namespace Detector
490 
491 } // namespace CV
492 
493 } // namespace Ocean
Base class for QR code implementations.
Definition: QRCodeBase.h:32
static unsigned int getErrorCorrectionCapacityValue(const ErrorCorrectionCapacity errorCorrectionCapacity)
Returns the integer value of an error correction capacity.
Definition: QRCodeBase.h:441
bool operator!=(const QRCodeBase &otherCode) const
Checks for inequality with another QR code.
Definition: QRCodeBase.h:376
QRCodeBase & operator=(const QRCodeBase &otherCode)=default
Copy assignment operator.
QRCodeBase(const QRCodeBase &otherCode)=default
Copy constructor.
QRCodeBase()=default
Creates an invalid QR code instance.
CodeType codeType_
The variant of this QR code.
Definition: QRCodeBase.h:246
std::vector< uint8_t > data_
The plain data.
Definition: QRCodeBase.h:249
ErrorCorrectionCapacity errorCorrectionCapacity_
The error correction capacity that was used to generated this QR code.
Definition: QRCodeBase.h:255
virtual unsigned int modulesPerSide() const =0
Returns the number of modules per side of the QR code.
const std::vector< uint8_t > & modules() const
Returns the modules of this QR code The modules are stored in a vector and will have modulesPerSide()...
Definition: QRCodeBase.h:290
std::vector< uint8_t > modules_
The modules of the QR code that store the data.
Definition: QRCodeBase.h:258
bool operator==(const QRCodeBase &otherCode) const
Checks for equality with another QR code Two QR codes are equal iff they store identical data,...
Definition: QRCodeBase.h:371
CodeType codeType() const
Returns the type or variant of this code.
Definition: QRCodeBase.h:275
static std::string translateEncodingMode(const EncodingMode encodingMode)
Translates an encoding mode enum into a human-readable string.
Definition: QRCodeBase.h:381
virtual ~QRCodeBase()=default
Destructs a QR code instance.
CodeType
Definition of available types of codes.
Definition: QRCodeBase.h:39
@ CT_MICRO
Indicates a Micro QR codes.
Definition: QRCodeBase.h:45
@ CT_STANDARD
Indicates a standard QR codes.
Definition: QRCodeBase.h:43
@ CT_UNDEFINED
Default value of undefined or invalid code types.
Definition: QRCodeBase.h:41
static std::string translateErrorCorrectionCapacity(const ErrorCorrectionCapacity errorCorrectionCapacity)
Translates an error correction capacity enum into a human-readable string.
Definition: QRCodeBase.h:414
virtual std::string versionString() const
Returns the version of the QR code as a string.
Definition: QRCodeBase.h:310
unsigned int version() const
Returns the version of the QR code.
Definition: QRCodeBase.h:305
unsigned int version_
The version of the QR code.
Definition: QRCodeBase.h:261
const std::vector< uint8_t > & data() const
Returns a constant reference to the plain data of the QR code.
Definition: QRCodeBase.h:280
std::string dataString() const
Return the plain data of the QR code as a string, if possible.
Definition: QRCodeBase.h:285
bool isSame(const QRCodeBase &otherCode, const bool ignoreModules) const
Checks if another code is identical to this one.
Definition: QRCodeBase.h:315
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_ECI
Mode that allows the output data stream to have interpretations different from that of the default ch...
Definition: QRCodeBase.h:85
@ EM_BYTE
Mode that represents data as a sequence of bytes.
Definition: QRCodeBase.h:78
@ EM_INVALID_ENCODING_MODE
Indicator for an invalid encoding mode.
Definition: QRCodeBase.h:92
@ EM_KANJI
Mode that handles Kanji characters in accordance with the Shift JIS system based on JIS X 0208.
Definition: QRCodeBase.h:83
@ EM_STRUCTURED_APPEND
Structured Append mode is used to split the encodation of the data from a message over a number of QR...
Definition: QRCodeBase.h:87
@ EM_FNC1
Mode that is used for messages containing data formatted either in accordance with the UCC/EAN Applic...
Definition: QRCodeBase.h:89
static std::string translateCodeType(const CodeType codeType)
Translate the code type into a human-readable string.
Definition: QRCodeBase.h:469
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
virtual bool isValid() const =0
Returns whether this is a valid QR code instance.
ErrorCorrectionCapacity errorCorrectionCapacity() const
Returns the error correction capacity of the QR code.
Definition: QRCodeBase.h:300
EncodingMode encodingMode_
The encoding mode that was used to generate this QR code.
Definition: QRCodeBase.h:252
EncodingMode encodingMode() const
Returns the encoding mode of the QR code.
Definition: QRCodeBase.h:295
std::vector< QRCode > QRCodes
Definition of a vector of QR codes.
Definition: QRCode.h:25
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15