Preliminary RSS-14 support. Not enabled yet in Android client.

git-svn-id: https://zxing.googlecode.com/svn/trunk@1233 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2010-03-04 18:38:58 +00:00
parent 4f072f67ee
commit 0cf89d0402
69 changed files with 931 additions and 3 deletions

View file

@ -107,7 +107,7 @@ public final class CaptureActivity extends Activity implements SurfaceHolder.Cal
PRODUCT_FORMATS.add(BarcodeFormat.UPC_E);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_13);
PRODUCT_FORMATS.add(BarcodeFormat.EAN_8);
PRODUCT_FORMATS.add(BarcodeFormat.RSS14);
//PRODUCT_FORMATS.add(BarcodeFormat.RSS14);
ONE_D_FORMATS = new Vector<BarcodeFormat>(PRODUCT_FORMATS.size() + 3);
ONE_D_FORMATS.addAll(PRODUCT_FORMATS);
ONE_D_FORMATS.add(BarcodeFormat.CODE_39);

View file

@ -23,6 +23,7 @@ import com.google.zxing.Reader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.BitArray;
import com.google.zxing.oned.rss.RSS14Reader;
import java.util.Hashtable;
import java.util.Vector;
@ -58,7 +59,7 @@ public final class MultiFormatOneDReader extends OneDReader {
readers.addElement(new ITFReader());
}
if (possibleFormats.contains(BarcodeFormat.RSS14)) {
// TODO enable later readers.addElement(new RSS14Reader());
readers.addElement(new RSS14Reader());
}
}
if (readers.isEmpty()) {
@ -66,7 +67,7 @@ public final class MultiFormatOneDReader extends OneDReader {
readers.addElement(new Code39Reader());
readers.addElement(new Code128Reader());
readers.addElement(new ITFReader());
// TODO enable later readers.addElement(new RSS14Reader());
readers.addElement(new RSS14Reader());
}
}

View file

