Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

Code128Reader.cpp Example File

appdemos/qtws/QZXing/zxing/zxing/oned/Code128Reader.cpp
 // -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
 /*
  *  Copyright 2010 ZXing authors All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */

 #include <zxing/ZXing.h>
 #include <zxing/oned/Code128Reader.h>
 #include <zxing/oned/OneDResultPoint.h>
 #include <zxing/common/Array.h>
 #include <zxing/ReaderException.h>
 #include <zxing/NotFoundException.h>
 #include <zxing/FormatException.h>
 #include <zxing/ChecksumException.h>
 #include <zxing/DecodeHints.h>
 #include <zxing/BarcodeFormat.h>
 #include <math.h>
 #include <string.h>
 #include <sstream>
 #include <algorithm>

 using std::vector;
 using std::string;
 using zxing::NotFoundException;
 using zxing::FormatException;
 using zxing::ChecksumException;
 using zxing::Ref;
 using zxing::Result;
 using zxing::oned::Code128Reader;

 // VC++
 using zxing::BitArray;

 const int Code128Reader::MAX_AVG_VARIANCE = int(PATTERN_MATCH_RESULT_SCALE_FACTOR * 250/1000);
 const int Code128Reader::MAX_INDIVIDUAL_VARIANCE = int(PATTERN_MATCH_RESULT_SCALE_FACTOR * 700/1000);

 namespace {

 const int CODE_SHIFT = 98;

 const int CODE_CODE_C = 99;
 const int CODE_CODE_B = 100;
 const int CODE_CODE_A = 101;

 const int CODE_FNC_1 = 102;
 const int CODE_FNC_2 = 97;
 const int CODE_FNC_3 = 96;
 const int CODE_FNC_4_A = 101;
 const int CODE_FNC_4_B = 100;

 const int CODE_START_A = 103;
 const int CODE_START_B = 104;
 const int CODE_START_C = 105;
 const int CODE_STOP = 106;

 const int CODE_PATTERNS_LENGTH = 107;
 const int CODE_PATTERNS[CODE_PATTERNS_LENGTH][6] = {
   {2, 1, 2, 2, 2, 2}, /* 0 */
   {2, 2, 2, 1, 2, 2},
   {2, 2, 2, 2, 2, 1},
   {1, 2, 1, 2, 2, 3},
   {1, 2, 1, 3, 2, 2},
   {1, 3, 1, 2, 2, 2}, /* 5 */
   {1, 2, 2, 2, 1, 3},
   {1, 2, 2, 3, 1, 2},
   {1, 3, 2, 2, 1, 2},
   {2, 2, 1, 2, 1, 3},
   {2, 2, 1, 3, 1, 2}, /* 10 */
   {2, 3, 1, 2, 1, 2},
   {1, 1, 2, 2, 3, 2},
   {1, 2, 2, 1, 3, 2},
   {1, 2, 2, 2, 3, 1},
   {1, 1, 3, 2, 2, 2}, /* 15 */
   {1, 2, 3, 1, 2, 2},
   {1, 2, 3, 2, 2, 1},
   {2, 2, 3, 2, 1, 1},
   {2, 2, 1, 1, 3, 2},
   {2, 2, 1, 2, 3, 1}, /* 20 */
   {2, 1, 3, 2, 1, 2},
   {2, 2, 3, 1, 1, 2},
   {3, 1, 2, 1, 3, 1},
   {3, 1, 1, 2, 2, 2},
   {3, 2, 1, 1, 2, 2}, /* 25 */
   {3, 2, 1, 2, 2, 1},
   {3, 1, 2, 2, 1, 2},
   {3, 2, 2, 1, 1, 2},
   {3, 2, 2, 2, 1, 1},
   {2, 1, 2, 1, 2, 3}, /* 30 */
   {2, 1, 2, 3, 2, 1},
   {2, 3, 2, 1, 2, 1},
   {1, 1, 1, 3, 2, 3},
   {1, 3, 1, 1, 2, 3},
   {1, 3, 1, 3, 2, 1}, /* 35 */
   {1, 1, 2, 3, 1, 3},
   {1, 3, 2, 1, 1, 3},
   {1, 3, 2, 3, 1, 1},
   {2, 1, 1, 3, 1, 3},
   {2, 3, 1, 1, 1, 3}, /* 40 */
   {2, 3, 1, 3, 1, 1},
   {1, 1, 2, 1, 3, 3},
   {1, 1, 2, 3, 3, 1},
   {1, 3, 2, 1, 3, 1},
   {1, 1, 3, 1, 2, 3}, /* 45 */
   {1, 1, 3, 3, 2, 1},
   {1, 3, 3, 1, 2, 1},
   {3, 1, 3, 1, 2, 1},
   {2, 1, 1, 3, 3, 1},
   {2, 3, 1, 1, 3, 1}, /* 50 */
   {2, 1, 3, 1, 1, 3},
   {2, 1, 3, 3, 1, 1},
   {2, 1, 3, 1, 3, 1},
   {3, 1, 1, 1, 2, 3},
   {3, 1, 1, 3, 2, 1}, /* 55 */
   {3, 3, 1, 1, 2, 1},
   {3, 1, 2, 1, 1, 3},
   {3, 1, 2, 3, 1, 1},
   {3, 3, 2, 1, 1, 1},
   {3, 1, 4, 1, 1, 1}, /* 60 */
   {2, 2, 1, 4, 1, 1},
   {4, 3, 1, 1, 1, 1},
   {1, 1, 1, 2, 2, 4},
   {1, 1, 1, 4, 2, 2},
   {1, 2, 1, 1, 2, 4}, /* 65 */
   {1, 2, 1, 4, 2, 1},
   {1, 4, 1, 1, 2, 2},
   {1, 4, 1, 2, 2, 1},
   {1, 1, 2, 2, 1, 4},
   {1, 1, 2, 4, 1, 2}, /* 70 */
   {1, 2, 2, 1, 1, 4},
   {1, 2, 2, 4, 1, 1},
   {1, 4, 2, 1, 1, 2},
   {1, 4, 2, 2, 1, 1},
   {2, 4, 1, 2, 1, 1}, /* 75 */
   {2, 2, 1, 1, 1, 4},
   {4, 1, 3, 1, 1, 1},
   {2, 4, 1, 1, 1, 2},
   {1, 3, 4, 1, 1, 1},
   {1, 1, 1, 2, 4, 2}, /* 80 */
   {1, 2, 1, 1, 4, 2},
   {1, 2, 1, 2, 4, 1},
   {1, 1, 4, 2, 1, 2},
   {1, 2, 4, 1, 1, 2},
   {1, 2, 4, 2, 1, 1}, /* 85 */
   {4, 1, 1, 2, 1, 2},
   {4, 2, 1, 1, 1, 2},
   {4, 2, 1, 2, 1, 1},
   {2, 1, 2, 1, 4, 1},
   {2, 1, 4, 1, 2, 1}, /* 90 */
   {4, 1, 2, 1, 2, 1},
   {1, 1, 1, 1, 4, 3},
   {1, 1, 1, 3, 4, 1},
   {1, 3, 1, 1, 4, 1},
   {1, 1, 4, 1, 1, 3}, /* 95 */
   {1, 1, 4, 3, 1, 1},
   {4, 1, 1, 1, 1, 3},
   {4, 1, 1, 3, 1, 1},
   {1, 1, 3, 1, 4, 1},
   {1, 1, 4, 1, 3, 1}, /* 100 */
   {3, 1, 1, 1, 4, 1},
   {4, 1, 1, 1, 3, 1},
   {2, 1, 1, 4, 1, 2},
   {2, 1, 1, 2, 1, 4},
   {2, 1, 1, 2, 3, 2}, /* 105 */
   {2, 3, 3, 1, 1, 1}
 };

 }

 Code128Reader::Code128Reader(){}

 vector<int> Code128Reader::findStartPattern(Ref<BitArray> row){
   int width = row->getSize();
   int rowOffset = row->getNextSet(0);

   int counterPosition = 0;
   vector<int> counters (6, 0);
   int patternStart = rowOffset;
   bool isWhite = false;
   int patternLength =  counters.size();

   for (int i = rowOffset; i < width; i++) {
     if (row->get(i) ^ isWhite) {
       counters[counterPosition]++;
     } else {
       if (counterPosition == patternLength - 1) {
         int bestVariance = MAX_AVG_VARIANCE;
         int bestMatch = -1;
         for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) {
           int variance = patternMatchVariance(counters, CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE);
           if (variance < bestVariance) {
             bestVariance = variance;
             bestMatch = startCode;
           }
         }
         // Look for whitespace before start pattern, >= 50% of width of start pattern
         if (bestMatch >= 0 &&
             row->isRange(std::max(0, patternStart - (i - patternStart) / 2), patternStart, false)) {
           vector<int> resultValue (3, 0);
           resultValue[0] = patternStart;
           resultValue[1] = i;
           resultValue[2] = bestMatch;
           return resultValue;
         }
         patternStart += counters[0] + counters[1];
         for (int y = 2; y < patternLength; y++) {
           counters[y - 2] = counters[y];
         }
         counters[patternLength - 2] = 0;
         counters[patternLength - 1] = 0;
         counterPosition--;
       } else {
         counterPosition++;
       }
       counters[counterPosition] = 1;
       isWhite = !isWhite;
     }
   }
   throw NotFoundException();
 }

 int Code128Reader::decodeCode(Ref<BitArray> row, vector<int>& counters, int rowOffset) {
   recordPattern(row, rowOffset, counters);
   int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
   int bestMatch = -1;
   for (int d = 0; d < CODE_PATTERNS_LENGTH; d++) {
     int const* const pattern = CODE_PATTERNS[d];
     int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
     if (variance < bestVariance) {
       bestVariance = variance;
       bestMatch = d;
     }
   }
   // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6.
   if (bestMatch >= 0) {
     return bestMatch;
   } else {
     throw NotFoundException();
   }
 }

 Ref<Result> Code128Reader::decodeRow(int rowNumber, Ref<BitArray> row, zxing::DecodeHints hints) {
   bool convertFNC1 = hints.containsFormat(zxing::BarcodeFormat(zxing::BarcodeFormat::Value::ASSUME_GS1));

   vector<int> startPatternInfo (findStartPattern(row));
   int startCode = startPatternInfo[2];
   int codeSet;
   switch (startCode) {
     case CODE_START_A:
       codeSet = CODE_CODE_A;
       break;
     case CODE_START_B:
       codeSet = CODE_CODE_B;
       break;
     case CODE_START_C:
       codeSet = CODE_CODE_C;
       break;
     default:
       throw FormatException();
   }

   bool done = false;
   bool isNextShifted = false;

   string result;
   vector<byte> rawCodes(20, 0);

   int lastStart = startPatternInfo[0];
   int nextStart = startPatternInfo[1];
   vector<int> counters (6, 0);

   int lastCode = 0;
   int code = 0;
   int checksumTotal = startCode;
   int multiplier = 0;
   bool lastCharacterWasPrintable = true;
   bool upperMode = false;
   bool shiftUpperMode = false;

   std::ostringstream oss;

   while (!done) {

     bool unshift = isNextShifted;
     isNextShifted = false;

     // Save off last code
     lastCode = code;

     code = decodeCode(row, counters, nextStart);

     // Remember whether the last code was printable or not (excluding CODE_STOP)
     if (code != CODE_STOP) {
       lastCharacterWasPrintable = true;
     }

     // Add to checksum computation (if not CODE_STOP of course)
     if (code != CODE_STOP) {
       multiplier++;
       checksumTotal += multiplier * code;
     }

     // Advance to where the next code will to start
     lastStart = nextStart;
     for (int i = 0, e = counters.size(); i < e; i++) {
       nextStart += counters[i];
     }

     // Take care of illegal start codes
     switch (code) {
       case CODE_START_A:
       case CODE_START_B:
       case CODE_START_C:
         throw FormatException();
     }

     switch (codeSet) {

       case CODE_CODE_A:
         if (code < 64) {
             if (shiftUpperMode == upperMode) {
               result.append(1,(byte) (' ' + code));
             } else {
               result.append(1,(byte) (' ' + code + 128));
             }
             shiftUpperMode = false;
         } else if (code < 96) {
             if (shiftUpperMode == upperMode) {
               result.append(1, (byte) (code - 64));
             } else {
               result.append(1, (byte) (code + 64));
             }
             shiftUpperMode = false;
         } else {
           // Don't let CODE_STOP, which always appears, affect whether whether we think the
           // last code was printable or not.
           if (code != CODE_STOP) {
             lastCharacterWasPrintable = false;
           }
           switch (code) {
             case CODE_FNC_1:
               if (convertFNC1) {
                 if (result.length() == 0){
                   // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
                   // is FNC1 then this is GS1-128. We add the symbology identifier.
                   result.append("]C1");
                 } else {
                   // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)
                   result.append(1, (byte) 29);
                 }
               }
               break;
             case CODE_FNC_2:
             case CODE_FNC_3:
               break;
             case CODE_FNC_4_A:
               if (!upperMode && shiftUpperMode) {
                 upperMode = true;
                 shiftUpperMode = false;
               } else if (upperMode && shiftUpperMode) {
                 upperMode = false;
                 shiftUpperMode = false;
               } else {
                 shiftUpperMode = true;
               }
               break;
             case CODE_SHIFT:
               isNextShifted = true;
               codeSet = CODE_CODE_B;
               break;
             case CODE_CODE_B:
               codeSet = CODE_CODE_B;
               break;
             case CODE_CODE_C:
               codeSet = CODE_CODE_C;
               break;
             case CODE_STOP:
               done = true;
               break;
           }
         }
         break;
       case CODE_CODE_B:
         if (code < 96) {
             if (shiftUpperMode == upperMode) {
               result.append(1, (byte) (' ' + code));
             } else {
               result.append(1, (byte) (' ' + code + 128));
             }
             shiftUpperMode = false;
         } else {
           if (code != CODE_STOP) {
             lastCharacterWasPrintable = false;
           }
           switch (code) {
           case CODE_FNC_1:
               if (convertFNC1) {
                 if (result.length() == 0) {
                   // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
                   // is FNC1 then this is GS1-128. We add the symbology identifier.
                   result.append("]C1");
                 } else {
                   // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)
                   result.append(1, (byte) 29);
                 }
               }
               break;
             case CODE_FNC_2:
             case CODE_FNC_3:
               break;
             case CODE_FNC_4_B:
               if (!upperMode && shiftUpperMode) {
                 upperMode = true;
                 shiftUpperMode = false;
               } else if (upperMode && shiftUpperMode) {
                 upperMode = false;
                 shiftUpperMode = false;
               } else {
                 shiftUpperMode = true;
               }
               break;
             case CODE_SHIFT:
               isNextShifted = true;
               codeSet = CODE_CODE_A;
               break;
             case CODE_CODE_A:
               codeSet = CODE_CODE_A;
               break;
             case CODE_CODE_C:
               codeSet = CODE_CODE_C;
               break;
             case CODE_STOP:
               done = true;
               break;
           }
         }
         break;
       case CODE_CODE_C:
         if (code < 100) {
           if (code < 10) {
             result.append(1, '0');
           }
           oss.clear();
           oss.str("");
           oss << code;
           result.append(oss.str());
         } else {
           if (code != CODE_STOP) {
             lastCharacterWasPrintable = false;
           }
           switch (code) {
             case CODE_FNC_1:
               if (convertFNC1) {
                 if (result.length() == 0) {
                   // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code
                   // is FNC1 then this is GS1-128. We add the symbology identifier.
                   result.append("]C1");
                 } else {
                   // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS)
                   result.append(1, (byte) 29);
                 }
               }
               break;
             case CODE_CODE_A:
               codeSet = CODE_CODE_A;
               break;
             case CODE_CODE_B:
               codeSet = CODE_CODE_B;
               break;
             case CODE_STOP:
               done = true;
               break;
           }
         }
         break;
     }

     // Unshift back to another code set if we were shifted
     if (unshift) {
       codeSet = codeSet == CODE_CODE_A ? CODE_CODE_B : CODE_CODE_A;
     }

   }

   int lastPatternSize = nextStart - lastStart;

   // Check for ample whitespace following pattern, but, to do this we first need to remember that
   // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left
   // to read off. Would be slightly better to properly read. Here we just skip it:
   nextStart = row->getNextUnset(nextStart);
   if (!row->isRange(nextStart,
                     std::min(row->getSize(), nextStart + (nextStart - lastStart) / 2),
                     false)) {
     throw NotFoundException();
   }

   // Pull out from sum the value of the penultimate check code
   checksumTotal -= multiplier * lastCode;
   // lastCode is the checksum then:
   if (checksumTotal % 103 != lastCode) {
     throw ChecksumException();
   }

   // Need to pull out the check digits from string
   int resultLength = result.length();
   if (resultLength == 0) {
     // false positive
     throw NotFoundException();
   }

   // Only bother if the result had at least one character, and if the checksum digit happened to
   // be a printable character. If it was just interpreted as a control code, nothing to remove.
   if (resultLength > 0 && lastCharacterWasPrintable) {
     if (codeSet == CODE_CODE_C) {
       result.erase(resultLength - 2, resultLength);
     } else {
       result.erase(resultLength - 1, resultLength);
     }
   }

   float left = (float) (startPatternInfo[1] + startPatternInfo[0]) / 2.0f;
   float right = lastStart + lastPatternSize / 2.0f;

   int rawCodesSize = rawCodes.size();
   ArrayRef<byte> rawBytes (rawCodesSize);
   for (int i = 0; i < rawCodesSize; i++) {
     rawBytes[i] = rawCodes[i];
   }

   ArrayRef< Ref<ResultPoint> > resultPoints(2);
   resultPoints[0] =
       Ref<OneDResultPoint>(new OneDResultPoint(left, (float) rowNumber));
   resultPoints[1] =
       Ref<OneDResultPoint>(new OneDResultPoint(right, (float) rowNumber));

   return Ref<Result>(new Result(Ref<String>(new String(result)), rawBytes, resultPoints,
                                 BarcodeFormat::CODE_128));
 }

 Code128Reader::~Code128Reader(){}

 zxing::BarcodeFormat Code128Reader::getBarcodeFormat(){
   return BarcodeFormat::CODE_128;
 }
Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded