Big RSS Expanded changelist -- thank you authors

git-svn-id: https://zxing.googlecode.com/svn/trunk@1350 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2010-05-10 19:18:50 +00:00
parent 0ab1caee3e
commit 74c8744e8c
398 changed files with 5120 additions and 98 deletions

View file

@ -1,11 +1,14 @@
This project consists of contributions from several people, recognized here for convenience,
in alphabetical order.
Agustín Delgado (Servinform S.A.)
Aitor Almeida (University of Deusto)
Alasdair Mackintosh (Google)
Alexander Martin (Haase & Martin GmbH)
Andreas Pillath
Andrey Sitnik
Androida.hu / http://www.androida.hu/
Antonio Manuel Benjumea (Servinform S.A.)
Brian Brown (Google)
Christian Brunschen (Google)
Daniel Switkin (Google)
@ -13,6 +16,7 @@ Dave MacLachlan (Google)
David Phillip Oster (Google)
David Albert (Bug Labs)
Diego Pierotto
Eduardo Castillejo (University of Deusto)
Eric Kobrin (Velocitude)
Erik Barbara
Fred Lin (Anobiit)
@ -32,6 +36,7 @@ Matthew Schulkind (Google)
Matt York (LifeMarks)
Mohamad Fairol
Nikolaos Ftylitakis
Pablo Orduña (University of Deusto)
Paul Hackenberger
Randy Shen (Acer)
Rasmus Schrøder Sørensen

View file

@ -62,6 +62,9 @@ public final class BarcodeFormat {
/** PDF417 format. */
public static final BarcodeFormat PDF417 = new BarcodeFormat("PDF417");
/** RSS EXPANDED */
public static final BarcodeFormat RSS_EXPANDED = new BarcodeFormat("RSS_EXPANDED");
private final String name;
private BarcodeFormat(String name) {
@ -88,4 +91,4 @@ public final class BarcodeFormat {
return format;
}
}
}

View file

@ -102,7 +102,8 @@ public final class MultiFormatReader implements Reader {
formats.contains(BarcodeFormat.CODE_39) ||
formats.contains(BarcodeFormat.CODE_128) ||
formats.contains(BarcodeFormat.ITF) ||
formats.contains(BarcodeFormat.RSS14);
formats.contains(BarcodeFormat.RSS14) ||
formats.contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder) {
readers.addElement(new MultiFormatOneDReader(hints));

View file

@ -0,0 +1,195 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.client.result;
import java.util.Hashtable;
/**
* @author Antonio Manuel Benjumea Conde, Servinform, S.A.
* @author Agustín Delgado, Servinform, S.A.
*/
public class ExpandedProductParsedResult extends ParsedResult {
public static final String KILOGRAM = "KG";
public static final String POUND = "LB";
private final String productID;
private final String sscc;
private final String lotNumber;
private final String productionDate;
private final String packagingDate;
private final String bestBeforeDate;
private final String expirationDate;
private final String weight;
private final String weightType;
private final String weightIncrement;
private final String price;
private final String priceIncrement;
private final String priceCurrency;
// For AIS that not exist in this object
private final Hashtable uncommonAIs;
ExpandedProductParsedResult() {
super(ParsedResultType.PRODUCT);
this.productID = "";
this.sscc = "";
this.lotNumber = "";
this.productionDate = "";
this.packagingDate = "";
this.bestBeforeDate = "";
this.expirationDate = "";
this.weight = "";
this.weightType = "";
this.weightIncrement = "";
this.price = "";
this.priceIncrement = "";
this.priceCurrency = "";
this.uncommonAIs = new Hashtable();
}
public ExpandedProductParsedResult(String productID, String sscc,
String lotNumber, String productionDate, String packagingDate,
String bestBeforeDate, String expirationDate, String weight,
String weightType, String weightIncrement, String price,
String priceIncrement, String priceCurrency, Hashtable uncommonAIs) {
super(ParsedResultType.PRODUCT);
this.productID = productID;
this.sscc = sscc;
this.lotNumber = lotNumber;
this.productionDate = productionDate;
this.packagingDate = packagingDate;
this.bestBeforeDate = bestBeforeDate;
this.expirationDate = expirationDate;
this.weight = weight;
this.weightType = weightType;
this.weightIncrement = weightIncrement;
this.price = price;
this.priceIncrement = priceIncrement;
this.priceCurrency = priceCurrency;
this.uncommonAIs = uncommonAIs;
}
public boolean equals(Object o){
if (!(o instanceof ExpandedProductParsedResult)) {
return false;
}
ExpandedProductParsedResult other = (ExpandedProductParsedResult)o;
return this.productID.equals( other.productID)
&& this.sscc.equals( other.sscc)
&& this.lotNumber.equals( other.lotNumber)
&& this.productionDate.equals( other.productionDate)
&& this.bestBeforeDate.equals( other.bestBeforeDate)
&& this.expirationDate.equals( other.expirationDate)
&& this.weight.equals( other.weight)
&& this.weightType.equals( other.weightType)
&& this.weightIncrement.equals( other.weightIncrement)
&& this.price.equals( other.price)
&& this.priceIncrement.equals( other.priceIncrement)
&& this.priceCurrency.equals( other.priceCurrency)
&& this.uncommonAIs.equals( other.uncommonAIs);
}
public int hashCode(){
int hash1 = this.productID.hashCode();
hash1 = 31 * hash1 + this.sscc.hashCode();
hash1 = 31 * hash1 + this.lotNumber.hashCode();
hash1 = 31 * hash1 + this.productionDate.hashCode();
hash1 = 31 * hash1 + this.bestBeforeDate.hashCode();
hash1 = 31 * hash1 + this.expirationDate.hashCode();
hash1 = 31 * hash1 + this.weight.hashCode();
int hash2 = this.weightType.hashCode();
hash2 = 31 * hash2 + this.weightIncrement.hashCode();
hash2 = 31 * hash2 + this.price.hashCode();
hash2 = 31 * hash2 + this.priceIncrement.hashCode();
hash2 = 31 * hash2 + this.priceCurrency.hashCode();
hash2 = 31 * hash2 + this.uncommonAIs.hashCode();
return hash1 ^ hash2;
}
public String getProductID() {
return productID;
}
public String getSscc() {
return sscc;
}
public String getLotNumber() {
return lotNumber;
}
public String getProductionDate() {
return productionDate;
}
public String getPackagingDate() {
return packagingDate;
}
public String getBestBeforeDate() {
return bestBeforeDate;
}
public String getExpirationDate() {
return expirationDate;
}
public String getWeight() {
return weight;
}
public String getWeightType() {
return weightType;
}
public String getWeightIncrement() {
return weightIncrement;
}
public String getPrice() {
return price;
}
public String getPriceIncrement() {
return priceIncrement;
}
public String getPriceCurrency() {
return priceCurrency;
}
public Hashtable getUncommonAIs() {
return uncommonAIs;
}
public String getDisplayResult() {
return productID;
}
}

View file

@ -0,0 +1,199 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.client.result;
import java.util.Hashtable;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
/**
* Parses strings of digits that represent a RSS Extended code.
*
* @author Antonio Manuel Benjumea Conde, Servinform, S.A.
* @author Agustín Delgado, Servinform, S.A.
*/
final class ExpandedProductResultParser extends ResultParser {
private ExpandedProductResultParser() {
}
// Treat all RSS EXPANDED, in the sense that they are all
// product barcodes with complementary data.
public static ExpandedProductParsedResult parse(Result result) {
BarcodeFormat format = result.getBarcodeFormat();
if (!(BarcodeFormat.RSS_EXPANDED.equals(format))) {
// ExtendedProductParsedResult NOT created. Not a RSS Expanded barcode
return null;
}
// Really neither of these should happen:
String rawText = result.getText();
if (rawText == null) {
// ExtendedProductParsedResult NOT created. Input text is NULL
return null;
}
String productID = "-";
String sscc = "-";
String lotNumber = "-";
String productionDate = "-";
String packagingDate = "-";
String bestBeforeDate = "-";
String expirationDate = "-";
String weight = "-";
String weightType = "-";
String weightIncrement = "-";
String price = "-";
String priceIncrement = "-";
String priceCurrency = "-";
Hashtable uncommonAIs = new Hashtable();
int i = 0;
while (i < rawText.length()) {
String ai = findAIvalue(i, rawText);
if ("ERROR".equals(ai)) {
// Error. Code doesn't match with RSS expanded pattern
// ExtendedProductParsedResult NOT created. Not match with RSS Expanded pattern
return null;
}
i += ai.length() + 2;
String value = findValue(i, rawText);
i += value.length();
if ("00".equals(ai)) {
sscc = value;
} else if ("01".equals(ai)) {
productID = value;
} else if ("10".equals(ai)) {
lotNumber = value;
} else if ("11".equals(ai)) {
productionDate = value;
} else if ("13".equals(ai)) {
packagingDate = value;
} else if ("15".equals(ai)) {
bestBeforeDate = value;
} else if ("17".equals(ai)) {
expirationDate = value;
} else if ("3100".equals(ai) || "3101".equals(ai)
|| "3102".equals(ai) || "3103".equals(ai)
|| "3104".equals(ai) || "3105".equals(ai)
|| "3106".equals(ai) || "3107".equals(ai)
|| "3108".equals(ai) || "3109".equals(ai)) {
weight = value;
weightType = ExpandedProductParsedResult.KILOGRAM;
weightIncrement = ai.substring(3);
} else if ("3200".equals(ai) || "3201".equals(ai)
|| "3202".equals(ai) || "3203".equals(ai)
|| "3204".equals(ai) || "3205".equals(ai)
|| "3206".equals(ai) || "3207".equals(ai)
|| "3208".equals(ai) || "3209".equals(ai)) {
weight = value;
weightType = ExpandedProductParsedResult.POUND;
weightIncrement = ai.substring(3);
} else if ("3920".equals(ai) || "3921".equals(ai)
|| "3922".equals(ai) || "3923".equals(ai)) {
price = value;
priceIncrement = ai.substring(3);
} else if ("3930".equals(ai) || "3931".equals(ai)
|| "3932".equals(ai) || "3933".equals(ai)) {
if (value.length() < 4) {
// The value must have more of 3 symbols (3 for currency and
// 1 at least for the price)
// ExtendedProductParsedResult NOT created. Not match with RSS Expanded pattern
return null;
}
price = value.substring(3);
priceCurrency = value.substring(0, 3);
priceIncrement = ai.substring(3);
} else {
// No match with common AIs
uncommonAIs.put(ai, value);
}
}
return new ExpandedProductParsedResult(productID, sscc, lotNumber,
productionDate, packagingDate, bestBeforeDate, expirationDate,
weight, weightType, weightIncrement, price, priceIncrement,
priceCurrency, uncommonAIs);
}
private static String findAIvalue(int i, String rawText) {
StringBuffer buf = new StringBuffer();
char c = rawText.charAt(i);
// First character must be a open parenthesis.If not, ERROR
if (c != '(') {
return "ERROR";
}
String rawTextAux = rawText.substring(i + 1);
for (int index = 0; index < rawTextAux.length(); index++) {
char currentChar = rawTextAux.charAt(index);
switch (currentChar){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
buf.append(currentChar);
break;
case ')':
return buf.toString();
default:
return "ERROR";
}
}
return buf.toString();
}
private static String findValue(int i, String rawText) {
StringBuffer buf = new StringBuffer();
String rawTextAux = rawText.substring(i);
for (int index = 0; index < rawTextAux.length(); index++) {
char c = rawTextAux.charAt(index);
if (c == '(') {
// We look for a new AI. If it doesn't exist (ERROR), we coninue
// with the iteration
if ("ERROR".equals(findAIvalue(index, rawTextAux))) {
buf.append(c);
} else {
break;
}
} else {
buf.append(c);
}
}
return buf.toString();
}
}

View file

@ -72,6 +72,8 @@ public abstract class ResultParser {
return result;
} else if ((result = ProductResultParser.parse(theResult)) != null) {
return result;
} else if ((result = ExpandedProductResultParser.parse(theResult)) != null) {
return result;
}
return new TextParsedResult(theResult.getText(), null);
}