@ -0,0 +1,37 @@
/*
* Copyright 2009 ZXing authors
*
* 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.
*/
package com.google.zxing.oned.rss;
class DataCharacter {
private final int value;
private final int checksumPortion;
DataCharacter(int value, int checksumPortion) {
this.value = value;
this.checksumPortion = checksumPortion;
}
int getValue() {
return value;
}
int getChecksumPortion() {
return checksumPortion;
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright 2009 ZXing authors
*
* 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.
*/
package com.google.zxing.oned.rss;
import com.google.zxing.ResultPoint;
final class FinderPattern {
private final int value;
private final int[] startEnd;
private final ResultPoint[] resultPoints;
FinderPattern(int value, int[] startEnd, int start, int end, int rowNumber) {
this.value = value;
this.startEnd = startEnd;
this.resultPoints = new ResultPoint[] {
new ResultPoint((float) start, (float) rowNumber),
new ResultPoint((float) end, (float) rowNumber),
};
}
int getValue() {
return value;
}
int[] getStartEnd() {
return startEnd;
}
ResultPoint[] getResultPoints() {
return resultPoints;
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright 2009 ZXing authors
*
* 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.
*/
package com.google.zxing.oned.rss;
final class Pair extends DataCharacter {
private final FinderPattern finderPattern;
Pair(int value, int checksumPortion, FinderPattern finderPattern) {
super(value, checksumPortion);
this.finderPattern = finderPattern;
}
FinderPattern getFinderPattern() {
return finderPattern;
}
}

View file

@ -0,0 +1,557 @@
/*
* Copyright 2009 ZXing authors
*
* 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.
*/
package com.google.zxing.oned.rss;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.ResultPointCallback;
import com.google.zxing.common.BitArray;
import com.google.zxing.oned.OneDReader;
import java.util.Hashtable;
import java.util.Vector;
/**
* Decodes RSS-14, including truncated and stacked variants. See ISO/IEC 24724:2006.
*/
public final class RSS14Reader extends OneDReader {
private static final int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.2f);
private static final int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.4f);
private static final float MIN_FINDER_PATTERN_RATIO = 9.5f / 12.0f;
private static final float MAX_FINDER_PATTERN_RATIO = 12.5f / 14.0f;
private static final int[] OUTSIDE_EVEN_TOTAL_SUBSET = {1,10,34,70,126};
private static final int[] INSIDE_ODD_TOTAL_SUBSET = {4,20,48,81};
private static final int[] OUTSIDE_GSUM = {0,161,961,2015,2715};
private static final int[] INSIDE_GSUM = {0,336,1036,1516};
private static final int[] OUTSIDE_ODD_WIDEST = {8,6,4,3,1};
private static final int[] INSIDE_ODD_WIDEST = {2,4,6,8};
private static final int[][] FINDER_PATTERNS = {
{3,8,2,1},
{3,5,5,1},
{3,3,7,1},
{3,1,9,1},
{2,7,4,1},
{2,5,6,1},
{2,3,8,1},
{1,5,7,1},
{1,3,9,1},
};
private final int[] decodeFinderCounters;
private final int[] dataCharacterCounters;
private final float[] oddRoundingErrors;
private final float[] evenRoundingErrors;
private final int[] oddCounts;
private final int[] evenCounts;
private final Vector possibleLeftPairs;
private final Vector possibleRightPairs;
public RSS14Reader() {
decodeFinderCounters = new int[4];
dataCharacterCounters = new int[8];
oddRoundingErrors = new float[4];
evenRoundingErrors = new float[4];
oddCounts = new int[dataCharacterCounters.length / 2];
evenCounts = new int[dataCharacterCounters.length / 2];
possibleLeftPairs = new Vector();
possibleRightPairs = new Vector();
}
public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws NotFoundException {
Pair leftPair = decodePair(row, false, rowNumber, hints);
if (leftPair != null) {
possibleLeftPairs.add(leftPair);
}
row.reverse();
Pair rightPair = decodePair(row, true, rowNumber, hints);
if (rightPair != null) {
possibleRightPairs.add(rightPair);
}
row.reverse();
int numLeftPairs = possibleLeftPairs.size();
int numRightPairs = possibleRightPairs.size();
for (int l = 0; l < numLeftPairs; l++) {
Pair left = (Pair) possibleLeftPairs.elementAt(l);
for (int r = 0; r < numRightPairs; r++) {
Pair right = (Pair) possibleRightPairs.elementAt(r);
if (checkChecksum(left, right)) {
return constructResult(left, right);
}
}
}
throw NotFoundException.getNotFoundInstance();
}
public void reset() {
possibleLeftPairs.clear();
possibleRightPairs.clear();
}
private static Result constructResult(Pair leftPair, Pair rightPair) {
long symbolValue = 4537077L * leftPair.getValue() + rightPair.getValue();
String text = String.valueOf(symbolValue);
StringBuffer buffer = new StringBuffer(14);
for (int i = 13 - text.length(); i > 0; i--) {
buffer.append('0');
}
buffer.append(text);
int checkDigit = 0;
for (int i = 0; i < 13; i++) {
int digit = buffer.charAt(i) - '0';
checkDigit += (((i & 0x01) == 0) ? 3 * digit : digit);
}
checkDigit = 10 - (checkDigit % 10);
if (checkDigit == 10) {
checkDigit = 0;
}
buffer.append(checkDigit);
ResultPoint[] leftPoints = leftPair.getFinderPattern().getResultPoints();
ResultPoint[] rightPoints = rightPair.getFinderPattern().getResultPoints();
return new Result(
String.valueOf(buffer.toString()),
null,
new ResultPoint[] { leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1], },
BarcodeFormat.RSS14);
}
private static boolean checkChecksum(Pair leftPair, Pair rightPair) {
int leftFPValue = leftPair.getFinderPattern().getValue();
int rightFPValue = rightPair.getFinderPattern().getValue();
if ((leftFPValue == 0 && rightFPValue == 8) ||
(leftFPValue == 8 && rightFPValue == 0)) {
}
int checkValue = (leftPair.getChecksumPortion() + 16 * rightPair.getChecksumPortion()) % 79;
int targetCheckValue =
9 * leftPair.getFinderPattern().getValue() + rightPair.getFinderPattern().getValue();
if (targetCheckValue > 72) {
targetCheckValue--;
}
if (targetCheckValue > 8) {
targetCheckValue--;
}
return checkValue == targetCheckValue;
}
private Pair decodePair(BitArray row, boolean right, int rowNumber, Hashtable hints) {
try {
int[] startEnd = findFinderPattern(row, 0, right);
FinderPattern pattern = parseFoundFinderPattern(row, rowNumber, right, startEnd);
ResultPointCallback resultPointCallback = hints == null ? null :
(ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
if (resultPointCallback != null) {
float center = (startEnd[0] + startEnd[1]) / 2.0f;
if (right) {
// row is actually reversed
center = row.getSize() - 1 - center;
}
resultPointCallback.foundPossibleResultPoint(new ResultPoint(center, rowNumber));
}
DataCharacter outside = decodeDataCharacter(row, pattern, true);
DataCharacter inside = decodeDataCharacter(row, pattern, false);
return new Pair(1597 * outside.getValue() + inside.getValue(),
outside.getChecksumPortion() + 4 * inside.getChecksumPortion(),
pattern);
} catch (NotFoundException re) {
return null;
}
}
private DataCharacter decodeDataCharacter(BitArray row, FinderPattern pattern, boolean outsideChar)
throws NotFoundException {
int[] counters = dataCharacterCounters;
counters[0] = 0;
counters[1] = 0;
counters[2] = 0;
counters[3] = 0;
counters[4] = 0;
counters[5] = 0;
counters[6] = 0;
counters[7] = 0;
if (outsideChar) {
recordPatternInReverse(row, pattern.getStartEnd()[0], counters);
} else {
recordPattern(row, pattern.getStartEnd()[1] + 1, counters);
// reverse it
for (int i = 0, j = counters.length - 1; i < j; i++, j--) {
int temp = counters[i];
counters[i] = counters[j];
counters[j] = temp;
}
}
int numModules = outsideChar ? 16 : 15;
float elementWidth = (float) count(counters) / (float) numModules;
int[] oddCounts = this.oddCounts;
int[] evenCounts = this.evenCounts;
float[] oddRoundingErrors = this.oddRoundingErrors;
float[] evenRoundingErrors = this.evenRoundingErrors;
for (int i = 0; i < counters.length; i++) {
float value = (float) counters[i] / elementWidth;
int count = (int) (value + 0.5f); // Round
if (count < 1) {
count = 1;
} else if (count > 8) {
count = 8;
}
int offset = i >> 1;
if ((i & 0x01) == 0) {
oddCounts[offset] = count;
oddRoundingErrors[offset] = value - count;
} else {
evenCounts[offset] = count;
evenRoundingErrors[offset] = value - count;
}
}
adjustOddEvenCounts(outsideChar, numModules);
int oddSum = 0;
int oddChecksumPortion = 0;
for (int i = oddCounts.length - 1; i >= 0; i--) {
oddChecksumPortion *= 9;
oddChecksumPortion += oddCounts[i];
oddSum += oddCounts[i];
}
int evenChecksumPortion = 0;
int evenSum = 0;
for (int i = evenCounts.length - 1; i >= 0; i--) {
evenChecksumPortion *= 9;
evenChecksumPortion += evenCounts[i];
evenSum += evenCounts[i];
}
int checksumPortion = oddChecksumPortion + 3*evenChecksumPortion;
if (outsideChar) {
if ((oddSum & 0x01) != 0 || oddSum > 12 || oddSum < 4) {
throw NotFoundException.getNotFoundInstance();
}
int group = (12 - oddSum) / 2;
int oddWidest = OUTSIDE_ODD_WIDEST[group];
int evenWidest = 9 - oddWidest;
int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false);
int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true);
int tEven = OUTSIDE_EVEN_TOTAL_SUBSET[group];
int gSum = OUTSIDE_GSUM[group];
return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion);
} else {
if ((evenSum & 0x01) != 0 || evenSum > 10 || evenSum < 4) {
throw NotFoundException.getNotFoundInstance();
}
int group = (10 - evenSum) / 2;
int oddWidest = INSIDE_ODD_WIDEST[group];
int evenWidest = 9 - oddWidest;
int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);
int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);
int tOdd = INSIDE_ODD_TOTAL_SUBSET[group];
int gSum = INSIDE_GSUM[group];
return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion);
}
}
private int[] findFinderPattern(BitArray row, int rowOffset, boolean rightFinderPattern)
throws NotFoundException {
int[] counters = decodeFinderCounters;
counters[0] = 0;
counters[1] = 0;
counters[2] = 0;
counters[3] = 0;
int width = row.getSize();
boolean isWhite = false;
while (rowOffset < width) {
isWhite = !row.get(rowOffset);
if (rightFinderPattern == isWhite) {
// Will encounter white first when searching for right finder pattern
break;
}
rowOffset++;
}
int counterPosition = 0;
int patternStart = rowOffset;
for (int x = rowOffset; x < width; x++) {
boolean pixel = row.get(x);
if (pixel ^ isWhite) {
counters[counterPosition]++;
} else {
if (counterPosition == 3) {
if (isFinderPattern(counters)) {
return new int[]{patternStart, x};
}
patternStart += counters[0] + counters[1];
counters[0] = counters[2];
counters[1] = counters[3];
counters[2] = 0;
counters[3] = 0;
counterPosition--;
} else {
counterPosition++;
}
counters[counterPosition] = 1;
isWhite = !isWhite;
}
}
throw NotFoundException.getNotFoundInstance();
}
private static boolean isFinderPattern(int[] counters) {
int firstTwoSum = counters[0] + counters[1];
int sum = firstTwoSum + counters[2] + counters[3];
float ratio = (float) firstTwoSum / (float) sum;
if (ratio >= MIN_FINDER_PATTERN_RATIO && ratio <= MAX_FINDER_PATTERN_RATIO) {
// passes ratio test in spec, but see if the counts are unreasonable
int minCounter = Integer.MAX_VALUE;
int maxCounter = Integer.MIN_VALUE;
for (int i = 0; i < counters.length; i++) {
int counter = counters[i];
if (counter > maxCounter) {
maxCounter = counter;
}
if (counter < minCounter) {
minCounter = counter;
}
}
return maxCounter < 10 * minCounter;
}
return false;
}
private FinderPattern parseFoundFinderPattern(BitArray row, int rowNumber, boolean right, int[] startEnd)
throws NotFoundException {
// Actually we found elements 2-5
boolean firstIsBlack = row.get(startEnd[0]);
int firstElementStart = startEnd[0] - 1;
// Locate element 1
while (firstElementStart >= 0 && firstIsBlack ^ row.get(firstElementStart)) {
firstElementStart--;
}
firstElementStart++;
int firstCounter = startEnd[0] - firstElementStart;
// Make 'counters' hold 1-4
int[] counters = decodeFinderCounters;
for (int i = counters.length - 1; i > 0; i--) {
counters[i] = counters[i-1];
}
counters[0] = firstCounter;
int value = parseFinderValue(counters);
int start = firstElementStart;
int end = startEnd[1];
if (right) {
// row is actually reversed
start = row.getSize() - 1 - start;
end = row.getSize() - 1 - end;
}
return new FinderPattern(value, new int[] {firstElementStart, startEnd[1]}, start, end, rowNumber);
}
private static int parseFinderValue(int[] counters) throws NotFoundException {
for (int value = 0; value < FINDER_PATTERNS.length; value++) {
if (patternMatchVariance(counters, FINDER_PATTERNS[value], MAX_INDIVIDUAL_VARIANCE) <
MAX_AVG_VARIANCE) {
return value;
}
}
throw NotFoundException.getNotFoundInstance();
}
/*
private static int[] normalizeE2SEValues(int[] counters) {
int p = 0;
for (int i = 0; i < counters.length; i++) {
p += counters[i];
}
int[] normalized = new int[counters.length - 2];
for (int i = 0; i < normalized.length; i++) {
int e = counters[i] + counters[i+1];
float eRatio = (float) e / (float) p;
float E = ((eRatio * 32.0f) + 1.0f) / 2.0f;
normalized[i] = (int) E;
}
return normalized;
}
*/
private static int count(int[] array) {
int count = 0;
for (int i = 0; i < array.length; i++) {
count += array[i];
}
return count;
}
private static void increment(int[] array, float[] errors) {
int index = 0;
float biggestError = errors[0];
for (int i = 1; i < array.length; i++) {
if (errors[i] > biggestError) {
biggestError = errors[i];
index = i;
}
}
array[index]++;
}
private static void decrement(int[] array, float[] errors) {
int index = 0;
float biggestError = errors[0];
for (int i = 1; i < array.length; i++) {
if (errors[i] < biggestError) {
biggestError = errors[i];
index = i;
}
}
array[index]--;
}
private void adjustOddEvenCounts(boolean outsideChar, int numModules) throws NotFoundException {
int oddSum = count(oddCounts);
int evenSum = count(evenCounts);
int mismatch = oddSum + evenSum - numModules;
boolean oddParityBad = (oddSum & 0x01) == (outsideChar ? 1 : 0);
boolean evenParityBad = (evenSum & 0x01) == 1;
boolean incrementOdd = false;
boolean decrementOdd = false;
boolean incrementEven = false;
boolean decrementEven = false;
if (outsideChar) {
if (oddSum > 12) {
decrementOdd = true;
} else if (oddSum < 4) {
incrementOdd = true;
}
if (evenSum > 12) {
decrementEven = true;
} else if (evenSum < 4) {
incrementEven = true;
}
} else {
if (oddSum > 11) {
decrementOdd = true;
} else if (oddSum < 5) {
incrementOdd = true;
}
if (evenSum > 10) {
decrementEven = true;
} else if (evenSum < 4) {
incrementEven = true;
}
}
/*if (mismatch == 2) {
if (!(oddParityBad && evenParityBad)) {
throw ReaderException.getInstance();
}
decrementOdd = true;
decrementEven = true;
} else if (mismatch == -2) {
if (!(oddParityBad && evenParityBad)) {
throw ReaderException.getInstance();
}
incrementOdd = true;
incrementEven = true;
} else */if (mismatch == 1) {
if (oddParityBad) {
if (evenParityBad) {
throw NotFoundException.getNotFoundInstance();
}
decrementOdd = true;
} else {
if (!evenParityBad) {
throw NotFoundException.getNotFoundInstance();
}
decrementEven = true;
}
} else if (mismatch == -1) {
if (oddParityBad) {
if (evenParityBad) {
throw NotFoundException.getNotFoundInstance();
}
incrementOdd = true;
} else {
if (!evenParityBad) {
throw NotFoundException.getNotFoundInstance();
}
incrementEven = true;
}
} else if (mismatch == 0) {
if (oddParityBad) {
if (!evenParityBad) {
throw NotFoundException.getNotFoundInstance();
}
// Both bad
if (oddSum < evenSum) {
incrementOdd = true;
decrementEven = true;
} else {
decrementOdd = true;
incrementEven = true;
}
} else {
if (evenParityBad) {
throw NotFoundException.getNotFoundInstance();
}
// Nothing to do!
}
} else {
throw NotFoundException.getNotFoundInstance();
}
if (incrementOdd) {
if (decrementOdd) {
throw NotFoundException.getNotFoundInstance();
}
increment(oddCounts, oddRoundingErrors);
}
if (decrementOdd) {
decrement(oddCounts, oddRoundingErrors);
}
if (incrementEven) {
if (decrementEven) {
throw NotFoundException.getNotFoundInstance();
}
increment(evenCounts, oddRoundingErrors);
}
if (decrementEven) {
decrement(evenCounts, evenRoundingErrors);
}
}
}

