int Code128Reader::decodeCode(Ref<BitArray> row, int counters[], int countersCount, int rowOffset) { if (!recordPattern(row, rowOffset, counters, countersCount)) { throw ReaderException(""); } unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; for (int d = 0; d < CODE_PATTERNS_LENGTH; d++) { int pattern[countersLength]; for(int ind = 0; ind< countersLength; ind++){ pattern[ind] = CODE_PATTERNS[d][ind]; } // memcpy(pattern, CODE_PATTERNS[d], countersLength); unsigned int variance = patternMatchVariance(counters, countersCount, 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 ReaderException(""); } }
void OneDReader::recordPattern(Ref<BitArray> row, int start, int counters[], int countersCount){ int numCounters = countersCount;//sizeof(counters) / sizeof(int); for (int i = 0; i < numCounters; i++) { counters[i] = 0; } int end = row->getSize(); if (start >= end) { throw ReaderException("recordPattern: start >= end"); } bool isWhite = !row->get(start); int counterPosition = 0; int i = start; while (i < end) { bool pixel = row->get(i); if (pixel ^ isWhite) { // that is, exactly one is true counters[counterPosition]++; } else { counterPosition++; if (counterPosition == numCounters) { break; } else { counters[counterPosition] = 1; isWhite ^= true; // isWhite = !isWhite; } } i++; } // If we read fully the last section of pixels and filled up our counters -- or filled // the last counter but ran off the side of the image, OK. Otherwise, a problem. if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end))) { throw ReaderException("recordPattern"); } }
Ref<String> Code39Reader::decodeExtended(std::string encoded){ int length = encoded.length(); std::string tmpDecoded; for (int i = 0; i < length; i++) { char c = encoded[i]; if (c == '+' || c == '$' || c == '%' || c == '/') { char next = encoded[i + 1]; char decodedChar = '\0'; switch (c) { case '+': // +A to +Z map to a to z if (next >= 'A' && next <= 'Z') { decodedChar = (char) (next + 32); } else { throw ReaderException(""); } break; case '$': // $A to $Z map to control codes SH to SB if (next >= 'A' && next <= 'Z') { decodedChar = (char) (next - 64); } else { throw ReaderException(""); } break; case '%': // %A to %E map to control codes ESC to US if (next >= 'A' && next <= 'E') { decodedChar = (char) (next - 38); } else if (next >= 'F' && next <= 'W') { decodedChar = (char) (next - 11); } else { throw ReaderException(""); } break; case '/': // /A to /O map to ! to , and /Z maps to : if (next >= 'A' && next <= 'O') { decodedChar = (char) (next - 32); } else if (next == 'Z') { decodedChar = ':'; } else { throw ReaderException(""); } break; } tmpDecoded.append(1, decodedChar); // bump up i again since we read two characters i++; } else { tmpDecoded.append(1, c); } } Ref<String> decoded(new String(tmpDecoded)); return decoded; }
void read_until(Reader* r, TokenType tt, const std::set<TokenType>& not_in, std::list<UExpression>& l) { while (r->current_token().type != tt) { if (r->current_token() == Token::EndOfFile) { throw ReaderException(std::string("EOF, expected ") + tokenTypeTranslations.at(tt)); } if (not_in.find(r->current_token().type) != not_in.end()) { throw ReaderException(std::string("Expected ") + tokenTypeTranslations.at(tt) + " got " + tokenTypeTranslations.at(r->current_token().type)); } l.push_back(std::move(r->next())); } }
int* Code39Reader::findAsteriskPattern(Ref<BitArray> row){ int width = row->getSize(); int rowOffset = 0; while (rowOffset < width) { if (row->get(rowOffset)) { break; } rowOffset++; } int counterPosition = 0; const int countersLen = 9; int counters[countersLen]; for (int i = 0; i < countersLen; i++) { counters[i] = 0; } int patternStart = rowOffset; bool isWhite = false; int patternLength = countersLen; for (int i = rowOffset; i < width; i++) { bool pixel = row->get(i); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (toNarrowWidePattern(counters, countersLen) == ASTERISK_ENCODING) { // Look for whitespace before start pattern, >= 50% of width of // start pattern. long double longPatternOffset = 0; #ifndef NOFMAXL longPatternOffset = fmax(0, patternStart - (i - patternStart) / 2); #else longPatternOffset = fmax(0, patternStart - (i - patternStart) / 2); #endif if (row->isRange(longPatternOffset, patternStart, false)) { int* resultValue = new int[2]; resultValue[0] = patternStart; resultValue[1] = i; 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 ReaderException(""); }
std::vector<Ref<Result> > QRCodeMultiReader::decodeMultiple(Ref<BinaryBitmap> image, DecodeHints hints) { std::vector<Ref<Result> > results; MultiDetector detector(image->getBlackMatrix()); std::vector<Ref<DetectorResult> > detectorResult = detector.detectMulti(hints); for (unsigned int i = 0; i < detectorResult.size(); i++) { try { Ref<DecoderResult> decoderResult = getDecoder().decode( detectorResult[i]->getBits()); ArrayRef<Ref<ResultPoint> > points = detectorResult[i]->getPoints(); Ref<Result> result = Ref<Result>(new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat::QR_CODE)); // result->putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult->getByteSegments()); // result->putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult->getECLevel().toString()); results.push_back(result); } catch (ReaderException const &re) { (void) re; // ignore and continue } } if (results.empty()) { throw ReaderException("No code detected"); } return results; }
int* Code128Reader::findStartPattern(Ref<BitArray> row){ int width = row->getSize(); int rowOffset = 0; while (rowOffset < width) { if (row->get(rowOffset)) { break; } rowOffset++; } int counterPosition = 0; int counters[countersLength] = {0,0,0,0,0,0}; int patternStart = rowOffset; bool isWhite = false; int patternLength = sizeof(counters) / sizeof(int); for (int i = rowOffset; i < width; i++) { bool pixel = row->get(i); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { unsigned int bestVariance = MAX_AVG_VARIANCE; int bestMatch = -1; for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) { unsigned int variance = patternMatchVariance(counters, sizeof(counters) / sizeof(int), CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = startCode; } } if (bestMatch >= 0) { // Look for whitespace before start pattern, >= 50% of width of start pattern if (row->isRange(fmaxl(0, patternStart - (i - patternStart) / 2), patternStart, false)) { int* resultValue = new int[3]; 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 ReaderException(""); }
char Code39Reader::patternToChar(int pattern){ for (int i = 0; i < CHARACTER_ENCODINGS_LEN; i++) { if (CHARACTER_ENCODINGS[i] == pattern) { return ALPHABET[i]; } } throw ReaderException(""); }
/// \brief Fonction de lecture du fichier d'adjacence /// \param g Matrice d'adjacence à remplir /// \throws ReaderException when an error occurs void File_reader::parse(Graph & g) { int retour = 0; int nbPoint = 0, i1, i2; bool line_error = false, found= false; edge_descriptor e; vertex_descriptor oldVertex_descriptor; std::string line, tempString, linkType; vertex_descriptor v,vv ; try { std::ifstream file(filename.c_str()); int oldVertex=0, vertexType=-1; int peersCount=0, clientsCount=0; if( file.is_open() ) { //remplissage de la matrice while(std::getline(file, line)) { // std::cout << "je lis la ligne" << file.tellg() << std::endl; std::istringstream lineStream(line); if(lineStream >> tempString) { std::istringstream in1(tempString); if(lineStream >> tempString) { std::istringstream in2(tempString); //Si tout rentre dans chacun des conteneurs... if(lineStream >> linkType && in1 >> i1 && in2 >> i2) { v = boost::vertex(i1,g); vv = boost::vertex(i2,g); vertexType=addEdge(v, vv, linkType, found, e, g); if(!found) { line_error=true; }else{ stubs_testing(peersCount, clientsCount, i1, oldVertex, vertexType, oldVertex_descriptor); oldVertex=i1; oldVertex_descriptor = v; } } else { line_error=true; } } } } if(peersCount == 0 && clientsCount == 0){ stubs_testing(peersCount, clientsCount, i1, oldVertex, vertexType, oldVertex_descriptor); } create_peers_graph(); file.close(); } else{ throw ReaderException("Fichier inexistant ou non lisible", filename,ReaderException::CRITICAL); } }
Ref<Result> UPCAReader::maybeReturnResult(Ref<Result> result) { const std::string& text = (result->getText())->getText(); if (text[0] == '0') { Ref<String> resultString(new String(text.substr(1))); Ref<Result> res(new Result(resultString, result->getRawBytes(), result->getResultPoints(), BarcodeFormat_UPC_A)); return res; } else { throw ReaderException("Not UPC-A barcode."); } }
std::vector<Ref<Result> > GenericMultipleBarcodeReader::decodeMultiple( Ref<BinaryBitmap> image, DecodeHints hints) { std::vector<Ref<Result> > results; doDecodeMultiple(image, hints, results, 0, 0); if (results.empty()){ throw ReaderException("No code detected"); } return results; }
Ref<Result> MultiFormatReader::decode(Ref<BinaryBitmap> image) { for (unsigned int i = 0; i < readers.size(); i++) { try { return readers[i]->decode(image); } catch (ReaderException re) { // continue } } throw ReaderException("No code detected"); }
BitMatrixParser::BitMatrixParser(Ref<BitMatrix> bitMatrix) : bitMatrix_(NULL), parsedVersion_(NULL), readBitMatrix_(NULL) { size_t dimension = bitMatrix->getDimension(); if (dimension < 8 || dimension > 144 || (dimension & 0x01) != 0) throw ReaderException("Dimension must be even, > 8 < 144"); parsedVersion_ = readVersion(bitMatrix); bitMatrix_ = extractDataRegion(bitMatrix); readBitMatrix_ = new BitMatrix(bitMatrix_->getWidth(), bitMatrix_->getHeight()); }
Ref<Version> BitMatrixParser::readVersion(Ref<BitMatrix> bitMatrix) { if (parsedVersion_ != 0) { return parsedVersion_; } int numRows = bitMatrix->getHeight();//getDimension(); int numColumns = bitMatrix->getWidth();//numRows; Ref<Version> version = parsedVersion_->getVersionForDimensions(numRows, numColumns); if (version != 0) { return version; } throw ReaderException("Couldn't decode version"); }
UExpression Map::create(Reader *r) { r->pop_token(); auto without_curly_close = without(closeTypes, TokenType::CurlyClose); std::list<UExpression> l; read_until(r, TokenType::CurlyClose, without_curly_close, l); if (l.size() % 2 == 1) { throw ReaderException("Map entries should be even"); } return make_unique<Map>(l); }
/** * Skip all whitespace until we get to the first black line. * * @param row row of black/white values to search * @return index of the first black line. * @throws ReaderException Throws exception if no black lines are found in the row */ int ITFReader::skipWhiteSpace(Ref<BitArray> row) { int width = (int)row->getSize(); int endStart = 0; while (endStart < width) { if (row->get(endStart)) { break; } endStart++; } if (endStart == width) { throw ReaderException(""); } return endStart; }
/** * Computes the UPC/EAN checksum on a string of digits, and reports * whether the checksum is correct or not. * * @param s string of digits to check * @return true iff string of digits passes the UPC/EAN checksum algorithm * @throws ReaderException if the string does not contain only digits */ bool UPCEANReader::checkStandardUPCEANChecksum(std::string s){ int length = s.length(); if (length == 0) { return false; } int sum = 0; for (int i = length - 2; i >= 0; i -= 2) { int digit = (int) s[i] - (int) '0'; if (digit < 0 || digit > 9) { throw ReaderException("checkStandardUPCEANChecksum"); } sum += digit; } sum *= 3; for (int i = length - 1; i >= 0; i -= 2) { int digit = (int) s[i] - (int) '0'; if (digit < 0 || digit > 9) { throw ReaderException("checkStandardUPCEANChecksum"); } sum += digit; } return sum % 10 == 0; }
int* UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst, const int pattern[], int patternLen){ int patternLength = patternLen; int counters[patternLength]; int countersCount = sizeof(counters)/sizeof(int); for (int i=0; i<countersCount ; i++) { counters[i]=0; } int width = row->getSize(); bool isWhite = false; while (rowOffset < width) { isWhite = !row->get(rowOffset); if (whiteFirst == isWhite) { break; } rowOffset++; } int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { bool pixel = row->get(x); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (patternMatchVariance(counters, countersCount, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { int* resultValue = new int[2]; resultValue[0] = patternStart; resultValue[1] = x; 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 ReaderException("findGuardPattern"); }
// int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset, int** patterns/*[][]*/, int paterns1Len, int paterns2Len) int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset, UPC_EAN_PATTERNS patternType){ recordPattern(row, rowOffset, counters, countersLen); unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; int max = 0; switch (patternType) { case UPC_EAN_PATTERNS_L_PATTERNS: max = L_PATTERNS_LEN; for (int i = 0; i < max; i++) { int pattern[countersLen]; for(int j = 0; j< countersLen; j++){ pattern[j] = L_PATTERNS[i][j]; } unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = i; } } break; case UPC_EAN_PATTERNS_L_AND_G_PATTERNS: max = L_AND_G_PATTERNS_LEN; for (int i = 0; i < max; i++) { int pattern[countersLen]; for(int j = 0; j< countersLen; j++){ pattern[j] = L_AND_G_PATTERNS[i][j]; } unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = i; } } break; default: break; } if (bestMatch >= 0) { return bestMatch; } else { throw ReaderException("UPCEANReader::decodeDigit: No best mach"); } }
UExpression Reader::next() { if (cur_tok == Token::EndOfFile) { return std::move(m_end); } if (Keyword::accepts(cur_tok)) { ret(Keyword::create(this)); } else if (Integer::accepts(cur_tok)) { ret(Integer::create(this)); } else if (Float::accepts(cur_tok)) { ret(Float::create(this)); } else if (Ratio::accepts(cur_tok)) { ret(Ratio::create(this)); } else if (Literal::accepts(cur_tok)) { ret(Literal::create(this)); } else if (List::accepts(cur_tok)) { ret(List::create(this)); } else if (Map::accepts(cur_tok)) { ret(Map::create(this)); } else if (Set::accepts(cur_tok)) { ret(Set::create(this)); } else if (String::accepts(cur_tok)) { ret(String::create(this)); } else if (Vector::accepts(cur_tok)) { ret(Vector::create(this)); } else if (closeTypes.find(cur_tok.type) != closeTypes.end()) { throw ReaderException("Closing tag without open"); } else { //throw ReaderException(); } cur_tok = tokenizer->next(); return std::move(current); }
/** * @param row row of black/white values to search * @param rowOffset position to start search * @param pattern pattern of counts of number of black and white pixels that are * being searched for as a pattern * @return start/end horizontal offset of guard pattern, as an array of two * ints * @throws ReaderException if pattern is not found */ int* ITFReader::findGuardPattern(Ref<BitArray> row, int rowOffset, const int pattern[], int patternLen) { // TODO: This is very similar to implementation in UPCEANReader. Consider if they can be // merged to a single method. int patternLength = patternLen; int counters[patternLength]; for (int i=0; i<patternLength; i++) { counters[i] = 0; } int width = (int)row->getSize(); bool isWhite = false; int counterPosition = 0; int patternStart = rowOffset; for (int x = rowOffset; x < width; x++) { bool pixel = row->get(x); if (pixel ^ isWhite) { counters[counterPosition]++; } else { if (counterPosition == patternLength - 1) { if (patternMatchVariance(counters, patternLength, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { int* resultValue = new int[2]; resultValue[0] = patternStart; resultValue[1] = x; 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 ReaderException(""); }
std::string Tokenizer::slurp_until(const char c) { std::string result; while (scanner->current_char()) { result += *scanner->current_char(); if (scanner->next_char() && !is_next(c)) { scanner->pop(); } else { break; } } if (!scanner->next_char()) { throw ReaderException("Unexpected stream end"); } return result; }
/** * Attempts to decode a sequence of ITF black/white lines into single * digit. * * @param counters the counts of runs of observed black/white/black/... values * @return The decoded digit * @throws ReaderException if digit cannot be decoded */ int ITFReader::decodeDigit(int counters[], int countersLen){ unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept int bestMatch = -1; int max = PATTERNS_LEN; for (int i = 0; i < max; i++) { int pattern[countersLen]; for(int ind = 0; ind<countersLen; ind++){ pattern[ind] = PATTERNS[i][ind]; } unsigned int variance = patternMatchVariance(counters, countersLen, pattern, MAX_INDIVIDUAL_VARIANCE); if (variance < bestVariance) { bestVariance = variance; bestMatch = i; } } if (bestMatch >= 0) { return bestMatch; } else { throw ReaderException("digit didint found"); } }
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardRange[]){ std::string tmpResultString; std::string& tmpResultStringRef = tmpResultString; int endStart; try { endStart = decodeMiddle(row, startGuardRange, 2 /*reference findGuardPattern*/ , tmpResultStringRef); } catch (ReaderException re) { if (startGuardRange!=NULL) { delete [] startGuardRange; startGuardRange = NULL; } throw re; } int* endRange = decodeEnd(row, endStart); #pragma mark QuietZone needs some change // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The // spec might want more whitespace, but in practice this is the maximum we can count on. // int end = endRange[1]; // int quietEnd = end + (end - endRange[0]); // if (quietEnd >= row->getSize() || !row->isRange(end, quietEnd, false)) { // throw ReaderException("Quiet zone asserrt fail."); // } if (!checkChecksum(tmpResultString)) { if (startGuardRange!=NULL) { delete [] startGuardRange; startGuardRange = NULL; } if (endRange!=NULL) { delete [] endRange; endRange = NULL; } throw ReaderException("Checksum fail."); } Ref<String> resultString(new String(tmpResultString)); float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f; float right = (float) (endRange[1] + endRange[0]) / 2.0f; std::vector< Ref<ResultPoint> > resultPoints(2); Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber)); Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber)); resultPoints[0] = resultPoint1; resultPoints[1] = resultPoint2; ArrayRef<unsigned char> resultBytes(1); if (startGuardRange!=NULL) { delete [] startGuardRange; startGuardRange = NULL; } if (endRange!=NULL) { delete [] endRange; endRange = NULL; } Ref<Result> res(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat())); return res; }
UExpression Integer::create(Reader *r) { /* regex breaks first number after [+-], so we check for it and remove it*/ bool negate = false; std::string input = r->current_token().value; if (sign_start.find(input.at(0)) != sign_start.end()) { if (input.find("-") == 0) { negate = true; } input = input.substr(1); } boost::smatch match; boost::regex_match(input, match, int_pattern); //bool negate = (n.matched && std::string(n.first, n.second).compare("-") == 0); if(match[3].matched) { if(match[9].matched) { // not yet bigint thingies. return make_unique<Integer>(0); } return make_unique<Integer>(0); } auto n = match[1]; int group = 0; int radix = 10; if(match[4].matched) { radix = 10; group = 4; } else if(match[5].matched) { radix = 16; group = 5; } else if(match[6].matched) { radix = 8; group = 6; } else if(match[8].matched) { auto r = match[7]; radix = std::stoi(std::string(r.first, r.second)); group = 8; } if(group == 0) { throw ReaderException("Invalid integer"); } auto m = match[group]; //std::cout << m.length() << " INT! " << group << " : [" << std::string(m.first, m.second) << "] : " << radix << std::endl; long value = std::stol(std::string(m.first, m.second), nullptr, radix); if(negate) { value = -value; } // if(match[9].matched) { // // bigint not supported // } return make_unique<Integer>(value); }
Ref<Result> Code128Reader::decodeRow(int rowNumber, Ref<BitArray> row) { int* startPatternInfo = NULL; try { 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 ReaderException(""); } bool done = false; bool isNextShifted = false; std::string tmpResultString; std::stringstream tmpResultSStr; // used if its Code 128C int lastStart = startPatternInfo[0]; int nextStart = startPatternInfo[1]; int counters[countersLength] = {0,0,0,0,0,0}; int lastCode = 0; int code = 0; int checksumTotal = startCode; int multiplier = 0; bool lastCharacterWasPrintable = true; while (!done) { bool unshift = isNextShifted; isNextShifted = false; // Save off last code lastCode = code; // Decode another code from image try { code = decodeCode(row, counters, sizeof(counters)/sizeof(int), nextStart); } catch (ReaderException const& re) { throw re; } // 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; int _countersLength = sizeof(counters) / sizeof(int); for (int i = 0; i < _countersLength; 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 ReaderException(""); } switch (codeSet) { case CODE_CODE_A: if (code < 64) { tmpResultString.append(1, (char) (' ' + code)); } else if (code < 96) { tmpResultString.append(1, (char) (code - 64)); } 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: case CODE_FNC_2: case CODE_FNC_3: case CODE_FNC_4_A: // do nothing? 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) { tmpResultString.append(1, (char) (' ' + code)); } else { if (code != CODE_STOP) { lastCharacterWasPrintable = false; } switch (code) { case CODE_FNC_1: case CODE_FNC_2: case CODE_FNC_3: case CODE_FNC_4_B: // do nothing? break; case CODE_SHIFT: isNextShifted = true; codeSet = CODE_CODE_C; 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: tmpResultSStr.str(std::string()); // the code read in this case is the number encoded directly if (code < 100) { if (code < 10) { tmpResultSStr << '0'; } tmpResultSStr << code; tmpResultString.append(tmpResultSStr.str()); } else { if (code != CODE_STOP) { lastCharacterWasPrintable = false; } switch (code) { case CODE_FNC_1: // do nothing? 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) { switch (codeSet) { case CODE_CODE_A: codeSet = CODE_CODE_C; break; case CODE_CODE_B: codeSet = CODE_CODE_A; break; case CODE_CODE_C: codeSet = CODE_CODE_B; break; } } } // 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: int width = row->getSize(); while (nextStart < width && row->get(nextStart)) { nextStart++; } long minResult = 0; #ifndef NOFMAXL minResult = fminl(width, nextStart + (nextStart - lastStart)/ 2); #else minResult = fmin(width, nextStart + (nextStart - lastStart)/ 2); #endif if (!row->isRange(nextStart, minResult, false)) { throw ReaderException(""); } // Pull out from sum the value of the penultimate check code checksumTotal -= multiplier * lastCode; // lastCode is the checksum then: if (checksumTotal % 103 != lastCode) { throw ReaderException(""); } // Need to pull out the check digits from string int resultLength = tmpResultString.length(); // 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) { tmpResultString.erase(resultLength - 2, resultLength); } else { tmpResultString.erase(resultLength - 1, resultLength); } } Ref<String> resultString(new String(tmpResultString)); if (tmpResultString.length() == 0) { // Almost surely a false positive throw ReaderException(""); } float left = (float) (startPatternInfo[1] + startPatternInfo[0]) / 2.0f; float right = (float) (nextStart + lastStart) / 2.0f; std::vector< Ref<ResultPoint> > resultPoints(2); Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber)); Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber)); resultPoints[0] = resultPoint1; resultPoints[1] = resultPoint2; delete [] startPatternInfo; ArrayRef<unsigned char> resultBytes(1); return Ref<Result>(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_CODE_128)); } catch (ReaderException const& re) { delete [] startPatternInfo; return Ref<Result>(); } }
ArrayRef<unsigned char> BitMatrixParser::readCodewords() { ArrayRef<unsigned char> result(parsedVersion_->getTotalCodewords()); int resultOffset = 0; int row = 4; int column = 0; int numRows = bitMatrix_->getHeight(); int numColumns = bitMatrix_->getWidth(); bool corner1Read = false; bool corner2Read = false; bool corner3Read = false; bool corner4Read = false; // Read all of the codewords do { // Check the four corner cases if ((row == numRows) && (column == 0) && !corner1Read) { result[resultOffset++] = (unsigned char) readCorner1(numRows, numColumns); row -= 2; column +=2; corner1Read = true; } else if ((row == numRows-2) && (column == 0) && ((numColumns & 0x03) != 0) && !corner2Read) { result[resultOffset++] = (unsigned char) readCorner2(numRows, numColumns); row -= 2; column +=2; corner2Read = true; } else if ((row == numRows+4) && (column == 2) && ((numColumns & 0x07) == 0) && !corner3Read) { result[resultOffset++] = (unsigned char) readCorner3(numRows, numColumns); row -= 2; column +=2; corner3Read = true; } else if ((row == numRows-2) && (column == 0) && ((numColumns & 0x07) == 4) && !corner4Read) { result[resultOffset++] = (unsigned char) readCorner4(numRows, numColumns); row -= 2; column +=2; corner4Read = true; } else { // Sweep upward diagonally to the right do { if ((row < numRows) && (column >= 0) && !readBitMatrix_->get(column, row)) { result[resultOffset++] = (unsigned char) readUtah(row, column, numRows, numColumns); } row -= 2; column +=2; } while ((row >= 0) && (column < numColumns)); row += 1; column +=3; // Sweep downward diagonally to the left do { if ((row >= 0) && (column < numColumns) && !readBitMatrix_->get(column, row)) { result[resultOffset++] = (unsigned char) readUtah(row, column, numRows, numColumns); } row += 2; column -=2; } while ((row < numRows) && (column >= 0)); row += 3; column +=1; } } while ((row < numRows) || (column < numColumns)); if (resultOffset != parsedVersion_->getTotalCodewords()) { throw ReaderException("Did not read all codewords"); } return result; }
ErrorCorrectionLevel& ErrorCorrectionLevel::forBits(int bits) { if (bits < 0 || bits >= N_LEVELS) { throw ReaderException("Ellegal error correction level bits"); } return *FOR_BITS[bits]; }
Ref<Result> Code39Reader::decodeRow(int rowNumber, Ref<BitArray> row) { int* start = NULL; try { start = findAsteriskPattern(row); int nextStart = start[1]; int end = row->getSize(); // Read off white space while (nextStart < end && !row->get(nextStart)) { nextStart++; } std::string tmpResultString; const int countersLen = 9; int counters[countersLen]; for (int i = 0; i < countersLen; i++) { counters[i] = 0; } char decodedChar; int lastStart; do { if (!recordPattern(row, nextStart, counters, countersLen)) { throw ReaderException(""); } int pattern = toNarrowWidePattern(counters, countersLen); if (pattern < 0) { throw ReaderException("pattern < 0"); } decodedChar = patternToChar(pattern); tmpResultString.append(1, decodedChar); lastStart = nextStart; for (int i = 0; i < countersLen; i++) { nextStart += counters[i]; } // Read off white space while (nextStart < end && !row->get(nextStart)) { nextStart++; } } while (decodedChar != '*'); tmpResultString.erase(tmpResultString.length()-1, 1);// remove asterisk // Look for whitespace after pattern: int lastPatternSize = 0; for (int i = 0; i < countersLen; i++) { lastPatternSize += counters[i]; } int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize; // If 50% of last pattern size, following last pattern, is not whitespace, // fail (but if it's whitespace to the very end of the image, that's OK) if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) { throw ReaderException("too short end white space"); } if (usingCheckDigit) { int max = tmpResultString.length() - 1; unsigned int total = 0; for (int i = 0; i < max; i++) { total += alphabet_string.find_first_of(tmpResultString[i], 0); } if (total % 43 != alphabet_string.find_first_of(tmpResultString[max], 0)) { throw ReaderException(""); } tmpResultString.erase(max, 1); } Ref<String> resultString(new String(tmpResultString)); if (extendedMode) { resultString = decodeExtended(tmpResultString); } if (tmpResultString.length() == 0) { // Almost surely a false positive throw ReaderException(""); } float left = (float) (start[1] + start[0]) / 2.0f; float right = (float) (nextStart + lastStart) / 2.0f; std::vector< Ref<ResultPoint> > resultPoints(2); Ref<OneDResultPoint> resultPoint1( new OneDResultPoint(left, (float) rowNumber)); Ref<OneDResultPoint> resultPoint2( new OneDResultPoint(right, (float) rowNumber)); resultPoints[0] = resultPoint1; resultPoints[1] = resultPoint2; ArrayRef<unsigned char> resultBytes(1); Ref<Result> res(new Result( resultString, resultBytes, resultPoints, BarcodeFormat_CODE_39)); delete [] start; return res; } catch (ReaderException const& re) { delete [] start; return Ref<Result>(); } }