View file

@ -24,6 +24,7 @@ import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.BitArray;
import com.google.zxing.oned.rss.RSS14Reader;
import com.google.zxing.oned.rss.expanded.RSSExpandedReader;
import java.util.Hashtable;
import java.util.Vector;
@ -61,6 +62,9 @@ public final class MultiFormatOneDReader extends OneDReader {
if (possibleFormats.contains(BarcodeFormat.RSS14)) {
readers.addElement(new RSS14Reader());
}
if (possibleFormats.contains(BarcodeFormat.RSS_EXPANDED)){
readers.addElement(new RSSExpandedReader());
}
}
if (readers.isEmpty()) {
readers.addElement(new MultiFormatUPCEANReader(hints));
@ -68,6 +72,7 @@ public final class MultiFormatOneDReader extends OneDReader {
readers.addElement(new Code128Reader());
readers.addElement(new ITFReader());
readers.addElement(new RSS14Reader());
readers.addElement(new RSSExpandedReader());
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright (C) 2010 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.NotFoundException;
import com.google.zxing.oned.OneDReader;
public abstract class AbstractRSSReader 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;
protected final int[] decodeFinderCounters;
protected final int[] dataCharacterCounters;
protected final float[] oddRoundingErrors;
protected final float[] evenRoundingErrors;
protected final int[] oddCounts;
protected final int[] evenCounts;
protected AbstractRSSReader(){
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];
}
protected static int parseFinderValue(int[] counters, int [][] finderPatterns) throws NotFoundException {
for (int value = 0; value < finderPatterns.length; value++) {
if (patternMatchVariance(counters, finderPatterns[value], MAX_INDIVIDUAL_VARIANCE) <
MAX_AVG_VARIANCE) {
return value;
}
}
throw NotFoundException.getNotFoundInstance();
}
protected static int count(int[] array) {
int count = 0;
for (int i = 0; i < array.length; i++) {
count += array[i];
}
return count;
}
protected 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]++;
}
protected 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]--;
}
protected 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;
}
}

View file