View file

@ -0,0 +1,155 @@
/*
* Copyright 2009 ZXing authors
*
* 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.
*/
package com.google.zxing.oned.rss;
/** Adapted from listings in ISO/IEC 24724 Appendix B and Appendix G. */
public final class RSSUtils {
private RSSUtils() {}
static int[] getRSSwidths(int val, int n, int elements, int maxWidth, boolean noNarrow) {
int[] widths = new int[elements];
int bar;
int narrowMask = 0;
for (bar = 0; bar < elements - 1; bar++) {
narrowMask |= (1 << bar);
int elmWidth = 1;
int subVal;
while (true) {
subVal = combins(n - elmWidth - 1, elements - bar - 2);
if (noNarrow && (narrowMask == 0) &&
(n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) {
subVal -= combins(n - elmWidth - (elements - bar), elements - bar - 2);
}
if (elements - bar - 1 > 1) {
int lessVal = 0;
for (int mxwElement = n - elmWidth - (elements - bar - 2);
mxwElement > maxWidth;
mxwElement--) {
lessVal += combins(n - elmWidth - mxwElement - 1, elements - bar - 3);
}
subVal -= lessVal * (elements - 1 - bar);
} else if (n - elmWidth > maxWidth) {
subVal--;
}
val -= subVal;
if (val < 0) {
break;
}
elmWidth++;
narrowMask &= ~(1 << bar);
}
val += subVal;
n -= elmWidth;
widths[bar] = elmWidth;
}
widths[bar] = n;
return widths;
}
static int getRSSvalue(int[] widths, int maxWidth, boolean noNarrow) {
int elements = widths.length;
int n = 0;
for (int i = 0; i < elements; i++) {
n += widths[i];
}
int val = 0;
int narrowMask = 0;
for (int bar = 0; bar < elements - 1; bar++) {
int elmWidth;
for (elmWidth = 1, narrowMask |= (1 << bar);
elmWidth < widths[bar];
elmWidth++, narrowMask &= ~(1 << bar)) {
int subVal = combins(n - elmWidth - 1, elements - bar - 2);
if (noNarrow && (narrowMask == 0) &&
(n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) {
subVal -= combins(n - elmWidth - (elements - bar),
elements - bar - 2);
}
if (elements - bar - 1 > 1) {
int lessVal = 0;
for (int mxwElement = n - elmWidth - (elements - bar - 2);
mxwElement > maxWidth; mxwElement--) {
lessVal += combins(n - elmWidth - mxwElement - 1,
elements - bar - 3);
}
subVal -= lessVal * (elements - 1 - bar);
} else if (n - elmWidth > maxWidth) {
subVal--;
}
val += subVal;
}
n -= elmWidth;
}
return (val);
}
static int combins(int n, int r) {
int maxDenom, minDenom;
if (n - r > r) {
minDenom = r;
maxDenom = n - r;
} else {
minDenom = n - r;
maxDenom = r;
}
int val = 1;
int j = 1;
for (int i = n; i > maxDenom; i--) {
val *= i;
if (j <= minDenom) {
val /= j;
j++;
}
}
while (j <= minDenom) {
val /= j;
j++;
}
return (val);
}
static int[] elements(int[] eDist, int N, int K) {
int[] widths = new int[eDist.length + 2];
int twoK = K << 1;
widths[0] = 1;
int i;
int minEven = 10;
int barSum = 1;
for (i = 1; i < twoK - 2; i += 2) {
widths[i] = eDist[i - 1] - widths[i - 1];
widths[i + 1] = eDist[i] - widths[i];
barSum += widths[i] + widths[i + 1];
if (widths[i] < minEven) {
minEven = widths[i];
}
}
widths[twoK - 1] = N - barSum;
if (widths[twoK - 1] < minEven) {
minEven = widths[twoK - 1];
}
if (minEven > 1) {
for (i = 0; i < twoK; i += 2) {
widths[i] += minEven - 1;
widths[i + 1] -= minEven - 1;
}
}
return widths;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -0,0 +1 @@
04412345678909

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View file

@ -0,0 +1 @@
00821935106427

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View file

@ -0,0 +1 @@
00075678164125

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1 @@
20012345678909

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1 @@
00034567890125

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1 @@
00012345678905

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View file

@ -0,0 +1 @@
04412345678909

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View file

@ -0,0 +1 @@
04412345678909

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View file

@ -0,0 +1 @@
00012345678905

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View file

@ -0,0 +1 @@
00012345678905

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View file

@ -0,0 +1 @@
00012345678905

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -0,0 +1 @@
00012345678905

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -0,0 +1 @@
00012345678905

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View file

@ -0,0 +1 @@
04412345678909

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -0,0 +1 @@
04412345678909

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View file

@ -0,0 +1 @@
02001234567893

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View file

@ -0,0 +1 @@
02001234567893

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 ZXing authors
*
* 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.
*/
package com.google.zxing.oned.rss;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.common.AbstractBlackBoxTestCase;
/**
* @author Sean Owen
*/
public final class RSS14BlackBox1TestCase extends AbstractBlackBoxTestCase {
public RSS14BlackBox1TestCase() {
super("test/data/blackbox/rss14-1", new MultiFormatReader(), BarcodeFormat.RSS14);
addTest(6, 6, 0.0f);
addTest(6, 6, 180.0f);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 ZXing authors
*
* 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.
*/
package com.google.zxing.oned.rss;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.common.AbstractBlackBoxTestCase;
/**
* @author Sean Owen
*/
public final class RSS14BlackBox2TestCase extends AbstractBlackBoxTestCase {
public RSS14BlackBox2TestCase() {
super("test/data/blackbox/rss14-2", new MultiFormatReader(), BarcodeFormat.RSS14);
addTest(7, 9, 0.0f);
addTest(6, 9, 180.0f);
}
}