@@ -34,7 +34,6 @@ static const int CODE_FNC_2 = 97;
34
34
static const int CODE_FNC_3 = 96 ;
35
35
36
36
static const int CODE_START_A = 103 ;
37
- static const int CODE_START_B = 104 ;
38
37
static const int CODE_START_C = 105 ;
39
38
static const int CODE_STOP = 106 ;
40
39
@@ -157,76 +156,44 @@ class Raw2TxtDecoder
157
156
bool readerInit () const { return _readerInit; }
158
157
};
159
158
160
- template <typename C>
161
- static int DetectStartCode (const C& c)
162
- {
163
- int bestCode = 0 ;
164
- float bestVariance = MAX_AVG_VARIANCE;
165
- for (int code : {CODE_START_A, CODE_START_B, CODE_START_C}) {
166
- float variance = RowReader::PatternMatchVariance (c, Code128::CODE_PATTERNS[code], MAX_INDIVIDUAL_VARIANCE);
167
- if (variance < bestVariance) {
168
- bestVariance = variance;
169
- bestCode = code;
170
- }
171
- }
172
- return bestVariance < MAX_AVG_VARIANCE ? bestCode : 0 ;
173
- }
174
-
175
159
// all 3 start patterns share the same 2-1-1 prefix
176
160
constexpr auto START_PATTERN_PREFIX = FixedPattern<3 , 4 >{2 , 1 , 1 };
177
161
constexpr int CHAR_LEN = 6 ;
178
162
constexpr float QUIET_ZONE = 5 ; // quiet zone spec is 10 modules, real world examples ignore that, see #138
179
-
180
- // #define USE_FAST_1_TO_4_BIT_PATTERN_DECODING
181
- #ifdef USE_FAST_1_TO_4_BIT_PATTERN_DECODING
182
163
constexpr int CHAR_SUM = 11 ;
183
- constexpr int CHARACTER_ENCODINGS[] = {
184
- 0b11011001100 , 0b11001101100 , 0b11001100110 , 0b10010011000 , 0b10010001100 , // 0
185
- 0b10001001100 , 0b10011001000 , 0b10011000100 , 0b10001100100 , 0b11001001000 , // 5
186
- 0b11001000100 , 0b11000100100 , 0b10110011100 , 0b10011011100 , 0b10011001110 , // 10
187
- 0b10111001100 , 0b10011101100 , 0b10011100110 , 0b11001110010 , 0b11001011100 , // 15
188
- 0b11001001110 , 0b11011100100 , 0b11001110100 , 0b11101101110 , 0b11101001100 , // 20
189
- 0b11100101100 , 0b11100100110 , 0b11101100100 , 0b11100110100 , 0b11100110010 , // 25
190
- 0b11011011000 , 0b11011000110 , 0b11000110110 , 0b10100011000 , 0b10001011000 , // 30
191
- 0b10001000110 , 0b10110001000 , 0b10001101000 , 0b10001100010 , 0b11010001000 , // 35
192
- 0b11000101000 , 0b11000100010 , 0b10110111000 , 0b10110001110 , 0b10001101110 , // 40
193
- 0b10111011000 , 0b10111000110 , 0b10001110110 , 0b11101110110 , 0b11010001110 , // 45
194
- 0b11000101110 , 0b11011101000 , 0b11011100010 , 0b11011101110 , 0b11101011000 , // 50
195
- 0b11101000110 , 0b11100010110 , 0b11101101000 , 0b11101100010 , 0b11100011010 , // 55
196
- 0b11101111010 , 0b11001000010 , 0b11110001010 , 0b10100110000 , 0b10100001100 , // 60
197
- 0b10010110000 , 0b10010000110 , 0b10000101100 , 0b10000100110 , 0b10110010000 , // 65
198
- 0b10110000100 , 0b10011010000 , 0b10011000010 , 0b10000110100 , 0b10000110010 , // 70
199
- 0b11000010010 , 0b11001010000 , 0b11110111010 , 0b11000010100 , 0b10001111010 , // 75
200
- 0b10100111100 , 0b10010111100 , 0b10010011110 , 0b10111100100 , 0b10011110100 , // 80
201
- 0b10011110010 , 0b11110100100 , 0b11110010100 , 0b11110010010 , 0b11011011110 , // 85
202
- 0b11011110110 , 0b11110110110 , 0b10101111000 , 0b10100011110 , 0b10001011110 , // 90
203
- 0b10111101000 , 0b10111100010 , 0b11110101000 , 0b11110100010 , 0b10111011110 , // 95
204
- 0b10111101110 , 0b11101011110 , 0b11110101110 , 0b11010000100 , 0b11010010000 , // 100
205
- 0b11010011100 , 0b11000111010 , // 105
206
- };
207
- #endif
164
+
165
+ // TODO: make this a constexpr variable initialization
166
+ static auto E2E_PATTERNS = [] {
167
+ // This creates an array of ints for fast IndexOf lookup of the edge-2-edge patterns (ISO/IEC 15417:2007(E) Table 2)
168
+ // e.g. a code pattern of { 2, 1, 2, 2, 2, 2 } becomes the e2e pattern { 3, 3, 4, 4 } and the value 0b11100011110000.
169
+ std::array<int , 107 > res;
170
+ for (int i = 0 ; i < Size (res); ++i) {
171
+ const auto & a = Code128::CODE_PATTERNS[i];
172
+ std::array<int , 4 > e2e;
173
+ for (int j = 0 ; j < 4 ; j++)
174
+ e2e[j] = a[j] + a[j + 1 ];
175
+ res[i] = ToInt (e2e);
176
+ }
177
+ return res;
178
+ }();
208
179
209
180
Result Code128Reader::decodePattern (int rowNumber, PatternView& next, std::unique_ptr<DecodingState>&) const
210
181
{
211
182
int minCharCount = 4 ; // start + payload + checksum + stop
212
- auto decodePattern = [](const PatternView& view, bool start = false ) {
213
- // TODO: the intention was to always use the way faster OneToFourBitPattern approach but it turned out
214
- // the old DecodeDigit currently detects more test samples. There could be gained another 20% in
215
- // in performance. This might work once the subpixel binarizer is in place.
216
- #ifdef USE_FAST_1_TO_4_BIT_PATTERN_DECODING
217
- return IndexOf (CHARACTER_ENCODINGS, OneToFourBitPattern<CHAR_LEN, CHAR_SUM>(view));
218
- #else
219
- return start ? DetectStartCode (view)
220
- : DecodeDigit (view, Code128::CODE_PATTERNS, MAX_AVG_VARIANCE, MAX_INDIVIDUAL_VARIANCE);
221
- #endif
183
+ auto decodePattern = [](const PatternView& view) {
184
+ // This is basically the reference algorithm from the specification
185
+ int code = IndexOf (E2E_PATTERNS, ToInt (NormalizedE2EPattern<CHAR_LEN, CHAR_SUM>(view)));
186
+ if (code == -1 ) // if the reference algo fails, give the original upstream version a try (required to decode a few samples)
187
+ code = DecodeDigit (view, Code128::CODE_PATTERNS, MAX_AVG_VARIANCE, MAX_INDIVIDUAL_VARIANCE);
188
+ return code;
222
189
};
223
190
224
191
next = FindLeftGuard (next, minCharCount * CHAR_LEN, START_PATTERN_PREFIX, QUIET_ZONE);
225
192
if (!next.isValid ())
226
193
return {};
227
194
228
195
next = next.subView (0 , CHAR_LEN);
229
- int startCode = decodePattern (next, true );
196
+ int startCode = decodePattern (next);
230
197
if (!(CODE_START_A <= startCode && startCode <= CODE_START_C))
231
198
return {};
232
199
0 commit comments