@ -16,22 +16,22 @@
package com.google.zxing.oned.rss;
class DataCharacter {
public class DataCharacter {
private final int value;
private final int checksumPortion;
DataCharacter(int value, int checksumPortion) {
public DataCharacter(int value, int checksumPortion) {
this.value = value;
this.checksumPortion = checksumPortion;
}
int getValue() {
public int getValue() {
return value;
}
int getChecksumPortion() {
public int getChecksumPortion() {
return checksumPortion;
}
}
}

View file

@ -18,13 +18,13 @@ package com.google.zxing.oned.rss;
import com.google.zxing.ResultPoint;
final class FinderPattern {
public 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) {
public FinderPattern(int value, int[] startEnd, int start, int end, int rowNumber) {
this.value = value;
this.startEnd = startEnd;
this.resultPoints = new ResultPoint[] {
@ -33,15 +33,15 @@ final class FinderPattern {
};
}
int getValue() {
public int getValue() {
return value;
}
int[] getStartEnd() {
public int[] getStartEnd() {
return startEnd;
}
ResultPoint[] getResultPoints() {
public ResultPoint[] getResultPoints() {
return resultPoints;
}

View file

@ -23,7 +23,6 @@ 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.Enumeration;
import java.util.Hashtable;
@ -32,13 +31,7 @@ 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;
public final class RSS14Reader extends AbstractRSSReader {
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};
@ -59,22 +52,10 @@ public final class RSS14Reader extends OneDReader {
{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();
}
@ -348,28 +329,6 @@ public final class RSS14Reader extends OneDReader {
}
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
@ -387,7 +346,7 @@ public final class RSS14Reader extends OneDReader {
counters[i] = counters[i-1];
}
counters[0] = firstCounter;
int value = parseFinderValue(counters);
int value = parseFinderValue(counters, FINDER_PATTERNS);
int start = firstElementStart;
int end = startEnd[1];
if (right) {
@ -398,16 +357,6 @@ public final class RSS14Reader extends OneDReader {
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;
@ -425,38 +374,6 @@ public final class RSS14Reader extends OneDReader {
}
*/
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);

View file

@ -61,7 +61,7 @@ public final class RSSUtils {
return widths;
}
static int getRSSvalue(int[] widths, int maxWidth, boolean noNarrow) {
public static int getRSSvalue(int[] widths, int maxWidth, boolean noNarrow) {
int elements = widths.length;
int n = 0;
for (int i = 0; i < elements; i++) {

View file

@ -0,0 +1,85 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded;
import java.util.Vector;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class BitArrayBuilder {
private BitArrayBuilder() {
}
static BitArray buildBitArray(Vector pairs) {
int charNumber = (pairs.size() << 1) - 1;
if ((((ExpandedPair)pairs.lastElement()).getRightChar()) == null) {
charNumber -= 1;
}
int size = 12 * charNumber;
BitArray binary = new BitArray(size);
int accPos = 0;
ExpandedPair firstPair = (ExpandedPair)pairs.get(0);
int firstValue = firstPair.getRightChar().getValue();
for(int i = 11; i >= 0; --i){
if ((firstValue & (1 << i)) != 0) {
binary.set(accPos);
}
accPos++;
}
for(int i = 1; i < pairs.size(); ++i){
ExpandedPair currentPair = (ExpandedPair)pairs.get(i);
int leftValue = currentPair.getLeftChar().getValue();
for(int j = 11; j >= 0; --j){
if ((leftValue & (1 << j)) != 0) {
binary.set(accPos);
}
accPos++;
}
if(currentPair.getRightChar() != null){
int rightValue = currentPair.getRightChar().getValue();
for(int j = 11; j >= 0; --j){
if ((rightValue & (1 << j)) != 0) {
binary.set(accPos);
}
accPos++;
}
}
}
return binary;
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded;
import com.google.zxing.oned.rss.DataCharacter;
import com.google.zxing.oned.rss.FinderPattern;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
final class ExpandedPair {
private final boolean mayBeLast;
private final DataCharacter leftChar;
private final DataCharacter rightChar;
private final FinderPattern finderPattern;
ExpandedPair(DataCharacter leftChar, DataCharacter rightChar, FinderPattern finderPattern, boolean mayBeLast) {
this.leftChar = leftChar;
this.rightChar = rightChar;
this.finderPattern = finderPattern;
this.mayBeLast = mayBeLast;
}
boolean mayBeLast(){
return this.mayBeLast;
}
DataCharacter getLeftChar() {
return this.leftChar;
}
DataCharacter getRightChar() {
return this.rightChar;
}
FinderPattern getFinderPattern() {
return this.finderPattern;
}
public boolean mustBeLast() {
return this.rightChar == null;
}
}

View file

@ -0,0 +1,578 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded;
import java.util.Hashtable;
import java.util.Vector;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.oned.rss.AbstractRSSReader;
import com.google.zxing.oned.rss.DataCharacter;
import com.google.zxing.oned.rss.FinderPattern;
import com.google.zxing.oned.rss.RSSUtils;
import com.google.zxing.oned.rss.expanded.decoders.AbstractExpandedDecoder;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
public final class RSSExpandedReader extends AbstractRSSReader{
private static final int[] SYMBOL_WIDEST = {7, 5, 4, 3, 1};
private static final int[] EVEN_TOTAL_SUBSET = {4, 20, 52, 104, 204};
private static final int[] GSUM = {0, 348, 1388, 2948, 3988};
private static final int[][] FINDER_PATTERNS = {
{1,8,4,1}, // A
{3,6,4,1}, // B
{3,4,6,1}, // C
{3,2,8,1}, // D
{2,6,5,1}, // E
{2,2,9,1} // F
};
private static final int[][] WEIGHTS = {
{ 1, 3, 9, 27, 81, 32, 96, 77},
{ 20, 60, 180, 118, 143, 7, 21, 63},
{189, 145, 13, 39, 117, 140, 209, 205},
{193, 157, 49, 147, 19, 57, 171, 91},
{ 62, 186, 136, 197, 169, 85, 44, 132},
{185, 133, 188, 142, 4, 12, 36, 108},
{113, 128, 173, 97, 80, 29, 87, 50},
{150, 28, 84, 41, 123, 158, 52, 156},
{ 46, 138, 203, 187, 139, 206, 196, 166},
{ 76, 17, 51, 153, 37, 111, 122, 155},
{ 43, 129, 176, 106, 107, 110, 119, 146},
{ 16, 48, 144, 10, 30, 90, 59, 177},
{109, 116, 137, 200, 178, 112, 125, 164},
{ 70, 210, 208, 202, 184, 130, 179, 115},
{134, 191, 151, 31, 93, 68, 204, 190},
{148, 22, 66, 198, 172, 94, 71, 2},
{ 6, 18, 54, 162, 64, 192,154, 40},
{120, 149, 25, 75, 14, 42,126, 167},
{ 79, 26, 78, 23, 69, 207,199, 175},
{103, 98, 83, 38, 114, 131, 182, 124},
{161, 61, 183, 127, 170, 88, 53, 159},
{ 55, 165, 73, 8, 24, 72, 5, 15},
{ 45, 135, 194, 160, 58, 174, 100, 89}
};
private static final int FINDER_PAT_A = 0;
private static final int FINDER_PAT_B = 1;
private static final int FINDER_PAT_C = 2;
private static final int FINDER_PAT_D = 3;
private static final int FINDER_PAT_E = 4;
private static final int FINDER_PAT_F = 5;
private static final int [][] FINDER_PATTERN_SEQUENCES = {
{ FINDER_PAT_A, FINDER_PAT_A },
{ FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B },
{ FINDER_PAT_A, FINDER_PAT_C, FINDER_PAT_B, FINDER_PAT_D },
{ FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_C },
{ FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_F },
{ FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F },
{ FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D },
{ FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E },
{ FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F },
{ FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F },
};
private static final int LONGEST_SEQUENCE_SIZE = FINDER_PATTERN_SEQUENCES[FINDER_PATTERN_SEQUENCES.length - 1].length;
private static final int MAX_PAIRS = 11;
private final Vector pairs = new Vector(MAX_PAIRS);
private final int [] startEnd = new int[2];
private final int [] currentSequence = new int[LONGEST_SEQUENCE_SIZE];
public Result decodeRow(int rowNumber, BitArray row, Hashtable hints) throws NotFoundException {
this.reset();
decodeRow2pairs(rowNumber, row);
return constructResult(this.pairs);
}
public void reset() {
this.pairs.setSize(0);
}
// Not private for testing
Vector decodeRow2pairs(int rowNumber, BitArray row) throws NotFoundException {
while(true){
ExpandedPair nextPair = retrieveNextPair(row, this.pairs, rowNumber);
this.pairs.add(nextPair);
if(nextPair.mayBeLast()){
if(checkChecksum()) {
return this.pairs;
}
if(nextPair.mustBeLast()) {
throw NotFoundException.getNotFoundInstance();
}
}
}
}
private static Result constructResult(Vector pairs) throws NotFoundException{
BitArray binary = BitArrayBuilder.buildBitArray(pairs);
AbstractExpandedDecoder decoder = AbstractExpandedDecoder.createDecoder(binary);
String resultingString = decoder.parseInformation();
ResultPoint [] firstPoints = ((ExpandedPair)pairs.get(0)).getFinderPattern().getResultPoints();
ResultPoint [] lastPoints = ((ExpandedPair)pairs.lastElement()).getFinderPattern().getResultPoints();
return new Result(
resultingString,
null,
new ResultPoint[]{firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]},
BarcodeFormat.RSS_EXPANDED
);
}
private boolean checkChecksum(){
ExpandedPair firstPair = (ExpandedPair)this.pairs.get(0);
DataCharacter checkCharacter = firstPair.getLeftChar();
DataCharacter firstCharacter = firstPair.getRightChar();
int checksum = firstCharacter.getChecksumPortion();
int S = 2;
for(int i = 1; i < this.pairs.size(); ++i){
ExpandedPair currentPair = (ExpandedPair)this.pairs.get(i);
checksum += currentPair.getLeftChar().getChecksumPortion();
S++;
if(currentPair.getRightChar() != null){
checksum += currentPair.getRightChar().getChecksumPortion();
S++;
}
}
checksum %= 211;
int checkCharacterValue = 211 * (S - 4) + checksum;
return checkCharacterValue == checkCharacter.getValue();
}
private static int getNextSecondBar(BitArray row, int initialPos){
int currentPos = initialPos;
boolean current = row.get(currentPos);
while(currentPos < row.size && row.get(currentPos) == current) {
currentPos++;
}
current = !current;
while(currentPos < row.size && row.get(currentPos) == current) {
currentPos++;
}
return currentPos;
}
// not private for testing
ExpandedPair retrieveNextPair(BitArray row, Vector previousPairs, int rowNumber) throws NotFoundException{
boolean isOddPattern = previousPairs.size() % 2 == 0;
FinderPattern pattern;
boolean keepFinding = true;
int forcedOffset = -1;
do{
this.findNextPair(row, previousPairs, forcedOffset);
pattern = parseFoundFinderPattern(row, rowNumber, isOddPattern);
if(pattern == null){
forcedOffset = getNextSecondBar(row, this.startEnd[0]);
}else {
keepFinding = false;
}
}while(keepFinding);
boolean mayBeLast = checkPairSequence(previousPairs, pattern);
DataCharacter leftChar = this.decodeDataCharacter(row, pattern, isOddPattern, true);
DataCharacter rightChar;
try{
rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);
}catch(NotFoundException nfe){
if(mayBeLast) {
rightChar = null;
} else {
throw nfe;
}
}
return new ExpandedPair(leftChar, rightChar, pattern, mayBeLast);
}
private boolean checkPairSequence(Vector previousPairs, FinderPattern pattern) throws NotFoundException{
int currentSequenceLength = previousPairs.size() + 1;
if(currentSequenceLength > this.currentSequence.length) {
throw NotFoundException.getNotFoundInstance();
}
for(int pos = 0; pos < previousPairs.size(); ++pos) {
this.currentSequence[pos] = ((ExpandedPair) previousPairs.get(pos)).getFinderPattern().getValue();
}
this.currentSequence[currentSequenceLength - 1] = pattern.getValue();
for(int i = 0; i < FINDER_PATTERN_SEQUENCES.length; ++i){
int [] validSequence = FINDER_PATTERN_SEQUENCES[i];
if(validSequence.length >= currentSequenceLength){
boolean valid = true;
for(int pos = 0; pos < currentSequenceLength; ++pos) {
if (this.currentSequence[pos] != validSequence[pos]) {
valid = false;
break;
}
}
if(valid) {
return currentSequenceLength == validSequence.length;
}
}
}
throw NotFoundException.getNotFoundInstance();
}
private void findNextPair(BitArray row, Vector previousPairs, int forcedOffset) throws NotFoundException{
int[] counters = this.decodeFinderCounters;
counters[0] = 0;
counters[1] = 0;
counters[2] = 0;
counters[3] = 0;
int width = row.getSize();
int rowOffset;
if (forcedOffset >= 0) {
rowOffset = forcedOffset;
} else if (previousPairs.isEmpty()) {
rowOffset = 0;
} else{
ExpandedPair lastPair = ((ExpandedPair)previousPairs.lastElement());
rowOffset = lastPair.getFinderPattern().getStartEnd()[1];
}
boolean searchingEvenPair = previousPairs.size() % 2 != 0;
boolean isWhite = false;
while (rowOffset < width) {
isWhite = !row.get(rowOffset);
if (!isWhite) {
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 (searchingEvenPair) {
reverseCounters(counters);
}
if (isFinderPattern(counters)){
this.startEnd[0] = patternStart;
this.startEnd[1] = x;
return;
}
if (searchingEvenPair) {
reverseCounters(counters);
}
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 void reverseCounters(int [] counters){
int length = counters.length;
for(int i = 0; i < length / 2; ++i){
int tmp = counters[i];
counters[i] = counters[length - i - 1];
counters[length - i - 1] = tmp;
}
}
private FinderPattern parseFoundFinderPattern(BitArray row, int rowNumber, boolean oddPattern) {
// Actually we found elements 2-5.
int firstCounter;
int start;
int end;
if(oddPattern){
// If pattern number is odd, we need to locate element 1 *before* the current block.
int firstElementStart = this.startEnd[0] - 1;
// Locate element 1
while (firstElementStart >= 0 && !row.get(firstElementStart)) {
firstElementStart--;
}
firstElementStart++;
firstCounter = this.startEnd[0] - firstElementStart;
start = firstElementStart;
end = this.startEnd[1];
}else{
// If pattern number is even, the pattern is reversed, so we need to locate element 1 *after* the current block.
start = this.startEnd[0];
int firstElementStart = this.startEnd[1] + 1;
while(row.get(firstElementStart) && firstElementStart < row.size) {
firstElementStart++;
}
end = firstElementStart;
firstCounter = end - this.startEnd[1];
}
// Make 'counters' hold 1-4
int [] counters = this.decodeFinderCounters;
for (int i = counters.length - 1; i > 0; i--) {
counters[i] = counters[i - 1];
}
counters[0] = firstCounter;
int value;
try {
value = parseFinderValue(counters, FINDER_PATTERNS);
} catch (NotFoundException nfe) {
return null;
}
return new FinderPattern(value, new int[] {start, end}, start, end, rowNumber);
}
DataCharacter decodeDataCharacter(BitArray row, FinderPattern pattern, boolean isOddPattern, boolean leftChar)
throws NotFoundException {
int[] counters = this.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 (leftChar) {
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;
}
}//counters[] has the pixels of the module
int numModules = 17; //left and right data characters have all the same length
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 = 1.0f * 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(numModules);
int weightRowNumber = 4 * pattern.getValue() + (isOddPattern?0:2) + (leftChar?0:1) - 1;
int oddSum = 0;
int oddChecksumPortion = 0;
for (int i = oddCounts.length - 1; i >= 0; i--) {
if(isNotA1left(pattern, isOddPattern, leftChar)){
int weight = WEIGHTS[weightRowNumber][2 * i];
oddChecksumPortion += oddCounts[i] * weight;
}
oddSum += oddCounts[i];
}
int evenChecksumPortion = 0;
int evenSum = 0;
for (int i = evenCounts.length - 1; i >= 0; i--) {
if(isNotA1left(pattern, isOddPattern, leftChar)){
int weight = WEIGHTS[weightRowNumber][2 * i + 1];
evenChecksumPortion += evenCounts[i] * weight;
}
evenSum += evenCounts[i];
}
int checksumPortion = oddChecksumPortion + evenChecksumPortion;
if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4) {
throw NotFoundException.getNotFoundInstance();
}
int group = (13 - oddSum) / 2;
int oddWidest = SYMBOL_WIDEST[group];
int evenWidest = 9 - oddWidest;
int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);
int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);
int tEven = EVEN_TOTAL_SUBSET[group];
int gSum = GSUM[group];
int value = vOdd * tEven + vEven + gSum;
return new DataCharacter(value, checksumPortion);
}
private static boolean isNotA1left(FinderPattern pattern, boolean isOddPattern, boolean leftChar) {
// A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char
return !(pattern.getValue() == 0 && isOddPattern && leftChar);
}
private void adjustOddEvenCounts(int numModules) throws NotFoundException {
int oddSum = count(this.oddCounts);
int evenSum = count(this.evenCounts);
int mismatch = oddSum + evenSum - numModules;
boolean oddParityBad = (oddSum & 0x01) == 1;
boolean evenParityBad = (evenSum & 0x01) == 0;
boolean incrementOdd = false;
boolean decrementOdd = false;
if (oddSum > 13) {
decrementOdd = true;
} else if (oddSum < 4) {
incrementOdd = true;
}
boolean incrementEven = false;
boolean decrementEven = false;
if (evenSum > 13) {
decrementEven = true;
} else if (evenSum < 4) {
incrementEven = true;
}
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(this.oddCounts, this.oddRoundingErrors);
}
if (decrementOdd) {
decrement(this.oddCounts, this.oddRoundingErrors);
}
if (incrementEven) {
if (decrementEven) {
throw NotFoundException.getNotFoundInstance();
}
increment(this.evenCounts, this.oddRoundingErrors);
}
if (decrementEven) {
decrement(this.evenCounts, this.evenRoundingErrors);
}
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
final class AI013103decoder extends AI013x0xDecoder {
AI013103decoder(BitArray information) {
super(information);
}
protected void addWeightCode(StringBuffer buf, int weight) {
buf.append("(3103)");
}
protected int checkWeight(int weight) {
return weight;
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
final class AI01320xDecoder extends AI013x0xDecoder {
AI01320xDecoder(BitArray information) {
super(information);
}
protected void addWeightCode(StringBuffer buf, int weight) {
if (weight < 10000) {
buf.append("(3202)");
} else {
buf.append("(3203)");
}
}
protected int checkWeight(int weight) {
if(weight < 10000) {
return weight;
}
return weight - 10000;
}
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
final class AI01392xDecoder extends AI01decoder {
private static final int headerSize = 5 + 1 + 2;
private static final int lastDigitSize = 2;
AI01392xDecoder(BitArray information) {
super(information);
}
public String parseInformation() throws NotFoundException {
if (this.information.size < headerSize + gtinSize) {
throw NotFoundException.getNotFoundInstance();
}
StringBuffer buf = new StringBuffer();
encodeCompressedGtin(buf, headerSize);
int lastAIdigit =
this.generalDecoder.extractNumericValueFromBitArray(headerSize + gtinSize, lastDigitSize);
buf.append("(392");
buf.append(lastAIdigit);
buf.append(')');
DecodedInformation decodedInformation =
this.generalDecoder.decodeGeneralPurposeField(headerSize + gtinSize + lastDigitSize, null);
buf.append(decodedInformation.getNewString());
return buf.toString();
}
}

View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
final class AI01393xDecoder extends AI01decoder {
private static final int headerSize = 5 + 1 + 2;
private static final int lastDigitSize = 2;
private static final int firstThreeDigitsSize = 10;
AI01393xDecoder(BitArray information) {
super(information);
}
public String parseInformation() throws NotFoundException {
if(this.information.size < headerSize + gtinSize) {
throw NotFoundException.getNotFoundInstance();
}
StringBuffer buf = new StringBuffer();
encodeCompressedGtin(buf, headerSize);
int lastAIdigit =
this.generalDecoder.extractNumericValueFromBitArray(headerSize + gtinSize, lastDigitSize);
buf.append("(393");
buf.append(lastAIdigit);
buf.append(')');
int firstThreeDigits =
this.generalDecoder.extractNumericValueFromBitArray(headerSize + gtinSize + lastDigitSize, firstThreeDigitsSize);
if(firstThreeDigits / 100 == 0) {
buf.append('0');
}
if(firstThreeDigits / 10 == 0) {
buf.append('0');
}
buf.append(firstThreeDigits);
DecodedInformation generalInformation =
this.generalDecoder.decodeGeneralPurposeField(headerSize + gtinSize + lastDigitSize + firstThreeDigitsSize, null);
buf.append(generalInformation.getNewString());
return buf.toString();
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class AI013x0x1xDecoder extends AI01weightDecoder {
private static final int headerSize = 7 + 1;
private static final int weightSize = 20;
private static final int dateSize = 16;
private final String dateCode;
private final String firstAIdigits;
AI013x0x1xDecoder(BitArray information, String firstAIdigits, String dateCode) {
super(information);
this.dateCode = dateCode;
this.firstAIdigits = firstAIdigits;
}
public String parseInformation() throws NotFoundException {
if (this.information.size != headerSize + gtinSize + weightSize + dateSize) {
throw NotFoundException.getNotFoundInstance();
}
StringBuffer buf = new StringBuffer();
encodeCompressedGtin(buf, headerSize);
encodeCompressedWeight(buf, headerSize + gtinSize, weightSize);
encodeCompressedDate(buf, headerSize + gtinSize + weightSize);
return buf.toString();
}
private void encodeCompressedDate(StringBuffer buf, int currentPos) {
int numericDate = this.generalDecoder.extractNumericValueFromBitArray(currentPos, dateSize);
if(numericDate == 38400) {
return;
}
buf.append('(');
buf.append(this.dateCode);
buf.append(')');
int day = numericDate % 32;
numericDate /= 32;
int month = numericDate % 12 + 1;
numericDate /= 12;
int year = numericDate;
if (year / 10 == 0) {
buf.append('0');
}
buf.append(year);
if (month / 10 == 0) {
buf.append('0');
}
buf.append(month);
if (day / 10 == 0) {
buf.append('0');
}
buf.append(day);
}
protected void addWeightCode(StringBuffer buf, int weight) {
int lastAI = weight / 100000;
buf.append('(');
buf.append(this.firstAIdigits);
buf.append(lastAI);
buf.append(')');
}
protected int checkWeight(int weight) {
return weight % 100000;
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
abstract class AI013x0xDecoder extends AI01weightDecoder {
private static final int headerSize = 4 + 1;
private static final int weightSize = 15;
AI013x0xDecoder(BitArray information) {
super(information);
}
public String parseInformation() throws NotFoundException {
if (this.information.size != headerSize + gtinSize + weightSize) {
throw NotFoundException.getNotFoundInstance();
}
StringBuffer buf = new StringBuffer();
encodeCompressedGtin(buf, headerSize);
encodeCompressedWeight(buf, headerSize + gtinSize, weightSize);
return buf.toString();
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class AI01AndOtherAIs extends AI01decoder {
private static final int HEADER_SIZE = 1 + 1 + 2; //first bit encodes the linkage flag,
//the second one is the encodation method, and the other two are for the variable length
AI01AndOtherAIs(BitArray information) {
super(information);
}
public String parseInformation() throws NotFoundException {
StringBuffer buff = new StringBuffer();
buff.append("(01)");
int initialGtinPosition = buff.length();
int firstGtinDigit = this.generalDecoder.extractNumericValueFromBitArray(HEADER_SIZE, 4);
buff.append(firstGtinDigit);
this.encodeCompressedGtinWithoutAI(buff, HEADER_SIZE + 4, initialGtinPosition);
return this.generalDecoder.decodeAllCodes(buff, HEADER_SIZE + 44);
}
}

View file

@ -0,0 +1,81 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
abstract class AI01decoder extends AbstractExpandedDecoder {
protected static final int gtinSize = 40;
AI01decoder(BitArray information) {
super(information);
}
protected void encodeCompressedGtin(StringBuffer buf, int currentPos) {
buf.append("(01)");
int initialPosition = buf.length();
buf.append('9');
encodeCompressedGtinWithoutAI(buf, currentPos, initialPosition);
}
protected void encodeCompressedGtinWithoutAI(StringBuffer buf, int currentPos, int initialBufferPosition) {
for(int i = 0; i < 4; ++i){
int currentBlock = this.generalDecoder.extractNumericValueFromBitArray(currentPos + 10 * i, 10);
if (currentBlock / 100 == 0) {
buf.append('0');
}
if (currentBlock / 10 == 0) {
buf.append('0');
}
buf.append(currentBlock);
}
appendCheckDigit(buf, initialBufferPosition);
}
private static void appendCheckDigit(StringBuffer buf, int currentPos){
int checkDigit = 0;
for (int i = 0; i < 13; i++) {
int digit = buf.charAt(i + currentPos) - '0';
checkDigit += (((i & 0x01) == 0) ? 3 * digit : digit);
}
checkDigit = 10 - (checkDigit % 10);
if (checkDigit == 10) {
checkDigit = 0;
}
buf.append(checkDigit);
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
abstract class AI01weightDecoder extends AI01decoder {
AI01weightDecoder(BitArray information) {
super(information);
}
protected void encodeCompressedWeight(StringBuffer buf, int currentPos, int weightSize) {
int originalWeightNumeric = this.generalDecoder.extractNumericValueFromBitArray(currentPos, weightSize);
addWeightCode(buf, originalWeightNumeric);
int weightNumeric = checkWeight(originalWeightNumeric);
int currentDivisor = 100000;
for(int i = 0; i < 5; ++i){
if (weightNumeric / currentDivisor == 0) {
buf.append('0');
}
currentDivisor /= 10;
}
buf.append(weightNumeric);
}
protected abstract void addWeightCode(StringBuffer buf, int weight);
protected abstract int checkWeight(int weight);
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
public abstract class AbstractExpandedDecoder {
protected final BitArray information;
protected final GeneralAppIdDecoder generalDecoder;
AbstractExpandedDecoder(BitArray information){
this.information = information;
this.generalDecoder = new GeneralAppIdDecoder(information);
}
public abstract String parseInformation() throws NotFoundException;
public static AbstractExpandedDecoder createDecoder(BitArray information){
if (information.get(1)) {
return new AI01AndOtherAIs(information);
} else if (!information.get(2)) {
return new AnyAIDecoder(information);
}
int fourBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 4);
switch(fourBitEncodationMethod){
case 4: return new AI013103decoder(information);
case 5: return new AI01320xDecoder(information);
}
int fiveBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 5);
switch(fiveBitEncodationMethod){
case 12: return new AI01392xDecoder(information);
case 13: return new AI01393xDecoder(information);
}
int sevenBitEncodationMethod = GeneralAppIdDecoder.extractNumericValueFromBitArray(information, 1, 7);
switch(sevenBitEncodationMethod){
case 56: return new AI013x0x1xDecoder(information, "310", "11");
case 57: return new AI013x0x1xDecoder(information, "320", "11");
case 58: return new AI013x0x1xDecoder(information, "310", "13");
case 59: return new AI013x0x1xDecoder(information, "320", "13");
case 60: return new AI013x0x1xDecoder(information, "310", "15");
case 61: return new AI013x0x1xDecoder(information, "320", "15");
case 62: return new AI013x0x1xDecoder(information, "310", "17");
case 63: return new AI013x0x1xDecoder(information, "320", "17");
}
throw new IllegalStateException("unknown decoder: " + information);
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class AnyAIDecoder extends AbstractExpandedDecoder {
private static final int HEADER_SIZE = 2 + 1 + 2;
AnyAIDecoder(BitArray information) {
super(information);
}
public String parseInformation() throws NotFoundException {
StringBuffer buf = new StringBuffer();
return this.generalDecoder.decodeAllCodes(buf, HEADER_SIZE);
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class BlockParsedResult {
private final DecodedInformation decodedInformation;
private final boolean finished;
BlockParsedResult() {
this.finished = true;
this.decodedInformation = null;
}
BlockParsedResult(boolean finished) {
this.finished = finished;
this.decodedInformation = null;
}
BlockParsedResult(DecodedInformation information, boolean finished) {
this.finished = finished;
this.decodedInformation = information;
}
DecodedInformation getDecodedInformation() {
return this.decodedInformation;
}
boolean isFinished() {
return this.finished;
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
final class CurrentParsingState {
int position;
private int encoding;
private static final int NUMERIC = 1;
private static final int ALPHA = 2;
private static final int ISO_IEC_646 = 4;
CurrentParsingState(){
this.position = 0;
this.encoding = NUMERIC;
}
boolean isAlpha(){
return this.encoding == ALPHA;
}
boolean isNumeric(){
return this.encoding == NUMERIC;
}
boolean isIsoIec646(){
return this.encoding == ISO_IEC_646;
}
void setNumeric(){
this.encoding = NUMERIC;
}
void setAlpha(){
this.encoding = ALPHA;
}
void setIsoIec646(){
this.encoding = ISO_IEC_646;
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class DecodedChar extends DecodedObject {
private final char value;
static final char FNC1 = '$'; // It's not in Alphanumeric neither in ISO/IEC 646 charset
DecodedChar(int newPosition, char value) {
super(newPosition);
this.value = value;
}
char getValue(){
return this.value;
}
boolean isFNC1(){
return this.value == FNC1;
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class DecodedInformation extends DecodedObject {
private final String newString;
private final int remainingValue;
private final boolean remaining;
DecodedInformation(int newPosition, String newString){
super(newPosition);
this.newString = newString;
this.remaining = false;
this.remainingValue = 0;
}
DecodedInformation(int newPosition, String newString, int remainingValue){
super(newPosition);
this.remaining = true;
this.remainingValue = remainingValue;
this.newString = newString;
}
String getNewString(){
return this.newString;
}
boolean isRemaining(){
return this.remaining;
}
int getRemainingValue(){
return this.remainingValue;
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class DecodedNumeric extends DecodedObject {
private final int firstDigit;
private final int secondDigit;
static final int FNC1 = 10;
DecodedNumeric(int newPosition, int firstDigit, int secondDigit){
super(newPosition);
this.firstDigit = firstDigit;
this.secondDigit = secondDigit;
if (this.firstDigit < 0 || this.firstDigit > 10) {
throw new IllegalArgumentException("Invalid firstDigit: " + firstDigit);
}
if (this.secondDigit < 0 || this.secondDigit > 10) {
throw new IllegalArgumentException("Invalid secondDigit: " + secondDigit);
}
}
int getFirstDigit(){
return this.firstDigit;
}
int getSecondDigit(){
return this.secondDigit;
}
int getValue(){
return this.firstDigit * 10 + this.secondDigit;
}
boolean isFirstDigitFNC1(){
return this.firstDigit == FNC1;
}
boolean isSecondDigitFNC1(){
return this.secondDigit == FNC1;
}
boolean isAnyFNC1(){
return this.firstDigit == FNC1 || this.secondDigit == FNC1;
}
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
*/
abstract class DecodedObject {
protected final int newPosition;
DecodedObject(int newPosition){
this.newPosition = newPosition;
}
int getNewPosition() {
return this.newPosition;
}
}

View file

@ -0,0 +1,285 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class FieldParser {
private static final Object VARIABLE_LENGTH = new Object();
private static final Object [][] TWO_DIGIT_DATA_LENGTH = {
// "DIGITS", new Integer(LENGTH)
// or
// "DIGITS", VARIABLE_LENGTH, new Integer(MAX_SIZE)
{ "00", new Integer(18) },
{ "01", new Integer(14) },
{ "02", new Integer(14) },
{ "10", VARIABLE_LENGTH, new Integer(20) },
{ "11", new Integer(6) },
{ "12", new Integer(6) },
{ "13", new Integer(6) },
{ "15", new Integer(6) },
{ "17", new Integer(6) },
{ "20", new Integer(2) },
{ "21", VARIABLE_LENGTH, new Integer(20) },
{ "22", VARIABLE_LENGTH, new Integer(29) },
{ "30", VARIABLE_LENGTH, new Integer( 8) },
{ "37", VARIABLE_LENGTH, new Integer( 8) },
//internal company codes
{ "90", VARIABLE_LENGTH, new Integer(30) },
{ "91", VARIABLE_LENGTH, new Integer(30) },
{ "92", VARIABLE_LENGTH, new Integer(30) },
{ "93", VARIABLE_LENGTH, new Integer(30) },
{ "94", VARIABLE_LENGTH, new Integer(30) },
{ "95", VARIABLE_LENGTH, new Integer(30) },
{ "96", VARIABLE_LENGTH, new Integer(30) },
{ "97", VARIABLE_LENGTH, new Integer(30) },
{ "98", VARIABLE_LENGTH, new Integer(30) },
{ "99", VARIABLE_LENGTH, new Integer(30) },
};
private static final Object [][] THREE_DIGIT_DATA_LENGTH = {
// Same format as above
{ "240", VARIABLE_LENGTH, new Integer(30) },
{ "241", VARIABLE_LENGTH, new Integer(30) },
{ "242", VARIABLE_LENGTH, new Integer( 6) },
{ "250", VARIABLE_LENGTH, new Integer(30) },
{ "251", VARIABLE_LENGTH, new Integer(30) },
{ "253", VARIABLE_LENGTH, new Integer(17) },
{ "254", VARIABLE_LENGTH, new Integer(20) },
{ "400", VARIABLE_LENGTH, new Integer(30) },
{ "401", VARIABLE_LENGTH, new Integer(30) },
{ "402", new Integer(17) },
{ "403", VARIABLE_LENGTH, new Integer(30) },
{ "410", new Integer(13) },
{ "411", new Integer(13) },
{ "412", new Integer(13) },
{ "413", new Integer(13) },
{ "414", new Integer(13) },
{ "420", VARIABLE_LENGTH, new Integer(20) },
{ "421", VARIABLE_LENGTH, new Integer(15) },
{ "422", new Integer( 3) },
{ "423", VARIABLE_LENGTH, new Integer(15) },
{ "424", new Integer(3) },
{ "425", new Integer(3) },
{ "426", new Integer(3) },
};
private static final Object [][] THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH = {
// Same format as above
{ "310", new Integer(6) },
{ "311", new Integer(6) },
{ "312", new Integer(6) },
{ "313", new Integer(6) },
{ "314", new Integer(6) },
{ "315", new Integer(6) },
{ "316", new Integer(6) },
{ "320", new Integer(6) },
{ "321", new Integer(6) },
{ "322", new Integer(6) },
{ "323", new Integer(6) },
{ "324", new Integer(6) },
{ "325", new Integer(6) },
{ "326", new Integer(6) },
{ "327", new Integer(6) },
{ "328", new Integer(6) },
{ "329", new Integer(6) },
{ "330", new Integer(6) },
{ "331", new Integer(6) },
{ "332", new Integer(6) },
{ "333", new Integer(6) },
{ "334", new Integer(6) },
{ "335", new Integer(6) },
{ "336", new Integer(6) },
{ "340", new Integer(6) },
{ "341", new Integer(6) },
{ "342", new Integer(6) },
{ "343", new Integer(6) },
{ "344", new Integer(6) },
{ "345", new Integer(6) },
{ "346", new Integer(6) },
{ "347", new Integer(6) },
{ "348", new Integer(6) },
{ "349", new Integer(6) },
{ "350", new Integer(6) },
{ "351", new Integer(6) },
{ "352", new Integer(6) },
{ "353", new Integer(6) },
{ "354", new Integer(6) },
{ "355", new Integer(6) },
{ "356", new Integer(6) },
{ "357", new Integer(6) },
{ "360", new Integer(6) },
{ "361", new Integer(6) },
{ "362", new Integer(6) },
{ "363", new Integer(6) },
{ "364", new Integer(6) },
{ "365", new Integer(6) },
{ "366", new Integer(6) },
{ "367", new Integer(6) },
{ "368", new Integer(6) },
{ "369", new Integer(6) },
{ "390", VARIABLE_LENGTH, new Integer(15) },
{ "391", VARIABLE_LENGTH, new Integer(18) },
{ "392", VARIABLE_LENGTH, new Integer(15) },
{ "393", VARIABLE_LENGTH, new Integer(18) },
{ "703", VARIABLE_LENGTH, new Integer(30) }
};
private static final Object [][] FOUR_DIGIT_DATA_LENGTH = {
// Same format as above
{ "7001", new Integer(13) },
{ "7002", VARIABLE_LENGTH, new Integer(30) },
{ "7003", new Integer(10) },
{ "8001", new Integer(14) },
{ "8002", VARIABLE_LENGTH, new Integer(20) },
{ "8003", VARIABLE_LENGTH, new Integer(30) },
{ "8004", VARIABLE_LENGTH, new Integer(30) },
{ "8005", new Integer(6) },
{ "8006", new Integer(18) },
{ "8007", VARIABLE_LENGTH, new Integer(30) },
{ "8008", VARIABLE_LENGTH, new Integer(12) },
{ "8018", new Integer(18) },
{ "8020", VARIABLE_LENGTH, new Integer(25) },
{ "8100", new Integer(6) },
{ "8101", new Integer(10) },
{ "8102", new Integer(2) },
{ "8110", VARIABLE_LENGTH, new Integer(30) },
};
private FieldParser() {
}
static String parseFieldsInGeneralPurpose(String rawInformation) throws NotFoundException{
if(rawInformation.length() == 0) {
return "";
}
// Processing 2-digit AIs
if(rawInformation.length() < 2) {
throw NotFoundException.getNotFoundInstance();
}
String firstTwoDigits = rawInformation.substring(0, 2);
for (int i=0; i<TWO_DIGIT_DATA_LENGTH.length; ++i){
if (TWO_DIGIT_DATA_LENGTH[i][0].equals(firstTwoDigits)){
if(TWO_DIGIT_DATA_LENGTH[i][1] == VARIABLE_LENGTH) {
return processVariableAI(2, ((Integer) TWO_DIGIT_DATA_LENGTH[i][2]).intValue(), rawInformation);
}
return processFixedAI(2, ((Integer)TWO_DIGIT_DATA_LENGTH[i][1]).intValue(), rawInformation);
}
}
if(rawInformation.length() < 3) {
throw NotFoundException.getNotFoundInstance();
}
String firstThreeDigits = rawInformation.substring(0, 3);
for (int i=0; i<THREE_DIGIT_DATA_LENGTH.length; ++i){
if (THREE_DIGIT_DATA_LENGTH[i][0].equals(firstThreeDigits)){
if (THREE_DIGIT_DATA_LENGTH[i][1] == VARIABLE_LENGTH) {
return processVariableAI(3, ((Integer) THREE_DIGIT_DATA_LENGTH[i][2]).intValue(), rawInformation);
}
return processFixedAI(3, ((Integer)THREE_DIGIT_DATA_LENGTH[i][1]).intValue(), rawInformation);
}
}
for (int i=0; i<THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH.length; ++i){
if (THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH[i][0].equals(firstThreeDigits)){
if (THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH[i][1] == VARIABLE_LENGTH) {
return processVariableAI(4, ((Integer) THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH[i][2]).intValue(), rawInformation);
}
return processFixedAI(4, ((Integer)THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH[i][1]).intValue(), rawInformation);
}
}
if(rawInformation.length() < 4) {
throw NotFoundException.getNotFoundInstance();
}
String firstFourDigits = rawInformation.substring(0, 4);
for (int i=0; i<FOUR_DIGIT_DATA_LENGTH.length; ++i){
if (FOUR_DIGIT_DATA_LENGTH[i][0].equals(firstFourDigits)){
if (FOUR_DIGIT_DATA_LENGTH[i][1] == VARIABLE_LENGTH) {
return processVariableAI(4, ((Integer) FOUR_DIGIT_DATA_LENGTH[i][2]).intValue(), rawInformation);
}
return processFixedAI(4, ((Integer)FOUR_DIGIT_DATA_LENGTH[i][1]).intValue(), rawInformation);
}
}
throw NotFoundException.getNotFoundInstance();
}
private static String processFixedAI(int aiSize, int fieldSize, String rawInformation) throws NotFoundException{
if (rawInformation.length() < aiSize) {
throw NotFoundException.getNotFoundInstance();
}
String ai = rawInformation.substring(0, aiSize);
if(rawInformation.length() < aiSize + fieldSize) {
throw NotFoundException.getNotFoundInstance();
}
String field = rawInformation.substring(aiSize, aiSize + fieldSize);
String remaining = rawInformation.substring(aiSize + fieldSize);
return '(' + ai + ')' + field + parseFieldsInGeneralPurpose(remaining);
}
private static String processVariableAI(int aiSize, int variableFieldSize, String rawInformation) throws NotFoundException {
String ai = rawInformation.substring(0, aiSize);
int maxSize;
if (rawInformation.length() < aiSize + variableFieldSize) {
maxSize = rawInformation.length();
} else {
maxSize = aiSize + variableFieldSize;
}
String field = rawInformation.substring(aiSize, maxSize);
String remaining = rawInformation.substring(maxSize);
return '(' + ai + ')' + field + parseFieldsInGeneralPurpose(remaining);
}
}

View file

@ -0,0 +1,414 @@
/*
* Copyright (C) 2010 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.
*/
/*
* These authors would like to acknowledge the Spanish Ministry of Industry,
* Tourism and Trade, for the support in the project TSI020301-2008-2
* "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
* Mobile Dynamic Environments", led by Treelogic
* ( http://www.treelogic.com/ ):
*
* http://www.piramidepse.com/
*/
package com.google.zxing.oned.rss.expanded.decoders;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitArray;
/**
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
* @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
*/
final class GeneralAppIdDecoder {
private final BitArray information;
private final CurrentParsingState current = new CurrentParsingState();
private final StringBuffer buffer = new StringBuffer();
GeneralAppIdDecoder(BitArray information){
this.information = information;
}
String decodeAllCodes(StringBuffer buff, int initialPosition) throws NotFoundException {
int currentPosition = initialPosition;
String remaining = null;
do{
DecodedInformation info = this.decodeGeneralPurposeField(currentPosition, remaining);
String parsedFields = FieldParser.parseFieldsInGeneralPurpose(info.getNewString());
buff.append(parsedFields);
if(info.isRemaining()) {
remaining = String.valueOf(info.getRemainingValue());
} else {
remaining = null;
}
if(currentPosition == info.getNewPosition()) {// No step forward!
break;
}
currentPosition = info.getNewPosition();
}while(true);
return buff.toString();
}
private boolean isStillNumeric(int pos) {
// It's numeric if it still has 7 positions
// and one of the first 4 bits is "1".
if(pos + 7 > this.information.size){
return pos + 4 <= this.information.size;
}
for(int i = pos; i < pos + 3; ++i) {
if (this.information.get(i)) {
return true;
}
}
return this.information.get(pos + 3);
}
private DecodedNumeric decodeNumeric(int pos) {
if(pos + 7 > this.information.size){
int numeric = extractNumericValueFromBitArray(pos, 4);
if(numeric == 0) {
return new DecodedNumeric(this.information.size, DecodedNumeric.FNC1, DecodedNumeric.FNC1);
}
return new DecodedNumeric(this.information.size, numeric - 1, DecodedNumeric.FNC1);
}
int numeric = extractNumericValueFromBitArray(pos, 7);
int digit1 = (numeric - 8) / 11;
int digit2 = (numeric - 8) % 11;
return new DecodedNumeric(pos + 7, digit1, digit2);
}
int extractNumericValueFromBitArray(int pos, int bits){
return extractNumericValueFromBitArray(this.information, pos, bits);
}
static int extractNumericValueFromBitArray(BitArray information, int pos, int bits) {
if(bits > 32) {
throw new IllegalArgumentException("extractNumberValueFromBitArray can't handle more than 32 bits");
}
int value = 0;
for(int i = 0; i < bits; ++i) {
if (information.get(pos + i)) {
value |= (1 << (bits - i - 1));
}
}
return value;
}
DecodedInformation decodeGeneralPurposeField(int pos, String remaining) {
this.buffer.setLength(0);
if(remaining != null) {
this.buffer.append(remaining);
}
this.current.position = pos;
DecodedInformation lastDecoded = parseBlocks();
if(lastDecoded != null && lastDecoded.isRemaining()) {
return new DecodedInformation(this.current.position, this.buffer.toString(), lastDecoded.getRemainingValue());
}
return new DecodedInformation(this.current.position, this.buffer.toString());
}
private DecodedInformation parseBlocks() {
boolean isFinished;
BlockParsedResult result;
do{
int initialPosition = current.position;
if (current.isAlpha()){
result = parseAlphaBlock();
isFinished = result.isFinished();
}else if (current.isIsoIec646()){
result = parseIsoIec646Block();
isFinished = result.isFinished();
}else{ // it must be numeric
result = parseNumericBlock();
isFinished = result.isFinished();
}
boolean positionChanged = initialPosition != current.position;
if(!positionChanged && !isFinished) {
break;
}
} while (!isFinished);
return result.getDecodedInformation();
}
private BlockParsedResult parseNumericBlock() {
while(isStillNumeric(current.position)){
DecodedNumeric numeric = decodeNumeric(current.position);
current.position = numeric.getNewPosition();
if(numeric.isFirstDigitFNC1()){
DecodedInformation information;
if (numeric.isSecondDigitFNC1()) {
information = new DecodedInformation(current.position, buffer.toString());
} else {
information = new DecodedInformation(current.position, buffer.toString(), numeric.getSecondDigit());
}
return new BlockParsedResult(information, true);
}
buffer.append(numeric.getFirstDigit());
if(numeric.isSecondDigitFNC1()){
DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
return new BlockParsedResult(information, true);
}
buffer.append(numeric.getSecondDigit());
}
if(isNumericToAlphaNumericLatch(current.position)){
current.setAlpha();
current.position += 4;
}
return new BlockParsedResult(false);
}
private BlockParsedResult parseIsoIec646Block() {
while (isStillIsoIec646(current.position)) {
DecodedChar iso = decodeIsoIec646(current.position);
current.position = iso.getNewPosition();
if (iso.isFNC1()) {
DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
return new BlockParsedResult(information, true);
}
buffer.append(iso.getValue());
}
if (isAlphaOr646ToNumericLatch(current.position)) {
current.position += 3;
current.setNumeric();
} else if (isAlphaTo646ToAlphaLatch(current.position)) {
if (current.position + 5 < this.information.size) {
current.position += 5;
} else {
current.position = this.information.size;
}
current.setAlpha();
}
return new BlockParsedResult(false);
}
private BlockParsedResult parseAlphaBlock() {
while (isStillAlpha(current.position)) {
DecodedChar alpha = decodeAlphanumeric(current.position);
current.position = alpha.getNewPosition();
if(alpha.isFNC1()) {
DecodedInformation information = new DecodedInformation(current.position, buffer.toString());
return new BlockParsedResult(information, true); //end of the char block
}
buffer.append(alpha.getValue());
}
if (isAlphaOr646ToNumericLatch(current.position)) {
current.position += 3;
current.setNumeric();
} else if (isAlphaTo646ToAlphaLatch(current.position)) {
if (current.position + 5 < this.information.size) {
current.position += 5;
} else {
current.position = this.information.size;
}
current.setIsoIec646();
}
return new BlockParsedResult(false);
}
private boolean isStillIsoIec646(int pos) {
if(pos + 5 > this.information.size) {
return false;
}
int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
if(fiveBitValue >= 5 && fiveBitValue < 16) {
return true;
}
if(pos + 7 > this.information.size) {
return false;
}
int sevenBitValue = extractNumericValueFromBitArray(pos, 7);
if(sevenBitValue >= 64 && sevenBitValue < 116) {
return true;
}
if(pos + 8 > this.information.size) {
return false;
}
int eightBitValue = extractNumericValueFromBitArray(pos, 8);
return eightBitValue >= 232 && eightBitValue < 253;
}
private DecodedChar decodeIsoIec646(int pos) {
int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
if(fiveBitValue == 15) {
return new DecodedChar(pos + 5, DecodedChar.FNC1);
}
if(fiveBitValue >= 5 && fiveBitValue < 15) {
return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5));
}
int sevenBitValue = extractNumericValueFromBitArray(pos, 7);
if(sevenBitValue >= 64 && sevenBitValue < 90) {
return new DecodedChar(pos + 7, (char) (sevenBitValue + 1));
}
if(sevenBitValue >= 90 && sevenBitValue < 116) {
return new DecodedChar(pos + 7, (char) (sevenBitValue + 7));
}
int eightBitValue = extractNumericValueFromBitArray(pos, 8);
switch (eightBitValue){
case 232: return new DecodedChar(pos + 8, '!');
case 233: return new DecodedChar(pos + 8, '"');
case 234: return new DecodedChar(pos + 8, '%');
case 235: return new DecodedChar(pos + 8, '&');
case 236: return new DecodedChar(pos + 8, '\'');
case 237: return new DecodedChar(pos + 8, '(');
case 238: return new DecodedChar(pos + 8, ')');
case 239: return new DecodedChar(pos + 8, '*');
case 240: return new DecodedChar(pos + 8, '+');
case 241: return new DecodedChar(pos + 8, ',');
case 242: return new DecodedChar(pos + 8, '-');
case 243: return new DecodedChar(pos + 8, '.');
case 244: return new DecodedChar(pos + 8, '/');
case 245: return new DecodedChar(pos + 8, ':');
case 246: return new DecodedChar(pos + 8, ';');
case 247: return new DecodedChar(pos + 8, '<');
case 248: return new DecodedChar(pos + 8, '=');
case 249: return new DecodedChar(pos + 8, '>');
case 250: return new DecodedChar(pos + 8, '?');
case 251: return new DecodedChar(pos + 8, '_');
case 252: return new DecodedChar(pos + 8, ' ');
}
throw new RuntimeException("Decoding invalid ISO/IEC 646 value: " + eightBitValue);
}
private boolean isStillAlpha(int pos) {
if(pos + 5 > this.information.size) {
return false;
}
// We now check if it's a valid 5-bit value (0..9 and FNC1)
int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
if(fiveBitValue >= 5 && fiveBitValue < 16) {
return true;
}
if(pos + 6 > this.information.size) {
return false;
}
int sixBitValue = extractNumericValueFromBitArray(pos, 6);
return sixBitValue >= 16 && sixBitValue < 63; // 63 not included
}
private DecodedChar decodeAlphanumeric(int pos) {
int fiveBitValue = extractNumericValueFromBitArray(pos, 5);
if(fiveBitValue == 15) {
return new DecodedChar(pos + 5, DecodedChar.FNC1);
}
if(fiveBitValue >= 5 && fiveBitValue < 15) {
return new DecodedChar(pos + 5, (char) ('0' + fiveBitValue - 5));
}
int sixBitValue = extractNumericValueFromBitArray(pos, 6);
if(sixBitValue >= 32 && sixBitValue < 58) {
return new DecodedChar(pos + 6, (char) (sixBitValue + 33));
}
switch(sixBitValue){
case 58: return new DecodedChar(pos + 6, '*');
case 59: return new DecodedChar(pos + 6, ',');
case 60: return new DecodedChar(pos + 6, '-');
case 61: return new DecodedChar(pos + 6, '.');
case 62: return new DecodedChar(pos + 6, '/');
}
throw new RuntimeException("Decoding invalid alphanumeric value: " + sixBitValue);
}
private boolean isAlphaTo646ToAlphaLatch(int pos) {
if(pos + 1 > this.information.size) {
return false;
}
for(int i = 0; i < 5 && i + pos < this.information.size; ++i){
if(i == 2){
if(!this.information.get(pos + 2)) {
return false;
}
} else if(this.information.get(pos + i)) {
return false;
}
}
return true;
}
private boolean isAlphaOr646ToNumericLatch(int pos) {
// Next is alphanumeric if there are 3 positions and they are all zeros
if (pos + 3 > this.information.size) {
return false;
}
for (int i = pos; i < pos + 3; ++i) {
if (this.information.get(i)) {
return false;
}
}
return true;
}
private boolean isNumericToAlphaNumericLatch(int pos) {
// Next is alphanumeric if there are 4 positions and they are all zeros, or
// if there is a subset of this just before the end of the symbol
if (pos + 1 > this.information.size) {
return false;
}
for (int i = 0; i < 4 && i + pos < this.information.size; ++i) {
if (this.information.get(pos + i)) {
return false;
}
}
return true;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1 @@
(11)100224(17)110224(3102)000100

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

View file

@ -0,0 +1 @@
(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456(423)012345678901

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 B

View file

@ -0,0 +1 @@
(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -0,0 +1 @@
(01)98898765432106(3103)001750

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

View file

@ -0,0 +1 @@
(01)90012345678908(3922)795

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

View file

@ -0,0 +1 @@
(01)90012345678908(3932)0401234

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3102)001750(11)100312

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3202)001750(11)100312

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3102)001750(13)100312

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3202)001750(13)100312

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3102)001750(15)100312

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3103)001750

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3202)001750(15)100312

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3102)001750(17)100312

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1 @@
(01)90012345678908(3202)001750(17)100312

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

View file

@ -0,0 +1 @@
(10)56789(11)010101

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

View file

@ -0,0 +1 @@
(10)567890(11)010101

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

View file

@ -0,0 +1 @@
(10)123

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

View file

@ -0,0 +1 @@
(10)5678(11)010101

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

View file

@ -0,0 +1 @@
(10)1098-1234

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

View file

@ -0,0 +1 @@
(10)1098/1234

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

View file

@ -0,0 +1 @@
(10)1098.1234

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -0,0 +1 @@
(10)12A

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

View file

@ -0,0 +1 @@
(10)1098*1234

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

View file

@ -0,0 +1 @@
(10)1098,1234

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

View file

@ -0,0 +1 @@
(15)991231(3103)001750(10)12A(422)123(21)123456(423)0123456789012

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -0,0 +1 @@
(01)98898765432106(3202)012345(15)991231

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View file

@ -0,0 +1 @@
(01)90614141000015(3202)000150

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

View file

@ -0,0 +1 @@
(10)567(01)90012345678908(11)010101

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

View file

@ -0,0 +1 @@
(10)567(11)010101

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

View file

@ -0,0 +1 @@
(10)567(11)010101(13)010101

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

View file

@ -0,0 +1 @@
(10)567(3102)123456

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

View file

@ -0,0 +1 @@
(01)98898765432106(3103)001750

Some files were not shown because too many files have changed in this diff Show more