zxing-cpp: strip to core library only (remove tests/wrappers/examples/docs); .gitignore: fix /core to allow zxing-cpp/core/ dir
This commit is contained in:
1 parent
22c24d135e
commit
8051dfe4e5
2506 files changed
+57271
-30087
No files matched your search
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2016 Nu-book Inc.
|
||||
* Copyright 2016 ZXing authors
|
||||
*/
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "MCBitMatrixParser.h"
|
||||
|
||||
#include "BitMatrix.h"
|
||||
#include "ByteArray.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace ZXing::MaxiCode {
|
||||
|
||||
static const std::array<std::array<int, BitMatrixParser::MATRIX_WIDTH>, BitMatrixParser::MATRIX_HEIGHT> BITNR = {
|
||||
121,120,127,126,133,132,139,138,145,144,151,150,157,156,163,162,169,168,175,174,181,180,187,186,193,192,199,198, -2, -2,
|
||||
123,122,129,128,135,134,141,140,147,146,153,152,159,158,165,164,171,170,177,176,183,182,189,188,195,194,201,200,816, -3,
|
||||
125,124,131,130,137,136,143,142,149,148,155,154,161,160,167,166,173,172,179,178,185,184,191,190,197,196,203,202,818,817,
|
||||
283,282,277,276,271,270,265,264,259,258,253,252,247,246,241,240,235,234,229,228,223,222,217,216,211,210,205,204,819, -3,
|
||||
285,284,279,278,273,272,267,266,261,260,255,254,249,248,243,242,237,236,231,230,225,224,219,218,213,212,207,206,821,820,
|
||||
287,286,281,280,275,274,269,268,263,262,257,256,251,250,245,244,239,238,233,232,227,226,221,220,215,214,209,208,822, -3,
|
||||
289,288,295,294,301,300,307,306,313,312,319,318,325,324,331,330,337,336,343,342,349,348,355,354,361,360,367,366,824,823,
|
||||
291,290,297,296,303,302,309,308,315,314,321,320,327,326,333,332,339,338,345,344,351,350,357,356,363,362,369,368,825, -3,
|
||||
293,292,299,298,305,304,311,310,317,316,323,322,329,328,335,334,341,340,347,346,353,352,359,358,365,364,371,370,827,826,
|
||||
409,408,403,402,397,396,391,390, 79, 78, -2, -2, 13, 12, 37, 36, 2, -1, 44, 43,109,108,385,384,379,378,373,372,828, -3,
|
||||
411,410,405,404,399,398,393,392, 81, 80, 40, -2, 15, 14, 39, 38, 3, -1, -1, 45,111,110,387,386,381,380,375,374,830,829,
|
||||
413,412,407,406,401,400,395,394, 83, 82, 41, -3, -3, -3, -3, -3, 5, 4, 47, 46,113,112,389,388,383,382,377,376,831, -3,
|
||||
415,414,421,420,427,426,103,102, 55, 54, 16, -3, -3, -3, -3, -3, -3, -3, 20, 19, 85, 84,433,432,439,438,445,444,833,832,
|
||||
417,416,423,422,429,428,105,104, 57, 56, -3, -3, -3, -3, -3, -3, -3, -3, 22, 21, 87, 86,435,434,441,440,447,446,834, -3,
|
||||
419,418,425,424,431,430,107,106, 59, 58, -3, -3, -3, -3, -3, -3, -3, -3, -3, 23, 89, 88,437,436,443,442,449,448,836,835,
|
||||
481,480,475,474,469,468, 48, -2, 30, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 0, 53, 52,463,462,457,456,451,450,837, -3,
|
||||
483,482,477,476,471,470, 49, -1, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -2, -1,465,464,459,458,453,452,839,838,
|
||||
485,484,479,478,473,472, 51, 50, 31, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 1, -2, 42,467,466,461,460,455,454,840, -3,
|
||||
487,486,493,492,499,498, 97, 96, 61, 60, -3, -3, -3, -3, -3, -3, -3, -3, -3, 26, 91, 90,505,504,511,510,517,516,842,841,
|
||||
489,488,495,494,501,500, 99, 98, 63, 62, -3, -3, -3, -3, -3, -3, -3, -3, 28, 27, 93, 92,507,506,513,512,519,518,843, -3,
|
||||
491,490,497,496,503,502,101,100, 65, 64, 17, -3, -3, -3, -3, -3, -3, -3, 18, 29, 95, 94,509,508,515,514,521,520,845,844,
|
||||
559,558,553,552,547,546,541,540, 73, 72, 32, -3, -3, -3, -3, -3, -3, 10, 67, 66,115,114,535,534,529,528,523,522,846, -3,
|
||||
561,560,555,554,549,548,543,542, 75, 74, -2, -1, 7, 6, 35, 34, 11, -2, 69, 68,117,116,537,536,531,530,525,524,848,847,
|
||||
563,562,557,556,551,550,545,544, 77, 76, -2, 33, 9, 8, 25, 24, -1, -2, 71, 70,119,118,539,538,533,532,527,526,849, -3,
|
||||
565,564,571,570,577,576,583,582,589,588,595,594,601,600,607,606,613,612,619,618,625,624,631,630,637,636,643,642,851,850,
|
||||
567,566,573,572,579,578,585,584,591,590,597,596,603,602,609,608,615,614,621,620,627,626,633,632,639,638,645,644,852, -3,
|
||||
569,568,575,574,581,580,587,586,593,592,599,598,605,604,611,610,617,616,623,622,629,628,635,634,641,640,647,646,854,853,
|
||||
727,726,721,720,715,714,709,708,703,702,697,696,691,690,685,684,679,678,673,672,667,666,661,660,655,654,649,648,855, -3,
|
||||
729,728,723,722,717,716,711,710,705,704,699,698,693,692,687,686,681,680,675,674,669,668,663,662,657,656,651,650,857,856,
|
||||
731,730,725,724,719,718,713,712,707,706,701,700,695,694,689,688,683,682,677,676,671,670,665,664,659,658,653,652,858, -3,
|
||||
733,732,739,738,745,744,751,750,757,756,763,762,769,768,775,774,781,780,787,786,793,792,799,798,805,804,811,810,860,859,
|
||||
735,734,741,740,747,746,753,752,759,758,765,764,771,770,777,776,783,782,789,788,795,794,801,800,807,806,813,812,861, -3,
|
||||
737,736,743,742,749,748,755,754,761,760,767,766,773,772,779,778,785,784,791,790,797,796,803,802,809,808,815,814,863,862,
|
||||
};
|
||||
|
||||
ByteArray BitMatrixParser::ReadCodewords(const BitMatrix& image)
|
||||
{
|
||||
ByteArray result(144);
|
||||
int height = image.height();
|
||||
int width = image.width();
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int bit = BITNR[y][x];
|
||||
if (bit >= 0 && image.get(x, y)) {
|
||||
result[bit / 6] |= static_cast<uint8_t>(1 << (5 - (bit % 6)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace ZXing::MaxiCode
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2016 Nu-book Inc.
|
||||
* Copyright 2016 ZXing authors
|
||||
*/
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ZXing {
|
||||
|
||||
class ByteArray;
|
||||
class BitMatrix;
|
||||
|
||||
namespace MaxiCode {
|
||||
|
||||
/**
|
||||
* @author mike32767
|
||||
* @author Manuel Kasten
|
||||
*/
|
||||
class BitMatrixParser
|
||||
{
|
||||
public:
|
||||
static ByteArray ReadCodewords(const BitMatrix& image);
|
||||
|
||||
static const int MATRIX_WIDTH = 30;
|
||||
static const int MATRIX_HEIGHT = 33;
|
||||
};
|
||||
|
||||
} // MaxiCode
|
||||
} // ZXing
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright 2016 Nu-book Inc.
|
||||
* Copyright 2016 ZXing authors
|
||||
*/
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "MCDecoder.h"
|
||||
|
||||
#include "ByteArray.h"
|
||||
#include "CharacterSet.h"
|
||||
#include "DecoderResult.h"
|
||||
#include "MCBitMatrixParser.h"
|
||||
#include "ReedSolomon.h"
|
||||
#include "ZXTestSupport.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace ZXing::MaxiCode {
|
||||
|
||||
static const int ALL = 0;
|
||||
static const int EVEN = 1;
|
||||
static const int ODD = 2;
|
||||
|
||||
static bool CorrectErrors(ByteArray& codewordBytes, int start, int dataCodewords, int ecCodewords, int mode)
|
||||
{
|
||||
int codewords = dataCodewords + ecCodewords;
|
||||
|
||||
// in EVEN or ODD mode only half the codewords
|
||||
int divisor = mode == ALL ? 1 : 2;
|
||||
|
||||
// First read into an array of ints
|
||||
std::vector<int> codewordsInts(codewords / divisor, 0);
|
||||
for (int i = 0; i < codewords; i++) {
|
||||
if ((mode == ALL) || (i % 2 == (mode - 1)))
|
||||
codewordsInts[i / divisor] = codewordBytes[i + start];
|
||||
}
|
||||
|
||||
if (!ReedSolomonDecode(RSField::MaxiCode, codewordsInts, ecCodewords / divisor))
|
||||
return false;
|
||||
|
||||
// Copy back into array of bytes -- only need to worry about the bytes that were data
|
||||
// We don't care about errors in the error-correction codewords
|
||||
for (int i = 0; i < dataCodewords; i++) {
|
||||
if ((mode == ALL) || (i % 2 == (mode - 1)))
|
||||
codewordBytes[i + start] = narrow_cast<uint8_t>(codewordsInts[i / divisor]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>MaxiCodes can encode text or structured information as bits in one of several modes,
|
||||
* with multiple character sets in one code. This class decodes the bits back into text.</p>
|
||||
*
|
||||
* @author mike32767
|
||||
* @author Manuel Kasten
|
||||
*/
|
||||
namespace DecodedBitStreamParser {
|
||||
|
||||
static const short SHI0 = 0x100;
|
||||
static const short SHI1 = 0x101;
|
||||
static const short SHI2 = 0x102;
|
||||
static const short SHI3 = 0x103;
|
||||
static const short SHI4 = 0x104;
|
||||
static const short TWSA = 0x105; // two shift A
|
||||
static const short TRSA = 0x106; // three shift A
|
||||
static const short LCHA = 0x107; // latch A
|
||||
static const short LCHB = 0x108; // latch B
|
||||
static const short LOCK = 0x109;
|
||||
static const short ECI = 0x10A;
|
||||
static const short NS = 0x10B;
|
||||
static const short PAD = 0x10C;
|
||||
|
||||
static const char FS = 0x1C;
|
||||
static const char GS = 0x1D;
|
||||
static const char RS = 0x1E;
|
||||
|
||||
// clang-format off
|
||||
const static std::array<short, 0x40> CHARSETS[] = {
|
||||
{ // set 0 (A)
|
||||
'\r', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ECI, FS, GS, RS, NS,
|
||||
' ', PAD, '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', SHI1, SHI2, SHI3, SHI4, LCHB,
|
||||
},
|
||||
{ // set 1 (B)
|
||||
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ECI, FS, GS, RS, NS,
|
||||
'{', PAD, '}', '~', 0x7F, ';', '<', '=', '>', '?', '[', '\\', ']', '^', '_', ' ',
|
||||
',', '.', '/', ':', '@', '!', '|', PAD, TWSA, TRSA, PAD, SHI0, SHI2, SHI3, SHI4, LCHA,
|
||||
},
|
||||
{ // set 2 (C)
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, ECI, FS, GS, RS, NS, // Note that in original code in Java, NS is not there, which seems to be a bug
|
||||
0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xAA, 0xAC, 0xB1, 0xB2, 0xB3, 0xB5, 0xB9, 0xBA, 0xBC, 0xBD, 0xBE,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, LCHA, 0x20, LOCK, SHI3, SHI4, LCHB,
|
||||
},
|
||||
{ // set 3 (D)
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, ECI, FS, GS, RS, NS,
|
||||
0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xA1, 0xA8, 0xAB, 0xAF, 0xB0, 0xB4, 0xB7, 0xB8, 0xBB, 0xBF, 0x8A,
|
||||
0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, LCHA, 0x20, SHI2, LOCK, SHI4, LCHB,
|
||||
},
|
||||
{ // set 4 (E)
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, ECI, PAD, PAD, 0x1B, NS,
|
||||
FS, GS, RS, 0x1F, 0x9F, 0xA0, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA9, 0xAD, 0xAE, 0xB6,
|
||||
0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, LCHA, 0x20, SHI2, SHI3, LOCK, LCHB,
|
||||
},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static int GetBit(int bit, const ByteArray& bytes)
|
||||
{
|
||||
bit--;
|
||||
return (bytes[bit / 6] & (1 << (5 - (bit % 6)))) == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
static unsigned int GetInt(const ByteArray& bytes, const ByteArray& x)
|
||||
{
|
||||
int len = Size(x);
|
||||
unsigned int val = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
val += GetBit(x[i], bytes) << (len - i - 1);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static unsigned int GetPostCode2Length(const ByteArray& bytes)
|
||||
{
|
||||
return std::min(GetInt(bytes, {39, 40, 41, 42, 31, 32}), 9U);
|
||||
}
|
||||
|
||||
static std::string GetPostCode2(const ByteArray& bytes)
|
||||
{
|
||||
unsigned int val = GetInt(bytes,
|
||||
{33, 34, 35, 36, 25, 26, 27, 28, 29, 30, 19, 20, 21, 22, 23, 24, 13, 14, 15, 16, 17, 18, 7, 8, 9, 10, 11, 12, 1, 2});
|
||||
unsigned int len = GetPostCode2Length(bytes);
|
||||
// Pad or truncate to length
|
||||
char buf[11]; // 30 bits 0x3FFFFFFF == 1073741823 (10 digits)
|
||||
snprintf(buf, sizeof(buf), "%0*d", len, val);
|
||||
buf[len] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
static std::string GetPostCode3(const ByteArray& bytes)
|
||||
{
|
||||
return {
|
||||
(char) CHARSETS[0].at(GetInt(bytes, { 39, 40, 41, 42, 31, 32 })),
|
||||
(char) CHARSETS[0].at(GetInt(bytes, { 33, 34, 35, 36, 25, 26 })),
|
||||
(char) CHARSETS[0].at(GetInt(bytes, { 27, 28, 29, 30, 19, 20 })),
|
||||
(char) CHARSETS[0].at(GetInt(bytes, { 21, 22, 23, 24, 13, 14 })),
|
||||
(char) CHARSETS[0].at(GetInt(bytes, { 15, 16, 17, 18, 7, 8 })),
|
||||
(char) CHARSETS[0].at(GetInt(bytes, { 9, 10, 11, 12, 1, 2 })),
|
||||
};
|
||||
}
|
||||
|
||||
static unsigned int GetCountry(const ByteArray& bytes)
|
||||
{
|
||||
return std::min(GetInt(bytes, {53, 54, 43, 44, 45, 46, 47, 48, 37, 38}), 999U);
|
||||
}
|
||||
|
||||
static unsigned int GetServiceClass(const ByteArray& bytes)
|
||||
{
|
||||
return std::min(GetInt(bytes, {55, 56, 57, 58, 59, 60, 49, 50, 51, 52}), 999U);
|
||||
}
|
||||
|
||||
/**
|
||||
* See ISO/IEC 16023:2000 Section 4.6 Table 3
|
||||
*/
|
||||
static ZXing::ECI ParseECIValue(const ByteArray& bytes, int& i)
|
||||
{
|
||||
int firstByte = bytes[++i];
|
||||
if ((firstByte & 0x20) == 0)
|
||||
return ZXing::ECI(firstByte);
|
||||
|
||||
int secondByte = bytes[++i];
|
||||
if ((firstByte & 0x10) == 0)
|
||||
return ZXing::ECI(((firstByte & 0x0F) << 6) | secondByte);
|
||||
|
||||
int thirdByte = bytes[++i];
|
||||
if ((firstByte & 0x08) == 0)
|
||||
return ZXing::ECI(((firstByte & 0x07) << 12) | (secondByte << 6) | thirdByte);
|
||||
|
||||
int fourthByte = bytes[++i];
|
||||
return ZXing::ECI(((firstByte & 0x03) << 18) | (secondByte << 12) | (thirdByte << 6) | fourthByte);
|
||||
}
|
||||
|
||||
/**
|
||||
* See ISO/IEC 16023:2000 Section 4.9.1 Table 5
|
||||
*/
|
||||
static void ParseStructuredAppend(const ByteArray& bytes, int& i, StructuredAppendInfo& sai)
|
||||
{
|
||||
int byte = bytes[++i];
|
||||
sai.index = (byte >> 3) & 0x07;
|
||||
sai.count = (byte & 0x07) + 1;
|
||||
if (sai.count == 1 || sai.count <= sai.index) // If info doesn't make sense
|
||||
sai.count = 0; // Choose to mark count as unknown
|
||||
// No id
|
||||
}
|
||||
|
||||
static void GetMessage(const ByteArray& bytes, int start, int len, Content& result, StructuredAppendInfo& sai)
|
||||
{
|
||||
int shift = -1;
|
||||
int set = 0;
|
||||
int lastset = 0;
|
||||
|
||||
for (int i = start; i < start + len; i++) {
|
||||
int c = CHARSETS[set].at(bytes[i]);
|
||||
switch (c) {
|
||||
case LCHA:
|
||||
set = 0;
|
||||
shift = -1;
|
||||
break;
|
||||
case LCHB:
|
||||
set = 1;
|
||||
shift = -1;
|
||||
break;
|
||||
case SHI0:
|
||||
case SHI1:
|
||||
case SHI2:
|
||||
case SHI3:
|
||||
case SHI4:
|
||||
lastset = set;
|
||||
set = c - SHI0;
|
||||
shift = 1;
|
||||
break;
|
||||
case TWSA:
|
||||
lastset = set;
|
||||
set = 0;
|
||||
shift = 2;
|
||||
break;
|
||||
case TRSA:
|
||||
lastset = set;
|
||||
set = 0;
|
||||
shift = 3;
|
||||
break;
|
||||
case NS:
|
||||
result.append(
|
||||
ToString((bytes[i + 1] << 24) + (bytes[i + 2] << 18) + (bytes[i + 3] << 12) + (bytes[i + 4] << 6) + bytes[i + 5], 9));
|
||||
i += 5;
|
||||
break;
|
||||
case LOCK: shift = -1; break;
|
||||
case ECI: result.switchEncoding(ParseECIValue(bytes, i)); break;
|
||||
case PAD:
|
||||
if (i == start)
|
||||
ParseStructuredAppend(bytes, i, sai);
|
||||
shift = -1;
|
||||
break;
|
||||
default: result.push_back(c);
|
||||
}
|
||||
|
||||
if (shift-- == 0)
|
||||
set = lastset;
|
||||
}
|
||||
}
|
||||
|
||||
ZXING_EXPORT_TEST_ONLY
|
||||
DecoderResult Decode(ByteArray&& bytes, const int mode)
|
||||
{
|
||||
Content result;
|
||||
result.symbology = {'U', (mode == 2 || mode == 3) ? '1' : '0', 2}; // TODO: No identifier defined for mode 6?
|
||||
result.defaultCharset = CharacterSet::ISO8859_1;
|
||||
StructuredAppendInfo sai;
|
||||
|
||||
switch (mode) {
|
||||
case 2:
|
||||
case 3: {
|
||||
auto postcode = mode == 2 ? GetPostCode2(bytes) : GetPostCode3(bytes);
|
||||
auto country = ToString(GetCountry(bytes), 3);
|
||||
auto service = ToString(GetServiceClass(bytes), 3);
|
||||
GetMessage(bytes, 10, 84, result, sai);
|
||||
result.insert(result.bytes.asString().starts_with("[)>\u001E01\u001D") ? 9 : 0, // "[)>" + RS + "01" + GS
|
||||
postcode + GS + country + GS + service + GS);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 6: GetMessage(bytes, 1, 93, result, sai); break;
|
||||
case 5: GetMessage(bytes, 1, 77, result, sai); break;
|
||||
}
|
||||
|
||||
return DecoderResult(std::move(result))
|
||||
.setEcLevel(std::to_string(mode))
|
||||
.setStructuredAppend(sai)
|
||||
.setReaderInit(mode == 6);
|
||||
}
|
||||
|
||||
} // DecodedBitStreamParser
|
||||
|
||||
DecoderResult Decode(const BitMatrix& bits)
|
||||
{
|
||||
ByteArray codewords = BitMatrixParser::ReadCodewords(bits);
|
||||
|
||||
if (!CorrectErrors(codewords, 0, 10, 10, ALL))
|
||||
return ChecksumError();
|
||||
|
||||
int mode = codewords[0] & 0x0F;
|
||||
ByteArray datawords;
|
||||
switch (mode) {
|
||||
case 2: // Structured Carrier Message (numeric postcode)
|
||||
case 3: // Structured Carrier Message (alphanumeric postcode)
|
||||
case 4: // Standard Symbol
|
||||
case 6: // Reader Programming
|
||||
if (CorrectErrors(codewords, 20, 84, 40, EVEN) && CorrectErrors(codewords, 20, 84, 40, ODD))
|
||||
datawords.resize(94, 0);
|
||||
else
|
||||
return ChecksumError();
|
||||
break;
|
||||
case 5: // Full ECC
|
||||
if (CorrectErrors(codewords, 20, 68, 56, EVEN) && CorrectErrors(codewords, 20, 68, 56, ODD))
|
||||
datawords.resize(78, 0);
|
||||
else
|
||||
return ChecksumError();
|
||||
break;
|
||||
default: return FormatError("Invalid mode");
|
||||
}
|
||||
|
||||
std::copy_n(codewords.begin(), 10, datawords.begin());
|
||||
std::copy_n(codewords.begin() + 20, datawords.size() - 10, datawords.begin() + 10);
|
||||
|
||||
return DecodedBitStreamParser::Decode(std::move(datawords), mode);
|
||||
}
|
||||
|
||||
} // namespace ZXing::MaxiCode
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2016 Nu-book Inc.
|
||||
* Copyright 2016 ZXing authors
|
||||
*/
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ZXing {
|
||||
|
||||
class DecoderResult;
|
||||
class BitMatrix;
|
||||
|
||||
namespace MaxiCode {
|
||||
|
||||
DecoderResult Decode(const BitMatrix& bits);
|
||||
|
||||
} // MaxiCode
|
||||
} // ZXing
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2016 Nu-book Inc.
|
||||
* Copyright 2016 ZXing authors
|
||||
*/
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "MCReader.h"
|
||||
|
||||
#include "BinaryBitmap.h"
|
||||
#include "BitMatrix.h"
|
||||
#include "DecoderResult.h"
|
||||
#include "DetectorResult.h"
|
||||
#include "MCBitMatrixParser.h"
|
||||
#include "MCDecoder.h"
|
||||
#include "BarcodeData.h"
|
||||
|
||||
namespace ZXing::MaxiCode {
|
||||
|
||||
/**
|
||||
* This method detects a code in a "pure" image -- that is, pure monochrome image
|
||||
* which contains only an unrotated, unskewed, image of a code, with some white border
|
||||
* around it. This is a specialized method that works exceptionally fast in this special
|
||||
* case.
|
||||
*/
|
||||
static DetectorResult ExtractPureBits(const BitMatrix& image)
|
||||
{
|
||||
int left, top, width, height;
|
||||
if (!image.findBoundingBox(left, top, width, height, BitMatrixParser::MATRIX_WIDTH))
|
||||
return {};
|
||||
|
||||
// Now just read off the bits
|
||||
BitMatrix bits(BitMatrixParser::MATRIX_WIDTH, BitMatrixParser::MATRIX_HEIGHT);
|
||||
for (int y = 0; y < BitMatrixParser::MATRIX_HEIGHT; y++) {
|
||||
int iy = top + (y * height + height / 2) / BitMatrixParser::MATRIX_HEIGHT;
|
||||
for (int x = 0; x < BitMatrixParser::MATRIX_WIDTH; x++) {
|
||||
int ix = left + (x * width + width / 2 + (y & 0x01) * width / 2) / BitMatrixParser::MATRIX_WIDTH;
|
||||
if (image.get(ix, iy)) {
|
||||
bits.set(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {std::move(bits), Rectangle<PointI>(left, top, width, height)};
|
||||
}
|
||||
|
||||
BarcodesData Reader::read(const BinaryBitmap& image, [[maybe_unused]] int maxSymbols) const
|
||||
{
|
||||
auto binImg = image.getBitMatrix();
|
||||
if (binImg == nullptr)
|
||||
return {};
|
||||
|
||||
//TODO: this only works with effectively 'pure' barcodes. Needs proper detector.
|
||||
auto detRes = ExtractPureBits(*binImg);
|
||||
if (!detRes.isValid())
|
||||
return {};
|
||||
|
||||
DecoderResult decRes = Decode(detRes.bits());
|
||||
// TODO: before we can meaningfully return a ChecksumError result, we need to check the center for the presence of the finder pattern
|
||||
if (!decRes.isValid())
|
||||
return {};
|
||||
|
||||
return ToVector(MatrixBarcode(std::move(decRes), std::move(detRes), BarcodeFormat::MaxiCode));
|
||||
}
|
||||
|
||||
} // namespace ZXing::MaxiCode
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2016 Nu-book Inc.
|
||||
* Copyright 2016 ZXing authors
|
||||
*/
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Reader.h"
|
||||
|
||||
namespace ZXing::MaxiCode {
|
||||
|
||||
class Reader : public ZXing::Reader
|
||||
{
|
||||
public:
|
||||
using ZXing::Reader::Reader;
|
||||
|
||||
BarcodesData read(const BinaryBitmap& image, int maxSymbols) const override;
|
||||
};
|
||||
|
||||
} // namespace ZXing::MaxiCode
|
||||
Reference in new issue
Block a user