Began removing the excessive use of exceptions in the 1D readers by drawing
[zxing.git] / cpp / core / src / zxing / oned / Code128Reader.cpp
1 /*
2  *  Code128Reader.cpp
3  *  ZXing
4  *
5  *  Copyright 2010 ZXing authors All rights reserved.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include "Code128Reader.h"
21 #include <zxing/oned/OneDResultPoint.h>
22 #include <zxing/common/Array.h>
23 #include <zxing/ReaderException.h>
24 #include <math.h>
25 #include <string.h>
26 #include <sstream>
27
28 namespace zxing {
29         namespace oned {
30
31                 const int CODE_PATTERNS_LENGTH = 107;
32                 const int countersLength = 6;
33                 static const int CODE_PATTERNS[CODE_PATTERNS_LENGTH][countersLength] = {
34                         {2, 1, 2, 2, 2, 2}, /* 0 */
35                         {2, 2, 2, 1, 2, 2},
36                         {2, 2, 2, 2, 2, 1},
37                         {1, 2, 1, 2, 2, 3},
38                         {1, 2, 1, 3, 2, 2},
39                         {1, 3, 1, 2, 2, 2}, /* 5 */
40                         {1, 2, 2, 2, 1, 3},
41                         {1, 2, 2, 3, 1, 2},
42                         {1, 3, 2, 2, 1, 2},
43                         {2, 2, 1, 2, 1, 3},
44                         {2, 2, 1, 3, 1, 2}, /* 10 */
45                         {2, 3, 1, 2, 1, 2},
46                         {1, 1, 2, 2, 3, 2},
47                         {1, 2, 2, 1, 3, 2},
48                         {1, 2, 2, 2, 3, 1},
49                         {1, 1, 3, 2, 2, 2}, /* 15 */
50                         {1, 2, 3, 1, 2, 2},
51                         {1, 2, 3, 2, 2, 1},
52                         {2, 2, 3, 2, 1, 1},
53                         {2, 2, 1, 1, 3, 2},
54                         {2, 2, 1, 2, 3, 1}, /* 20 */
55                         {2, 1, 3, 2, 1, 2},
56                         {2, 2, 3, 1, 1, 2},
57                         {3, 1, 2, 1, 3, 1},
58                         {3, 1, 1, 2, 2, 2},
59                         {3, 2, 1, 1, 2, 2}, /* 25 */
60                         {3, 2, 1, 2, 2, 1},
61                         {3, 1, 2, 2, 1, 2},
62                         {3, 2, 2, 1, 1, 2},
63                         {3, 2, 2, 2, 1, 1},
64                         {2, 1, 2, 1, 2, 3}, /* 30 */
65                         {2, 1, 2, 3, 2, 1},
66                         {2, 3, 2, 1, 2, 1},
67                         {1, 1, 1, 3, 2, 3},
68                         {1, 3, 1, 1, 2, 3},
69                         {1, 3, 1, 3, 2, 1}, /* 35 */
70                         {1, 1, 2, 3, 1, 3},
71                         {1, 3, 2, 1, 1, 3},
72                         {1, 3, 2, 3, 1, 1},
73                         {2, 1, 1, 3, 1, 3},
74                         {2, 3, 1, 1, 1, 3}, /* 40 */
75                         {2, 3, 1, 3, 1, 1},
76                         {1, 1, 2, 1, 3, 3},
77                         {1, 1, 2, 3, 3, 1},
78                         {1, 3, 2, 1, 3, 1},
79                         {1, 1, 3, 1, 2, 3}, /* 45 */
80                         {1, 1, 3, 3, 2, 1},
81                         {1, 3, 3, 1, 2, 1},
82                         {3, 1, 3, 1, 2, 1},
83                         {2, 1, 1, 3, 3, 1},
84                         {2, 3, 1, 1, 3, 1}, /* 50 */
85                         {2, 1, 3, 1, 1, 3},
86                         {2, 1, 3, 3, 1, 1},
87                         {2, 1, 3, 1, 3, 1},
88                         {3, 1, 1, 1, 2, 3},
89                         {3, 1, 1, 3, 2, 1}, /* 55 */
90                         {3, 3, 1, 1, 2, 1},
91                         {3, 1, 2, 1, 1, 3},
92                         {3, 1, 2, 3, 1, 1},
93                         {3, 3, 2, 1, 1, 1},
94                         {3, 1, 4, 1, 1, 1}, /* 60 */
95                         {2, 2, 1, 4, 1, 1},
96                         {4, 3, 1, 1, 1, 1},
97                         {1, 1, 1, 2, 2, 4},
98                         {1, 1, 1, 4, 2, 2},
99                         {1, 2, 1, 1, 2, 4}, /* 65 */
100                         {1, 2, 1, 4, 2, 1},
101                         {1, 4, 1, 1, 2, 2},
102                         {1, 4, 1, 2, 2, 1},
103                         {1, 1, 2, 2, 1, 4},
104                         {1, 1, 2, 4, 1, 2}, /* 70 */
105                         {1, 2, 2, 1, 1, 4},
106                         {1, 2, 2, 4, 1, 1},
107                         {1, 4, 2, 1, 1, 2},
108                         {1, 4, 2, 2, 1, 1},
109                         {2, 4, 1, 2, 1, 1}, /* 75 */
110                         {2, 2, 1, 1, 1, 4},
111                         {4, 1, 3, 1, 1, 1},
112                         {2, 4, 1, 1, 1, 2},
113                         {1, 3, 4, 1, 1, 1},
114                         {1, 1, 1, 2, 4, 2}, /* 80 */
115                         {1, 2, 1, 1, 4, 2},
116                         {1, 2, 1, 2, 4, 1},
117                         {1, 1, 4, 2, 1, 2},
118                         {1, 2, 4, 1, 1, 2},
119                         {1, 2, 4, 2, 1, 1}, /* 85 */
120                         {4, 1, 1, 2, 1, 2},
121                         {4, 2, 1, 1, 1, 2},
122                         {4, 2, 1, 2, 1, 1},
123                         {2, 1, 2, 1, 4, 1},
124                         {2, 1, 4, 1, 2, 1}, /* 90 */
125                         {4, 1, 2, 1, 2, 1},
126                         {1, 1, 1, 1, 4, 3},
127                         {1, 1, 1, 3, 4, 1},
128                         {1, 3, 1, 1, 4, 1},
129                         {1, 1, 4, 1, 1, 3}, /* 95 */
130                         {1, 1, 4, 3, 1, 1},
131                         {4, 1, 1, 1, 1, 3},
132                         {4, 1, 1, 3, 1, 1},
133                         {1, 1, 3, 1, 4, 1},
134                         {1, 1, 4, 1, 3, 1}, /* 100 */
135                         {3, 1, 1, 1, 4, 1},
136                         {4, 1, 1, 1, 3, 1},
137                         {2, 1, 1, 4, 1, 2},
138                         {2, 1, 1, 2, 1, 4},
139                         {2, 1, 1, 2, 3, 2}, /* 105 */
140                         {2, 3, 3, 1, 1, 1}
141                 };
142
143
144                 Code128Reader::Code128Reader(){
145                 }
146
147                 int* Code128Reader::findStartPattern(Ref<BitArray> row){
148                         int width = row->getSize();
149                         int rowOffset = 0;
150                         while (rowOffset < width) {
151                                 if (row->get(rowOffset)) {
152                                         break;
153                                 }
154                                 rowOffset++;
155                         }
156
157                         int counterPosition = 0;
158                         int counters[countersLength] = {0,0,0,0,0,0};
159                         int patternStart = rowOffset;
160                         bool isWhite = false;
161                         int patternLength =  sizeof(counters) / sizeof(int);
162
163                         for (int i = rowOffset; i < width; i++) {
164                                 bool pixel = row->get(i);
165                                 if (pixel ^ isWhite) {
166                                         counters[counterPosition]++;
167                                 } else {
168                                         if (counterPosition == patternLength - 1) {
169                                                 unsigned int bestVariance = MAX_AVG_VARIANCE;
170                                                 int bestMatch = -1;
171                                                 for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) {
172                                                         unsigned int variance = patternMatchVariance(counters, sizeof(counters) / sizeof(int),
173                                                             CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE);
174                                                         if (variance < bestVariance) {
175                                                                 bestVariance = variance;
176                                                                 bestMatch = startCode;
177                                                         }
178                                                 }
179                                                 if (bestMatch >= 0) {
180                                                         // Look for whitespace before start pattern, >= 50% of width of start pattern
181                                                         if (row->isRange(fmaxl(0, patternStart - (i - patternStart) / 2), patternStart,
182                                                             false)) {
183                                                                 int* resultValue = new int[3];
184                                                                 resultValue[0] = patternStart;
185                                                                 resultValue[1] = i;
186                                                                 resultValue[2] = bestMatch;
187                                                                 return resultValue;
188                                                         }
189                                                 }
190                                                 patternStart += counters[0] + counters[1];
191                                                 for (int y = 2; y < patternLength; y++) {
192                                                         counters[y - 2] = counters[y];
193                                                 }
194                                                 counters[patternLength - 2] = 0;
195                                                 counters[patternLength - 1] = 0;
196                                                 counterPosition--;
197                                         } else {
198                                                 counterPosition++;
199                                         }
200                                         counters[counterPosition] = 1;
201                                         isWhite = !isWhite;
202                                 }
203                         }
204                         throw ReaderException("");
205                 }
206
207                 int Code128Reader::decodeCode(Ref<BitArray> row, int counters[], int countersCount,
208                     int rowOffset){
209                         recordPattern(row, rowOffset, counters, countersCount);
210                         unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
211                         int bestMatch = -1;
212                         for (int d = 0; d < CODE_PATTERNS_LENGTH; d++) {
213                                 int pattern[countersLength];
214
215                                 for(int ind = 0; ind< countersLength; ind++){
216                                         pattern[ind] = CODE_PATTERNS[d][ind];
217                                 }
218 //                              memcpy(pattern, CODE_PATTERNS[d], countersLength);
219                                 unsigned int variance = patternMatchVariance(counters, countersCount, pattern,
220                                     MAX_INDIVIDUAL_VARIANCE);
221                                 if (variance < bestVariance) {
222                                         bestVariance = variance;
223                                         bestMatch = d;
224                                 }
225                         }
226                         // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6.
227                         if (bestMatch >= 0) {
228                                 return bestMatch;
229                         } else {
230                                 throw ReaderException("");
231                         }
232                 }
233
234                 Ref<Result> Code128Reader::decodeRow(int rowNumber, Ref<BitArray> row) {
235                   int* startPatternInfo = NULL;
236                   try {
237         startPatternInfo = findStartPattern(row);
238         int startCode = startPatternInfo[2];
239         int codeSet;
240         switch (startCode) {
241           case CODE_START_A:
242             codeSet = CODE_CODE_A;
243             break;
244           case CODE_START_B:
245             codeSet = CODE_CODE_B;
246             break;
247           case CODE_START_C:
248             codeSet = CODE_CODE_C;
249             break;
250           default:
251             throw ReaderException("");
252         }
253
254         bool done = false;
255         bool isNextShifted = false;
256
257         std::string tmpResultString;
258         std::stringstream tmpResultSStr; // used if its Code 128C
259
260         int lastStart = startPatternInfo[0];
261         int nextStart = startPatternInfo[1];
262         int counters[countersLength] = {0,0,0,0,0,0};
263
264         int lastCode = 0;
265         int code = 0;
266         int checksumTotal = startCode;
267         int multiplier = 0;
268         bool lastCharacterWasPrintable = true;
269
270         while (!done) {
271           bool unshift = isNextShifted;
272           isNextShifted = false;
273
274           // Save off last code
275           lastCode = code;
276
277           // Decode another code from image
278           try {
279             code = decodeCode(row, counters, sizeof(counters)/sizeof(int), nextStart);
280           } catch (ReaderException re) {
281             throw re;
282           }
283
284           // Remember whether the last code was printable or not (excluding CODE_STOP)
285           if (code != CODE_STOP) {
286             lastCharacterWasPrintable = true;
287           }
288
289           // Add to checksum computation (if not CODE_STOP of course)
290           if (code != CODE_STOP) {
291             multiplier++;
292             checksumTotal += multiplier * code;
293           }
294
295           // Advance to where the next code will to start
296           lastStart = nextStart;
297           int _countersLength = sizeof(counters) / sizeof(int);
298           for (int i = 0; i < _countersLength; i++) {
299             nextStart += counters[i];
300           }
301
302           // Take care of illegal start codes
303           switch (code) {
304             case CODE_START_A:
305             case CODE_START_B:
306             case CODE_START_C:
307               throw ReaderException("");
308           }
309
310           switch (codeSet) {
311
312             case CODE_CODE_A:
313               if (code < 64) {
314                 tmpResultString.append(1, (char) (' ' + code));
315               } else if (code < 96) {
316                 tmpResultString.append(1, (char) (code - 64));
317               } else {
318                 // Don't let CODE_STOP, which always appears, affect whether whether we think the
319                 // last code was printable or not.
320                 if (code != CODE_STOP) {
321                   lastCharacterWasPrintable = false;
322                 }
323                 switch (code) {
324                   case CODE_FNC_1:
325                   case CODE_FNC_2:
326                   case CODE_FNC_3:
327                   case CODE_FNC_4_A:
328                     // do nothing?
329                     break;
330                   case CODE_SHIFT:
331                     isNextShifted = true;
332                     codeSet = CODE_CODE_B;
333                     break;
334                   case CODE_CODE_B:
335                     codeSet = CODE_CODE_B;
336                     break;
337                   case CODE_CODE_C:
338                     codeSet = CODE_CODE_C;
339                     break;
340                   case CODE_STOP:
341                     done = true;
342                     break;
343                 }
344               }
345               break;
346             case CODE_CODE_B:
347               if (code < 96) {
348                 tmpResultString.append(1, (char) (' ' + code));
349               } else {
350                 if (code != CODE_STOP) {
351                   lastCharacterWasPrintable = false;
352                 }
353                 switch (code) {
354                   case CODE_FNC_1:
355                   case CODE_FNC_2:
356                   case CODE_FNC_3:
357                   case CODE_FNC_4_B:
358                     // do nothing?
359                     break;
360                   case CODE_SHIFT:
361                     isNextShifted = true;
362                     codeSet = CODE_CODE_C;
363                     break;
364                   case CODE_CODE_A:
365                     codeSet = CODE_CODE_A;
366                     break;
367                   case CODE_CODE_C:
368                     codeSet = CODE_CODE_C;
369                     break;
370                   case CODE_STOP:
371                     done = true;
372                     break;
373                 }
374               }
375               break;
376             case CODE_CODE_C:
377             // the code read in this case is the number encoded directly
378               if (code < 100) {
379                 if (code < 10)
380                 tmpResultSStr << '0';
381               tmpResultSStr << code;
382               } else {
383                 if (code != CODE_STOP) {
384                   lastCharacterWasPrintable = false;
385                 }
386                 switch (code) {
387                   case CODE_FNC_1:
388                     // do nothing?
389                     break;
390                   case CODE_CODE_A:
391                     codeSet = CODE_CODE_A;
392                     break;
393                   case CODE_CODE_B:
394                     codeSet = CODE_CODE_B;
395                     break;
396                   case CODE_STOP:
397                     done = true;
398                     break;
399                 }
400               }
401               break;
402           }
403
404           // Unshift back to another code set if we were shifted
405           if (unshift) {
406             switch (codeSet) {
407               case CODE_CODE_A:
408                 codeSet = CODE_CODE_C;
409                 break;
410               case CODE_CODE_B:
411                 codeSet = CODE_CODE_A;
412                 break;
413               case CODE_CODE_C:
414                 codeSet = CODE_CODE_B;
415                 break;
416             }
417           }
418
419         }
420
421         // Check for ample whitespace following pattern, but, to do this we first need to remember that
422         // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left
423         // to read off. Would be slightly better to properly read. Here we just skip it:
424         int width = row->getSize();
425         while (nextStart < width && row->get(nextStart)) {
426           nextStart++;
427         }
428         if (!row->isRange(nextStart, fminl(width, nextStart + (nextStart - lastStart) / 2), false)) {
429           throw ReaderException("");
430         }
431
432         // Pull out from sum the value of the penultimate check code
433         checksumTotal -= multiplier * lastCode;
434         // lastCode is the checksum then:
435         if (checksumTotal % 103 != lastCode) {
436           throw ReaderException("");
437         }
438
439         if (codeSet == CODE_CODE_C)
440           tmpResultString.append(tmpResultSStr.str());
441
442         // Need to pull out the check digits from string
443         int resultLength = tmpResultString.length();
444         // Only bother if the result had at least one character, and if the checksum digit happened to
445         // be a printable character. If it was just interpreted as a control code, nothing to remove.
446         if (resultLength > 0 && lastCharacterWasPrintable) {
447           if (codeSet == CODE_CODE_C) {
448             tmpResultString.erase(resultLength - 2, resultLength);
449           } else {
450             tmpResultString.erase(resultLength - 1, resultLength);
451           }
452         }
453
454         Ref<String> resultString(new String(tmpResultString));
455         if (tmpResultString.length() == 0) {
456           // Almost surely a false positive
457           throw ReaderException("");
458         }
459
460         float left = (float) (startPatternInfo[1] + startPatternInfo[0]) / 2.0f;
461         float right = (float) (nextStart + lastStart) / 2.0f;
462
463         std::vector< Ref<ResultPoint> > resultPoints(2);
464         Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
465         Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber));
466         resultPoints[0] = resultPoint1;
467         resultPoints[1] = resultPoint2;
468
469         delete [] startPatternInfo;
470         ArrayRef<unsigned char> resultBytes(1);
471         return Ref<Result>(new Result(resultString, resultBytes, resultPoints,
472             BarcodeFormat_CODE_128));
473                         } catch (ReaderException const& re) {
474                           delete [] startPatternInfo;
475                           return Ref<Result>();
476                         }
477                 }
478
479                 void Code128Reader::append(char* s, char c){
480                         int len = strlen(s);
481                         s[len] = c;
482                         s[len + 1] = '\0';
483                 }
484
485                 Code128Reader::~Code128Reader(){
486                 }
487         }
488 }