private static void checkOneChecksum(CharSequence result, int checkPosition, int weightMax) throws ChecksumException { int weight = 1; int total = 0; for (int i = checkPosition - 1; i >= 0; i--) { total += weight * ALPHABET_STRING.indexOf(result.charAt(i)); if (++weight > weightMax) { weight = 1; } } if (result.charAt(checkPosition) != ALPHABET[total % 47]) { throw ChecksumException.getChecksumInstance(); } }
/** * Given data and error-correction codewords received, possibly corrupted by errors, attempts to * correct the errors in-place using Reed-Solomon error correction. * * @param codewordBytes data and error correction codewords * @param numDataCodewords number of codewords that are data bytes * @throws ChecksumException if error correction fails */ private void correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException { int numCodewords = codewordBytes.length; // First read into an array of ints int[] codewordsInts = new int[numCodewords]; for (int i = 0; i < numCodewords; i++) { codewordsInts[i] = codewordBytes[i] & 0xFF; } try { rsDecoder.decode(codewordsInts, codewordBytes.length - numDataCodewords); } catch (ReedSolomonException ignored) { throw ChecksumException.getChecksumInstance(); } // 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 < numDataCodewords; i++) { codewordBytes[i] = (byte) codewordsInts[i]; } }
@Override public Result decodeRow(int rowNumber, BitArray row, Map<DecodeHintType, ?> hints) throws NotFoundException, ChecksumException, FormatException { int[] counters = new int[9]; int[] start = findAsteriskPattern(row, counters); // Read off white space int nextStart = row.getNextSet(start[1]); int end = row.getSize(); StringBuilder result = new StringBuilder(20); char decodedChar; int lastStart; do { recordPattern(row, nextStart, counters); int pattern = toNarrowWidePattern(counters); if (pattern < 0) { throw NotFoundException.getNotFoundInstance(); } decodedChar = patternToChar(pattern); result.append(decodedChar); lastStart = nextStart; for (int counter : counters) { nextStart += counter; } // Read off white space nextStart = row.getNextSet(nextStart); } while (decodedChar != '*'); result.setLength(result.length() - 1); // remove asterisk // Look for whitespace after pattern: int lastPatternSize = 0; for (int counter : counters) { lastPatternSize += counter; } 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 >> 1) < lastPatternSize) { throw NotFoundException.getNotFoundInstance(); } if (usingCheckDigit) { int max = result.length() - 1; int total = 0; for (int i = 0; i < max; i++) { total += ALPHABET_STRING.indexOf(result.charAt(i)); } if (result.charAt(max) != ALPHABET[total % 43]) { throw ChecksumException.getChecksumInstance(); } result.setLength(max); } if (result.length() == 0) { // false positive throw NotFoundException.getNotFoundInstance(); } String resultString; if (extendedMode) { resultString = decodeExtended(result); } else { resultString = result.toString(); } float left = (float) (start[1] + start[0]) / 2.0f; float right = (float) (nextStart + lastStart) / 2.0f; return new Result( resultString, null, new ResultPoint[] { new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber) }, BarcodeFormat.CODE_39); }