[SCM] Multi-format 1D/2D barcode image processing library branch, upstream, updated. 24d4480bc48cf9eabf7b2bd2f528248b0e458809

srowen srowen at 59b500cc-1b3d-0410-9834-0bbf25fbcc57
Wed Aug 4 01:31:28 UTC 2010


The following commit has been merged in the upstream branch:
commit 1366f61518b0914bfdc8eff8bcbd863e780e3ffc
Author: srowen <srowen at 59b500cc-1b3d-0410-9834-0bbf25fbcc57>
Date:   Mon May 10 19:18:50 2010 +0000

    Big RSS Expanded changelist -- thank you authors
    
    git-svn-id: http://zxing.googlecode.com/svn/trunk@1350 59b500cc-1b3d-0410-9834-0bbf25fbcc57

diff --git a/AUTHORS b/AUTHORS
index 34401e7..cd9f5a8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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
diff --git a/core/src/com/google/zxing/BarcodeFormat.java b/core/src/com/google/zxing/BarcodeFormat.java
index 360baf7..d4e1e70 100644
--- a/core/src/com/google/zxing/BarcodeFormat.java
+++ b/core/src/com/google/zxing/BarcodeFormat.java
@@ -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;
   }
 
-}
\ No newline at end of file
+}
diff --git a/core/src/com/google/zxing/MultiFormatReader.java b/core/src/com/google/zxing/MultiFormatReader.java
index 6685882..c198021 100644
--- a/core/src/com/google/zxing/MultiFormatReader.java
+++ b/core/src/com/google/zxing/MultiFormatReader.java
@@ -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));
diff --git a/core/src/com/google/zxing/client/result/ExpandedProductParsedResult.java b/core/src/com/google/zxing/client/result/ExpandedProductParsedResult.java
new file mode 100644
index 0000000..a5cd3dc
--- /dev/null
+++ b/core/src/com/google/zxing/client/result/ExpandedProductParsedResult.java
@@ -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;
+  }
+}
diff --git a/core/src/com/google/zxing/client/result/ExpandedProductResultParser.java b/core/src/com/google/zxing/client/result/ExpandedProductResultParser.java
new file mode 100644
index 0000000..3e3fd51
--- /dev/null
+++ b/core/src/com/google/zxing/client/result/ExpandedProductResultParser.java
@@ -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();
+  }
+}
diff --git a/core/src/com/google/zxing/client/result/ResultParser.java b/core/src/com/google/zxing/client/result/ResultParser.java
index ce29b55..f1b3476 100644
--- a/core/src/com/google/zxing/client/result/ResultParser.java
+++ b/core/src/com/google/zxing/client/result/ResultParser.java
@@ -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);
   }
diff --git a/core/src/com/google/zxing/oned/MultiFormatOneDReader.java b/core/src/com/google/zxing/oned/MultiFormatOneDReader.java
index bc1d313..ccf63dd 100644
--- a/core/src/com/google/zxing/oned/MultiFormatOneDReader.java
+++ b/core/src/com/google/zxing/oned/MultiFormatOneDReader.java
@@ -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());      
     }
   }
 
diff --git a/core/src/com/google/zxing/oned/rss/AbstractRSSReader.java b/core/src/com/google/zxing/oned/rss/AbstractRSSReader.java
new file mode 100644
index 0000000..fce9e83
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/AbstractRSSReader.java
@@ -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;
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/DataCharacter.java b/core/src/com/google/zxing/oned/rss/DataCharacter.java
index a6e5a05..9b5e311 100644
--- a/core/src/com/google/zxing/oned/rss/DataCharacter.java
+++ b/core/src/com/google/zxing/oned/rss/DataCharacter.java
@@ -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;
   }
 
-}
\ No newline at end of file
+}
diff --git a/core/src/com/google/zxing/oned/rss/FinderPattern.java b/core/src/com/google/zxing/oned/rss/FinderPattern.java
index d1139b3..afc1a13 100644
--- a/core/src/com/google/zxing/oned/rss/FinderPattern.java
+++ b/core/src/com/google/zxing/oned/rss/FinderPattern.java
@@ -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;
   }
 
diff --git a/core/src/com/google/zxing/oned/rss/RSS14Reader.java b/core/src/com/google/zxing/oned/rss/RSS14Reader.java
index 941107a..1c99ac1 100644
--- a/core/src/com/google/zxing/oned/rss/RSS14Reader.java
+++ b/core/src/com/google/zxing/oned/rss/RSS14Reader.java
@@ -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);
diff --git a/core/src/com/google/zxing/oned/rss/RSSUtils.java b/core/src/com/google/zxing/oned/rss/RSSUtils.java
index f632439..6977fc2 100644
--- a/core/src/com/google/zxing/oned/rss/RSSUtils.java
+++ b/core/src/com/google/zxing/oned/rss/RSSUtils.java
@@ -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++) {
diff --git a/core/src/com/google/zxing/oned/rss/expanded/BitArrayBuilder.java b/core/src/com/google/zxing/oned/rss/expanded/BitArrayBuilder.java
new file mode 100644
index 0000000..0a78b8f
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/BitArrayBuilder.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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;
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/ExpandedPair.java b/core/src/com/google/zxing/oned/rss/expanded/ExpandedPair.java
new file mode 100644
index 0000000..cde1d02
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/ExpandedPair.java
@@ -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 at 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;
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java b/core/src/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java
new file mode 100644
index 0000000..d9c822a
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/RSSExpandedReader.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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);
+    }
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013103decoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013103decoder.java
new file mode 100644
index 0000000..5ef3fed
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013103decoder.java
@@ -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 at 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;
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01320xDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01320xDecoder.java
new file mode 100644
index 0000000..1fd7c0e
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01320xDecoder.java
@@ -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 at 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;
+  }
+
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01392xDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01392xDecoder.java
new file mode 100644
index 0000000..e618d81
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01392xDecoder.java
@@ -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 at 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();
+  }
+
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01393xDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01393xDecoder.java
new file mode 100644
index 0000000..67db980
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01393xDecoder.java
@@ -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 at 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();
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013x0x1xDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013x0x1xDecoder.java
new file mode 100644
index 0000000..0c373c3
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013x0x1xDecoder.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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;
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013x0xDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013x0xDecoder.java
new file mode 100644
index 0000000..96bdaff
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI013x0xDecoder.java
@@ -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 at 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();
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01AndOtherAIs.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01AndOtherAIs.java
new file mode 100644
index 0000000..49f109b
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01AndOtherAIs.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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);
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01decoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01decoder.java
new file mode 100644
index 0000000..62f878b
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01decoder.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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);
+  }
+
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01weightDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01weightDecoder.java
new file mode 100644
index 0000000..f120cc0
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AI01weightDecoder.java
@@ -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 at 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);
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AbstractExpandedDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AbstractExpandedDecoder.java
new file mode 100644
index 0000000..84fae37
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AbstractExpandedDecoder.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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);
+  }
+
+
+
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoder.java
new file mode 100644
index 0000000..4fcac27
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoder.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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);
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/BlockParsedResult.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/BlockParsedResult.java
new file mode 100644
index 0000000..132ba55
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/BlockParsedResult.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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;
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/CurrentParsingState.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/CurrentParsingState.java
new file mode 100644
index 0000000..cf7d687
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/CurrentParsingState.java
@@ -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 at 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;
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedChar.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedChar.java
new file mode 100644
index 0000000..790b684
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedChar.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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;
+  }
+
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedInformation.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedInformation.java
new file mode 100644
index 0000000..13eec5c
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedInformation.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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;
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedNumeric.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedNumeric.java
new file mode 100644
index 0000000..1b1be42
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedNumeric.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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;
+  }
+
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedObject.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedObject.java
new file mode 100644
index 0000000..7547384
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/DecodedObject.java
@@ -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 at deusto.es)
+ */
+abstract class DecodedObject {
+
+  protected final int newPosition;
+
+  DecodedObject(int newPosition){
+    this.newPosition = newPosition;
+  }
+
+  int getNewPosition() {
+    return this.newPosition;
+  }
+
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/FieldParser.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/FieldParser.java
new file mode 100644
index 0000000..91c1d49
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/FieldParser.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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);
+  }
+}
diff --git a/core/src/com/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java b/core/src/com/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java
new file mode 100644
index 0000000..821fbc4
--- /dev/null
+++ b/core/src/com/google/zxing/oned/rss/expanded/decoders/GeneralAppIdDecoder.java
@@ -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 at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at 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;
+  }
+}
diff --git a/core/test/data/blackbox/rssexpanded-1/1.jpg b/core/test/data/blackbox/rssexpanded-1/1.jpg
new file mode 100644
index 0000000..3978c7f
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/1.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/1.txt b/core/test/data/blackbox/rssexpanded-1/1.txt
new file mode 100644
index 0000000..8b369b3
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/1.txt
@@ -0,0 +1 @@
+(11)100224(17)110224(3102)000100
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/10.png b/core/test/data/blackbox/rssexpanded-1/10.png
new file mode 100644
index 0000000..4c290bc
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/10.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/10.txt b/core/test/data/blackbox/rssexpanded-1/10.txt
new file mode 100644
index 0000000..09d4208
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/10.txt
@@ -0,0 +1 @@
+(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456(423)012345678901
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/11.png b/core/test/data/blackbox/rssexpanded-1/11.png
new file mode 100644
index 0000000..39a67ce
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/11.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/11.txt b/core/test/data/blackbox/rssexpanded-1/11.txt
new file mode 100644
index 0000000..abe2a81
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/11.txt
@@ -0,0 +1 @@
+(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/12.jpg b/core/test/data/blackbox/rssexpanded-1/12.jpg
new file mode 100644
index 0000000..4d0eeef
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/12.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/12.txt b/core/test/data/blackbox/rssexpanded-1/12.txt
new file mode 100644
index 0000000..32ad2da
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/12.txt
@@ -0,0 +1 @@
+(01)98898765432106(3103)001750
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/13.png b/core/test/data/blackbox/rssexpanded-1/13.png
new file mode 100644
index 0000000..5efd2c7
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/13.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/13.txt b/core/test/data/blackbox/rssexpanded-1/13.txt
new file mode 100644
index 0000000..dd36aab
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/13.txt
@@ -0,0 +1 @@
+(01)90012345678908(3922)795
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/14.png b/core/test/data/blackbox/rssexpanded-1/14.png
new file mode 100644
index 0000000..1f5ad05
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/14.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/14.txt b/core/test/data/blackbox/rssexpanded-1/14.txt
new file mode 100644
index 0000000..fb00e31
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/14.txt
@@ -0,0 +1 @@
+(01)90012345678908(3932)0401234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/15.jpg b/core/test/data/blackbox/rssexpanded-1/15.jpg
new file mode 100644
index 0000000..e7c7550
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/15.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/15.txt b/core/test/data/blackbox/rssexpanded-1/15.txt
new file mode 100644
index 0000000..f2bfc4b
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/15.txt
@@ -0,0 +1 @@
+(01)90012345678908(3102)001750(11)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/16.jpg b/core/test/data/blackbox/rssexpanded-1/16.jpg
new file mode 100644
index 0000000..11c21b2
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/16.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/16.txt b/core/test/data/blackbox/rssexpanded-1/16.txt
new file mode 100644
index 0000000..c9f248d
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/16.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)001750(11)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/17.jpg b/core/test/data/blackbox/rssexpanded-1/17.jpg
new file mode 100644
index 0000000..4a29b41
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/17.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/17.txt b/core/test/data/blackbox/rssexpanded-1/17.txt
new file mode 100644
index 0000000..9b4fc49
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/17.txt
@@ -0,0 +1 @@
+(01)90012345678908(3102)001750(13)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/18.jpg b/core/test/data/blackbox/rssexpanded-1/18.jpg
new file mode 100644
index 0000000..8fc343f
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/18.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/18.txt b/core/test/data/blackbox/rssexpanded-1/18.txt
new file mode 100644
index 0000000..cd15aa0
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/18.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)001750(13)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/19.jpg b/core/test/data/blackbox/rssexpanded-1/19.jpg
new file mode 100644
index 0000000..0e823bd
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/19.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/19.txt b/core/test/data/blackbox/rssexpanded-1/19.txt
new file mode 100644
index 0000000..dcd1561
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/19.txt
@@ -0,0 +1 @@
+(01)90012345678908(3102)001750(15)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/2.jpg b/core/test/data/blackbox/rssexpanded-1/2.jpg
new file mode 100644
index 0000000..693dd77
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/2.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/2.txt b/core/test/data/blackbox/rssexpanded-1/2.txt
new file mode 100644
index 0000000..b4113ac
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/2.txt
@@ -0,0 +1 @@
+(01)90012345678908(3103)001750
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/20.jpg b/core/test/data/blackbox/rssexpanded-1/20.jpg
new file mode 100644
index 0000000..eb96e4e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/20.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/20.txt b/core/test/data/blackbox/rssexpanded-1/20.txt
new file mode 100644
index 0000000..830845f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/20.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)001750(15)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/21.jpg b/core/test/data/blackbox/rssexpanded-1/21.jpg
new file mode 100644
index 0000000..4901903
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/21.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/21.txt b/core/test/data/blackbox/rssexpanded-1/21.txt
new file mode 100644
index 0000000..506b17b
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/21.txt
@@ -0,0 +1 @@
+(01)90012345678908(3102)001750(17)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/22.jpg b/core/test/data/blackbox/rssexpanded-1/22.jpg
new file mode 100644
index 0000000..6ec7052
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/22.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/22.txt b/core/test/data/blackbox/rssexpanded-1/22.txt
new file mode 100644
index 0000000..ca6045a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/22.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)001750(17)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/23.png b/core/test/data/blackbox/rssexpanded-1/23.png
new file mode 100644
index 0000000..8919afa
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/23.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/23.txt b/core/test/data/blackbox/rssexpanded-1/23.txt
new file mode 100644
index 0000000..a6f7e24
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/23.txt
@@ -0,0 +1 @@
+(10)56789(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/24.png b/core/test/data/blackbox/rssexpanded-1/24.png
new file mode 100644
index 0000000..aabea10
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/24.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/24.txt b/core/test/data/blackbox/rssexpanded-1/24.txt
new file mode 100644
index 0000000..a7b3497
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/24.txt
@@ -0,0 +1 @@
+(10)567890(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/25.png b/core/test/data/blackbox/rssexpanded-1/25.png
new file mode 100644
index 0000000..cd52c3d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/25.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/25.txt b/core/test/data/blackbox/rssexpanded-1/25.txt
new file mode 100644
index 0000000..62c17f1
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/25.txt
@@ -0,0 +1 @@
+(10)123
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/26.png b/core/test/data/blackbox/rssexpanded-1/26.png
new file mode 100644
index 0000000..40f069c
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/26.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/26.txt b/core/test/data/blackbox/rssexpanded-1/26.txt
new file mode 100644
index 0000000..17966ee
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/26.txt
@@ -0,0 +1 @@
+(10)5678(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/27.png b/core/test/data/blackbox/rssexpanded-1/27.png
new file mode 100644
index 0000000..a541ca2
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/27.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/27.txt b/core/test/data/blackbox/rssexpanded-1/27.txt
new file mode 100644
index 0000000..5263f7f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/27.txt
@@ -0,0 +1 @@
+(10)1098-1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/28.png b/core/test/data/blackbox/rssexpanded-1/28.png
new file mode 100644
index 0000000..d03f073
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/28.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/28.txt b/core/test/data/blackbox/rssexpanded-1/28.txt
new file mode 100644
index 0000000..9208d92
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/28.txt
@@ -0,0 +1 @@
+(10)1098/1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/29.png b/core/test/data/blackbox/rssexpanded-1/29.png
new file mode 100644
index 0000000..9467691
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/29.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/29.txt b/core/test/data/blackbox/rssexpanded-1/29.txt
new file mode 100644
index 0000000..b78623a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/29.txt
@@ -0,0 +1 @@
+(10)1098.1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/3.jpg b/core/test/data/blackbox/rssexpanded-1/3.jpg
new file mode 100644
index 0000000..ce50ee5
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/3.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/3.txt b/core/test/data/blackbox/rssexpanded-1/3.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/3.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/30.png b/core/test/data/blackbox/rssexpanded-1/30.png
new file mode 100644
index 0000000..5468dc9
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/30.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/30.txt b/core/test/data/blackbox/rssexpanded-1/30.txt
new file mode 100644
index 0000000..82bfa6a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/30.txt
@@ -0,0 +1 @@
+(10)1098*1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/31.png b/core/test/data/blackbox/rssexpanded-1/31.png
new file mode 100644
index 0000000..eb00f82
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/31.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/31.txt b/core/test/data/blackbox/rssexpanded-1/31.txt
new file mode 100644
index 0000000..f6413d5
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/31.txt
@@ -0,0 +1 @@
+(10)1098,1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/32.png b/core/test/data/blackbox/rssexpanded-1/32.png
new file mode 100644
index 0000000..a94dcfc
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/32.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/32.txt b/core/test/data/blackbox/rssexpanded-1/32.txt
new file mode 100644
index 0000000..5e76631
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/32.txt
@@ -0,0 +1 @@
+(15)991231(3103)001750(10)12A(422)123(21)123456(423)0123456789012
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/4.jpg b/core/test/data/blackbox/rssexpanded-1/4.jpg
new file mode 100644
index 0000000..8aa8b14
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/4.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/4.txt b/core/test/data/blackbox/rssexpanded-1/4.txt
new file mode 100644
index 0000000..4e8655c
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/4.txt
@@ -0,0 +1 @@
+(01)98898765432106(3202)012345(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/5.jpg b/core/test/data/blackbox/rssexpanded-1/5.jpg
new file mode 100644
index 0000000..8d42ad4
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/5.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-1/5.txt b/core/test/data/blackbox/rssexpanded-1/5.txt
new file mode 100644
index 0000000..4a70860
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/5.txt
@@ -0,0 +1 @@
+(01)90614141000015(3202)000150
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/6.png b/core/test/data/blackbox/rssexpanded-1/6.png
new file mode 100644
index 0000000..393eac3
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/6.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/6.txt b/core/test/data/blackbox/rssexpanded-1/6.txt
new file mode 100644
index 0000000..84f8807
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/6.txt
@@ -0,0 +1 @@
+(10)567(01)90012345678908(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/7.png b/core/test/data/blackbox/rssexpanded-1/7.png
new file mode 100644
index 0000000..818a86b
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/7.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/7.txt b/core/test/data/blackbox/rssexpanded-1/7.txt
new file mode 100644
index 0000000..e8c7268
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/7.txt
@@ -0,0 +1 @@
+(10)567(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/8.png b/core/test/data/blackbox/rssexpanded-1/8.png
new file mode 100644
index 0000000..b09e5a9
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/8.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/8.txt b/core/test/data/blackbox/rssexpanded-1/8.txt
new file mode 100644
index 0000000..56981cd
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/8.txt
@@ -0,0 +1 @@
+(10)567(11)010101(13)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-1/9.png b/core/test/data/blackbox/rssexpanded-1/9.png
new file mode 100644
index 0000000..12f2594
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-1/9.png differ
diff --git a/core/test/data/blackbox/rssexpanded-1/9.txt b/core/test/data/blackbox/rssexpanded-1/9.txt
new file mode 100644
index 0000000..84cf63c
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-1/9.txt
@@ -0,0 +1 @@
+(10)567(3102)123456
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/12.jpg b/core/test/data/blackbox/rssexpanded-2/12.jpg
new file mode 100644
index 0000000..4750557
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/12.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/12.txt b/core/test/data/blackbox/rssexpanded-2/12.txt
new file mode 100644
index 0000000..32ad2da
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/12.txt
@@ -0,0 +1 @@
+(01)98898765432106(3103)001750
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/13.jpg b/core/test/data/blackbox/rssexpanded-2/13.jpg
new file mode 100644
index 0000000..8ed2841
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/13.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/13.txt b/core/test/data/blackbox/rssexpanded-2/13.txt
new file mode 100644
index 0000000..dd36aab
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/13.txt
@@ -0,0 +1 @@
+(01)90012345678908(3922)795
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/16.jpg b/core/test/data/blackbox/rssexpanded-2/16.jpg
new file mode 100644
index 0000000..cda424c
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/16.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/16.txt b/core/test/data/blackbox/rssexpanded-2/16.txt
new file mode 100644
index 0000000..c9f248d
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/16.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)001750(11)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/17.jpg b/core/test/data/blackbox/rssexpanded-2/17.jpg
new file mode 100644
index 0000000..7601179
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/17.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/17.txt b/core/test/data/blackbox/rssexpanded-2/17.txt
new file mode 100644
index 0000000..9b4fc49
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/17.txt
@@ -0,0 +1 @@
+(01)90012345678908(3102)001750(13)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/18.jpg b/core/test/data/blackbox/rssexpanded-2/18.jpg
new file mode 100644
index 0000000..f1f60c6
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/18.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/18.txt b/core/test/data/blackbox/rssexpanded-2/18.txt
new file mode 100644
index 0000000..cd15aa0
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/18.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)001750(13)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/18b.jpg b/core/test/data/blackbox/rssexpanded-2/18b.jpg
new file mode 100644
index 0000000..1872739
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/18b.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/18b.txt b/core/test/data/blackbox/rssexpanded-2/18b.txt
new file mode 100644
index 0000000..cd15aa0
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/18b.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)001750(13)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/19.jpg b/core/test/data/blackbox/rssexpanded-2/19.jpg
new file mode 100644
index 0000000..37db6cb
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/19.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/19.txt b/core/test/data/blackbox/rssexpanded-2/19.txt
new file mode 100644
index 0000000..dcd1561
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/19.txt
@@ -0,0 +1 @@
+(01)90012345678908(3102)001750(15)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/21.jpg b/core/test/data/blackbox/rssexpanded-2/21.jpg
new file mode 100644
index 0000000..e4ef2f2
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/21.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/21.txt b/core/test/data/blackbox/rssexpanded-2/21.txt
new file mode 100644
index 0000000..506b17b
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/21.txt
@@ -0,0 +1 @@
+(01)90012345678908(3102)001750(17)100312
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/3_01.jpg b/core/test/data/blackbox/rssexpanded-2/3_01.jpg
new file mode 100644
index 0000000..69b91e6
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/3_01.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/3_01.txt b/core/test/data/blackbox/rssexpanded-2/3_01.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/3_01.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/3_02.jpg b/core/test/data/blackbox/rssexpanded-2/3_02.jpg
new file mode 100644
index 0000000..7c386dd
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/3_02.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/3_02.txt b/core/test/data/blackbox/rssexpanded-2/3_02.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/3_02.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/3_03.jpg b/core/test/data/blackbox/rssexpanded-2/3_03.jpg
new file mode 100644
index 0000000..a8b2e50
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/3_03.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/3_03.txt b/core/test/data/blackbox/rssexpanded-2/3_03.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/3_03.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/3_04.jpg b/core/test/data/blackbox/rssexpanded-2/3_04.jpg
new file mode 100644
index 0000000..80c048d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/3_04.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/3_04.txt b/core/test/data/blackbox/rssexpanded-2/3_04.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/3_04.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/3_05.jpg b/core/test/data/blackbox/rssexpanded-2/3_05.jpg
new file mode 100644
index 0000000..fce80e0
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/3_05.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/3_05.txt b/core/test/data/blackbox/rssexpanded-2/3_05.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/3_05.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/3_06.jpg b/core/test/data/blackbox/rssexpanded-2/3_06.jpg
new file mode 100644
index 0000000..9a012bd
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/3_06.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/3_06.txt b/core/test/data/blackbox/rssexpanded-2/3_06.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/3_06.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/3_07.jpg b/core/test/data/blackbox/rssexpanded-2/3_07.jpg
new file mode 100644
index 0000000..8f66489
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/3_07.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/3_07.txt b/core/test/data/blackbox/rssexpanded-2/3_07.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/3_07.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/3_09.jpg b/core/test/data/blackbox/rssexpanded-2/3_09.jpg
new file mode 100644
index 0000000..2f5a460
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/3_09.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/3_09.txt b/core/test/data/blackbox/rssexpanded-2/3_09.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/3_09.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/4_00.jpg b/core/test/data/blackbox/rssexpanded-2/4_00.jpg
new file mode 100644
index 0000000..b6bfafa
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/4_00.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/4_00.txt b/core/test/data/blackbox/rssexpanded-2/4_00.txt
new file mode 100644
index 0000000..4e8655c
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/4_00.txt
@@ -0,0 +1 @@
+(01)98898765432106(3202)012345(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/4_01.jpg b/core/test/data/blackbox/rssexpanded-2/4_01.jpg
new file mode 100644
index 0000000..bed2601
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/4_01.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/4_01.txt b/core/test/data/blackbox/rssexpanded-2/4_01.txt
new file mode 100644
index 0000000..4e8655c
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/4_01.txt
@@ -0,0 +1 @@
+(01)98898765432106(3202)012345(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/4_02.jpg b/core/test/data/blackbox/rssexpanded-2/4_02.jpg
new file mode 100644
index 0000000..be1b66c
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/4_02.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/4_02.txt b/core/test/data/blackbox/rssexpanded-2/4_02.txt
new file mode 100644
index 0000000..4e8655c
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/4_02.txt
@@ -0,0 +1 @@
+(01)98898765432106(3202)012345(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/4_03.jpg b/core/test/data/blackbox/rssexpanded-2/4_03.jpg
new file mode 100644
index 0000000..d48028f
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/4_03.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/4_03.txt b/core/test/data/blackbox/rssexpanded-2/4_03.txt
new file mode 100644
index 0000000..4e8655c
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/4_03.txt
@@ -0,0 +1 @@
+(01)98898765432106(3202)012345(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/4_04.jpg b/core/test/data/blackbox/rssexpanded-2/4_04.jpg
new file mode 100644
index 0000000..2e64ec9
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/4_04.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/4_04.txt b/core/test/data/blackbox/rssexpanded-2/4_04.txt
new file mode 100644
index 0000000..4e8655c
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/4_04.txt
@@ -0,0 +1 @@
+(01)98898765432106(3202)012345(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/4_05.jpg b/core/test/data/blackbox/rssexpanded-2/4_05.jpg
new file mode 100644
index 0000000..1800a4e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/4_05.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/4_05.txt b/core/test/data/blackbox/rssexpanded-2/4_05.txt
new file mode 100644
index 0000000..4e8655c
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/4_05.txt
@@ -0,0 +1 @@
+(01)98898765432106(3202)012345(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-2/5.jpg b/core/test/data/blackbox/rssexpanded-2/5.jpg
new file mode 100644
index 0000000..204fa18
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-2/5.jpg differ
diff --git a/core/test/data/blackbox/rssexpanded-2/5.txt b/core/test/data/blackbox/rssexpanded-2/5.txt
new file mode 100644
index 0000000..4a70860
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-2/5.txt
@@ -0,0 +1 @@
+(01)90614141000015(3202)000150
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/1.png b/core/test/data/blackbox/rssexpanded-3/1.png
new file mode 100644
index 0000000..9a7769d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/1.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/1.txt b/core/test/data/blackbox/rssexpanded-3/1.txt
new file mode 100644
index 0000000..ed31c4d
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/1.txt
@@ -0,0 +1 @@
+(01)90012345678908(3103)012233(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/10.png b/core/test/data/blackbox/rssexpanded-3/10.png
new file mode 100644
index 0000000..bd28d8a
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/10.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/10.txt b/core/test/data/blackbox/rssexpanded-3/10.txt
new file mode 100644
index 0000000..e8f98fe
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/10.txt
@@ -0,0 +1 @@
+(01)90012345678908(3203)010000
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/100.png b/core/test/data/blackbox/rssexpanded-3/100.png
new file mode 100644
index 0000000..93dc882
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/100.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/100.txt b/core/test/data/blackbox/rssexpanded-3/100.txt
new file mode 100644
index 0000000..4339de9
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/100.txt
@@ -0,0 +1 @@
+(10)1098 1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/101.png b/core/test/data/blackbox/rssexpanded-3/101.png
new file mode 100644
index 0000000..e9cdd7a
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/101.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/101.txt b/core/test/data/blackbox/rssexpanded-3/101.txt
new file mode 100644
index 0000000..6f63fb0
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/101.txt
@@ -0,0 +1 @@
+(10)123456A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/102.png b/core/test/data/blackbox/rssexpanded-3/102.png
new file mode 100644
index 0000000..dd68bdf
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/102.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/102.txt b/core/test/data/blackbox/rssexpanded-3/102.txt
new file mode 100644
index 0000000..5c1b912
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/102.txt
@@ -0,0 +1 @@
+(10)123456A1
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/103.png b/core/test/data/blackbox/rssexpanded-3/103.png
new file mode 100644
index 0000000..519e39a
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/103.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/103.txt b/core/test/data/blackbox/rssexpanded-3/103.txt
new file mode 100644
index 0000000..d77a476
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/103.txt
@@ -0,0 +1 @@
+(10)123456A123
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/104.png b/core/test/data/blackbox/rssexpanded-3/104.png
new file mode 100644
index 0000000..a585805
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/104.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/104.txt b/core/test/data/blackbox/rssexpanded-3/104.txt
new file mode 100644
index 0000000..2e2ec43
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/104.txt
@@ -0,0 +1 @@
+(10)123456A1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/105.png b/core/test/data/blackbox/rssexpanded-3/105.png
new file mode 100644
index 0000000..97948c1
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/105.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/105.txt b/core/test/data/blackbox/rssexpanded-3/105.txt
new file mode 100644
index 0000000..b607d14
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/105.txt
@@ -0,0 +1 @@
+(10)123456A1234A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/106.png b/core/test/data/blackbox/rssexpanded-3/106.png
new file mode 100644
index 0000000..3965788
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/106.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/106.txt b/core/test/data/blackbox/rssexpanded-3/106.txt
new file mode 100644
index 0000000..389adca
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/106.txt
@@ -0,0 +1 @@
+(10)123456A123456
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/107.png b/core/test/data/blackbox/rssexpanded-3/107.png
new file mode 100644
index 0000000..5bb7801
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/107.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/107.txt b/core/test/data/blackbox/rssexpanded-3/107.txt
new file mode 100644
index 0000000..fffde5d
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/107.txt
@@ -0,0 +1 @@
+(10)123456A12345678
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/108.png b/core/test/data/blackbox/rssexpanded-3/108.png
new file mode 100644
index 0000000..d705f80
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/108.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/108.txt b/core/test/data/blackbox/rssexpanded-3/108.txt
new file mode 100644
index 0000000..1ad0fbd
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/108.txt
@@ -0,0 +1 @@
+(10)123456A1234A(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/109.png b/core/test/data/blackbox/rssexpanded-3/109.png
new file mode 100644
index 0000000..ee52aae
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/109.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/109.txt b/core/test/data/blackbox/rssexpanded-3/109.txt
new file mode 100644
index 0000000..ac79617
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/109.txt
@@ -0,0 +1 @@
+(10)1ABCDEF;:/1234567
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/11.png b/core/test/data/blackbox/rssexpanded-3/11.png
new file mode 100644
index 0000000..eb18d4e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/11.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/11.txt b/core/test/data/blackbox/rssexpanded-3/11.txt
new file mode 100644
index 0000000..9895a67
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/11.txt
@@ -0,0 +1 @@
+(01)90012345678908(3203)032767
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/110.png b/core/test/data/blackbox/rssexpanded-3/110.png
new file mode 100644
index 0000000..9c6ce73
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/110.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/110.txt b/core/test/data/blackbox/rssexpanded-3/110.txt
new file mode 100644
index 0000000..163b64b
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/110.txt
@@ -0,0 +1 @@
+(10)1ABCDEF;:/ABCDEFG
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/111.png b/core/test/data/blackbox/rssexpanded-3/111.png
new file mode 100644
index 0000000..216d52e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/111.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/111.txt b/core/test/data/blackbox/rssexpanded-3/111.txt
new file mode 100644
index 0000000..d359328
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/111.txt
@@ -0,0 +1 @@
+(10)1;:/ABCDEFGHIJKLM
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/112.png b/core/test/data/blackbox/rssexpanded-3/112.png
new file mode 100644
index 0000000..da42a90
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/112.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/112.txt b/core/test/data/blackbox/rssexpanded-3/112.txt
new file mode 100644
index 0000000..c25e84f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/112.txt
@@ -0,0 +1 @@
+(10)1;:/0123456789012
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/113.png b/core/test/data/blackbox/rssexpanded-3/113.png
new file mode 100644
index 0000000..5ab0ae5
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/113.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/113.txt b/core/test/data/blackbox/rssexpanded-3/113.txt
new file mode 100644
index 0000000..2914766
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/113.txt
@@ -0,0 +1 @@
+(10)1;:/0123
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/114.png b/core/test/data/blackbox/rssexpanded-3/114.png
new file mode 100644
index 0000000..8ab1daa
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/114.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/114.txt b/core/test/data/blackbox/rssexpanded-3/114.txt
new file mode 100644
index 0000000..c8be9f3
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/114.txt
@@ -0,0 +1 @@
+(10)1;:/0123(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/115.png b/core/test/data/blackbox/rssexpanded-3/115.png
new file mode 100644
index 0000000..2a89b68
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/115.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/115.txt b/core/test/data/blackbox/rssexpanded-3/115.txt
new file mode 100644
index 0000000..9a1581d
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/115.txt
@@ -0,0 +1 @@
+(10)1
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/116.png b/core/test/data/blackbox/rssexpanded-3/116.png
new file mode 100644
index 0000000..152483d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/116.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/116.txt b/core/test/data/blackbox/rssexpanded-3/116.txt
new file mode 100644
index 0000000..4c3769f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/116.txt
@@ -0,0 +1 @@
+(10)12A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/117.png b/core/test/data/blackbox/rssexpanded-3/117.png
new file mode 100644
index 0000000..cd52c3d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/117.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/117.txt b/core/test/data/blackbox/rssexpanded-3/117.txt
new file mode 100644
index 0000000..62c17f1
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/117.txt
@@ -0,0 +1 @@
+(10)123
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/12.png b/core/test/data/blackbox/rssexpanded-3/12.png
new file mode 100644
index 0000000..f9abacc
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/12.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/12.txt b/core/test/data/blackbox/rssexpanded-3/12.txt
new file mode 100644
index 0000000..dd36aab
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/12.txt
@@ -0,0 +1 @@
+(01)90012345678908(3922)795
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/13.png b/core/test/data/blackbox/rssexpanded-3/13.png
new file mode 100644
index 0000000..7fdf61d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/13.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/13.txt b/core/test/data/blackbox/rssexpanded-3/13.txt
new file mode 100644
index 0000000..0429d93
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/13.txt
@@ -0,0 +1 @@
+(01)90012345678908(3922)795888888888888888888888888888888888888888888888888888
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/14.png b/core/test/data/blackbox/rssexpanded-3/14.png
new file mode 100644
index 0000000..6b0f448
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/14.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/14.txt b/core/test/data/blackbox/rssexpanded-3/14.txt
new file mode 100644
index 0000000..fb00e31
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/14.txt
@@ -0,0 +1 @@
+(01)90012345678908(3932)0401234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/15.png b/core/test/data/blackbox/rssexpanded-3/15.png
new file mode 100644
index 0000000..360b412
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/15.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/15.txt b/core/test/data/blackbox/rssexpanded-3/15.txt
new file mode 100644
index 0000000..9066194
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/15.txt
@@ -0,0 +1 @@
+(01)00012345678905(10)ABC123
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/16.png b/core/test/data/blackbox/rssexpanded-3/16.png
new file mode 100644
index 0000000..baf3120
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/16.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/16.txt b/core/test/data/blackbox/rssexpanded-3/16.txt
new file mode 100644
index 0000000..8f0841f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/16.txt
@@ -0,0 +1 @@
+(01)12345678901231(10)UNIVERSITY-OF-DEUSTO
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/17.png b/core/test/data/blackbox/rssexpanded-3/17.png
new file mode 100644
index 0000000..49af6a6
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/17.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/17.txt b/core/test/data/blackbox/rssexpanded-3/17.txt
new file mode 100644
index 0000000..89fda98
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/17.txt
@@ -0,0 +1 @@
+(01)12345678901231(10)PIRAMIDE-PROJECT
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/18.png b/core/test/data/blackbox/rssexpanded-3/18.png
new file mode 100644
index 0000000..fa774d0
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/18.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/18.txt b/core/test/data/blackbox/rssexpanded-3/18.txt
new file mode 100644
index 0000000..b120324
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/18.txt
@@ -0,0 +1 @@
+(01)12345678901231(10)TREELOGIC
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/19.png b/core/test/data/blackbox/rssexpanded-3/19.png
new file mode 100644
index 0000000..40f069c
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/19.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/19.txt b/core/test/data/blackbox/rssexpanded-3/19.txt
new file mode 100644
index 0000000..17966ee
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/19.txt
@@ -0,0 +1 @@
+(10)5678(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/2.png b/core/test/data/blackbox/rssexpanded-3/2.png
new file mode 100644
index 0000000..1710366
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/2.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/2.txt b/core/test/data/blackbox/rssexpanded-3/2.txt
new file mode 100644
index 0000000..d7f0a6a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/2.txt
@@ -0,0 +1 @@
+(01)91234567980129(3103)012233(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/20.png b/core/test/data/blackbox/rssexpanded-3/20.png
new file mode 100644
index 0000000..305a71c
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/20.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/20.txt b/core/test/data/blackbox/rssexpanded-3/20.txt
new file mode 100644
index 0000000..b948648
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/20.txt
@@ -0,0 +1 @@
+(10)5678(11)001010
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/21.png b/core/test/data/blackbox/rssexpanded-3/21.png
new file mode 100644
index 0000000..aabea10
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/21.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/21.txt b/core/test/data/blackbox/rssexpanded-3/21.txt
new file mode 100644
index 0000000..a7b3497
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/21.txt
@@ -0,0 +1 @@
+(10)567890(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/22.png b/core/test/data/blackbox/rssexpanded-3/22.png
new file mode 100644
index 0000000..3bf678e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/22.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/22.txt b/core/test/data/blackbox/rssexpanded-3/22.txt
new file mode 100644
index 0000000..e8c7268
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/22.txt
@@ -0,0 +1 @@
+(10)567(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/23.png b/core/test/data/blackbox/rssexpanded-3/23.png
new file mode 100644
index 0000000..a541ca2
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/23.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/23.txt b/core/test/data/blackbox/rssexpanded-3/23.txt
new file mode 100644
index 0000000..5263f7f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/23.txt
@@ -0,0 +1 @@
+(10)1098-1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/24.png b/core/test/data/blackbox/rssexpanded-3/24.png
new file mode 100644
index 0000000..eb00f82
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/24.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/24.txt b/core/test/data/blackbox/rssexpanded-3/24.txt
new file mode 100644
index 0000000..f6413d5
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/24.txt
@@ -0,0 +1 @@
+(10)1098,1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/25.png b/core/test/data/blackbox/rssexpanded-3/25.png
new file mode 100644
index 0000000..d03f073
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/25.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/25.txt b/core/test/data/blackbox/rssexpanded-3/25.txt
new file mode 100644
index 0000000..9208d92
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/25.txt
@@ -0,0 +1 @@
+(10)1098/1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/26.png b/core/test/data/blackbox/rssexpanded-3/26.png
new file mode 100644
index 0000000..9467691
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/26.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/26.txt b/core/test/data/blackbox/rssexpanded-3/26.txt
new file mode 100644
index 0000000..b78623a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/26.txt
@@ -0,0 +1 @@
+(10)1098.1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/27.png b/core/test/data/blackbox/rssexpanded-3/27.png
new file mode 100644
index 0000000..5468dc9
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/27.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/27.txt b/core/test/data/blackbox/rssexpanded-3/27.txt
new file mode 100644
index 0000000..82bfa6a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/27.txt
@@ -0,0 +1 @@
+(10)1098*1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/28.png b/core/test/data/blackbox/rssexpanded-3/28.png
new file mode 100644
index 0000000..f330214
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/28.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/28.txt b/core/test/data/blackbox/rssexpanded-3/28.txt
new file mode 100644
index 0000000..6263d99
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/28.txt
@@ -0,0 +1 @@
+(10)1098a1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/29.png b/core/test/data/blackbox/rssexpanded-3/29.png
new file mode 100644
index 0000000..67fa5e5
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/29.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/29.txt b/core/test/data/blackbox/rssexpanded-3/29.txt
new file mode 100644
index 0000000..35fc529
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/29.txt
@@ -0,0 +1 @@
+(10)1098!1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/3.png b/core/test/data/blackbox/rssexpanded-3/3.png
new file mode 100644
index 0000000..3f54275
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/3.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/3.txt b/core/test/data/blackbox/rssexpanded-3/3.txt
new file mode 100644
index 0000000..ab93c97
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/3.txt
@@ -0,0 +1 @@
+(01)91234567980129(3102)012233(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/30.png b/core/test/data/blackbox/rssexpanded-3/30.png
new file mode 100644
index 0000000..f70bf7a
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/30.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/30.txt b/core/test/data/blackbox/rssexpanded-3/30.txt
new file mode 100644
index 0000000..d0d95d0
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/30.txt
@@ -0,0 +1 @@
+(10)1098"1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/31.png b/core/test/data/blackbox/rssexpanded-3/31.png
new file mode 100644
index 0000000..c2fca02
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/31.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/31.txt b/core/test/data/blackbox/rssexpanded-3/31.txt
new file mode 100644
index 0000000..53bf781
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/31.txt
@@ -0,0 +1 @@
+(10)1098%1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/32.png b/core/test/data/blackbox/rssexpanded-3/32.png
new file mode 100644
index 0000000..76b885f
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/32.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/32.txt b/core/test/data/blackbox/rssexpanded-3/32.txt
new file mode 100644
index 0000000..5d1d351
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/32.txt
@@ -0,0 +1 @@
+(10)1098&1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/33.png b/core/test/data/blackbox/rssexpanded-3/33.png
new file mode 100644
index 0000000..387c976
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/33.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/33.txt b/core/test/data/blackbox/rssexpanded-3/33.txt
new file mode 100644
index 0000000..f00c6bb
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/33.txt
@@ -0,0 +1 @@
+(10)1098'1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/34.png b/core/test/data/blackbox/rssexpanded-3/34.png
new file mode 100644
index 0000000..10abfa3
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/34.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/34.txt b/core/test/data/blackbox/rssexpanded-3/34.txt
new file mode 100644
index 0000000..18b90ec
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/34.txt
@@ -0,0 +1 @@
+(10)1098+1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/35.png b/core/test/data/blackbox/rssexpanded-3/35.png
new file mode 100644
index 0000000..b439faf
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/35.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/35.txt b/core/test/data/blackbox/rssexpanded-3/35.txt
new file mode 100644
index 0000000..96f9049
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/35.txt
@@ -0,0 +1 @@
+(10)1098:1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/36.png b/core/test/data/blackbox/rssexpanded-3/36.png
new file mode 100644
index 0000000..c1d645e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/36.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/36.txt b/core/test/data/blackbox/rssexpanded-3/36.txt
new file mode 100644
index 0000000..2dd84d5
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/36.txt
@@ -0,0 +1 @@
+(10)1098;1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/37.png b/core/test/data/blackbox/rssexpanded-3/37.png
new file mode 100644
index 0000000..dfb6fc7
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/37.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/37.txt b/core/test/data/blackbox/rssexpanded-3/37.txt
new file mode 100644
index 0000000..a64a6db
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/37.txt
@@ -0,0 +1 @@
+(10)1098<1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/38.png b/core/test/data/blackbox/rssexpanded-3/38.png
new file mode 100644
index 0000000..5d52658
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/38.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/38.txt b/core/test/data/blackbox/rssexpanded-3/38.txt
new file mode 100644
index 0000000..c7cc606
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/38.txt
@@ -0,0 +1 @@
+(10)1098=1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/39.png b/core/test/data/blackbox/rssexpanded-3/39.png
new file mode 100644
index 0000000..8f505c3
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/39.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/39.txt b/core/test/data/blackbox/rssexpanded-3/39.txt
new file mode 100644
index 0000000..7345e4e
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/39.txt
@@ -0,0 +1 @@
+(10)1098>1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/4.png b/core/test/data/blackbox/rssexpanded-3/4.png
new file mode 100644
index 0000000..e42f0f9
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/4.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/4.txt b/core/test/data/blackbox/rssexpanded-3/4.txt
new file mode 100644
index 0000000..fca726b
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/4.txt
@@ -0,0 +1 @@
+(01)91234567980129(3102)012233(15)000101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/40.png b/core/test/data/blackbox/rssexpanded-3/40.png
new file mode 100644
index 0000000..d137198
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/40.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/40.txt b/core/test/data/blackbox/rssexpanded-3/40.txt
new file mode 100644
index 0000000..5e152de
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/40.txt
@@ -0,0 +1 @@
+(10)1098?1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/41.png b/core/test/data/blackbox/rssexpanded-3/41.png
new file mode 100644
index 0000000..8910b83
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/41.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/41.txt b/core/test/data/blackbox/rssexpanded-3/41.txt
new file mode 100644
index 0000000..aad1b28
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/41.txt
@@ -0,0 +1 @@
+(10)1098_1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/42.png b/core/test/data/blackbox/rssexpanded-3/42.png
new file mode 100644
index 0000000..877e405
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/42.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/42.txt b/core/test/data/blackbox/rssexpanded-3/42.txt
new file mode 100644
index 0000000..4339de9
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/42.txt
@@ -0,0 +1 @@
+(10)1098 1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/43.png b/core/test/data/blackbox/rssexpanded-3/43.png
new file mode 100644
index 0000000..621aa88
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/43.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/43.txt b/core/test/data/blackbox/rssexpanded-3/43.txt
new file mode 100644
index 0000000..6f63fb0
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/43.txt
@@ -0,0 +1 @@
+(10)123456A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/44.png b/core/test/data/blackbox/rssexpanded-3/44.png
new file mode 100644
index 0000000..2ff0c3d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/44.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/44.txt b/core/test/data/blackbox/rssexpanded-3/44.txt
new file mode 100644
index 0000000..2e2ec43
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/44.txt
@@ -0,0 +1 @@
+(10)123456A1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/45.png b/core/test/data/blackbox/rssexpanded-3/45.png
new file mode 100644
index 0000000..d231946
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/45.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/45.txt b/core/test/data/blackbox/rssexpanded-3/45.txt
new file mode 100644
index 0000000..b607d14
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/45.txt
@@ -0,0 +1 @@
+(10)123456A1234A
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/46.png b/core/test/data/blackbox/rssexpanded-3/46.png
new file mode 100644
index 0000000..8832c69
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/46.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/46.txt b/core/test/data/blackbox/rssexpanded-3/46.txt
new file mode 100644
index 0000000..389adca
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/46.txt
@@ -0,0 +1 @@
+(10)123456A123456
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/47.png b/core/test/data/blackbox/rssexpanded-3/47.png
new file mode 100644
index 0000000..7f5de77
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/47.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/47.txt b/core/test/data/blackbox/rssexpanded-3/47.txt
new file mode 100644
index 0000000..fffde5d
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/47.txt
@@ -0,0 +1 @@
+(10)123456A12345678
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/48.png b/core/test/data/blackbox/rssexpanded-3/48.png
new file mode 100644
index 0000000..a9ec672
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/48.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/48.txt b/core/test/data/blackbox/rssexpanded-3/48.txt
new file mode 100644
index 0000000..ac79617
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/48.txt
@@ -0,0 +1 @@
+(10)1ABCDEF;:/1234567
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/49.png b/core/test/data/blackbox/rssexpanded-3/49.png
new file mode 100644
index 0000000..5f65a42
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/49.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/49.txt b/core/test/data/blackbox/rssexpanded-3/49.txt
new file mode 100644
index 0000000..163b64b
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/49.txt
@@ -0,0 +1 @@
+(10)1ABCDEF;:/ABCDEFG
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/5.png b/core/test/data/blackbox/rssexpanded-3/5.png
new file mode 100644
index 0000000..2c0ba26
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/5.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/5.txt b/core/test/data/blackbox/rssexpanded-3/5.txt
new file mode 100644
index 0000000..b4113ac
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/5.txt
@@ -0,0 +1 @@
+(01)90012345678908(3103)001750
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/50.png b/core/test/data/blackbox/rssexpanded-3/50.png
new file mode 100644
index 0000000..22c31e0
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/50.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/50.txt b/core/test/data/blackbox/rssexpanded-3/50.txt
new file mode 100644
index 0000000..d359328
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/50.txt
@@ -0,0 +1 @@
+(10)1;:/ABCDEFGHIJKLM
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/51.png b/core/test/data/blackbox/rssexpanded-3/51.png
new file mode 100644
index 0000000..604df03
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/51.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/51.txt b/core/test/data/blackbox/rssexpanded-3/51.txt
new file mode 100644
index 0000000..c25e84f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/51.txt
@@ -0,0 +1 @@
+(10)1;:/0123456789012
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/52.png b/core/test/data/blackbox/rssexpanded-3/52.png
new file mode 100644
index 0000000..fb71507
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/52.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/52.txt b/core/test/data/blackbox/rssexpanded-3/52.txt
new file mode 100644
index 0000000..2914766
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/52.txt
@@ -0,0 +1 @@
+(10)1;:/0123
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/53.png b/core/test/data/blackbox/rssexpanded-3/53.png
new file mode 100644
index 0000000..3e81195
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/53.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/53.txt b/core/test/data/blackbox/rssexpanded-3/53.txt
new file mode 100644
index 0000000..c8be9f3
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/53.txt
@@ -0,0 +1 @@
+(10)1;:/0123(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/54.png b/core/test/data/blackbox/rssexpanded-3/54.png
new file mode 100644
index 0000000..3f47cbf
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/54.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/54.txt b/core/test/data/blackbox/rssexpanded-3/54.txt
new file mode 100644
index 0000000..ed31c4d
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/54.txt
@@ -0,0 +1 @@
+(01)90012345678908(3103)012233(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/55.png b/core/test/data/blackbox/rssexpanded-3/55.png
new file mode 100644
index 0000000..5c47a88
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/55.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/55.txt b/core/test/data/blackbox/rssexpanded-3/55.txt
new file mode 100644
index 0000000..d7f0a6a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/55.txt
@@ -0,0 +1 @@
+(01)91234567980129(3103)012233(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/56.png b/core/test/data/blackbox/rssexpanded-3/56.png
new file mode 100644
index 0000000..c80fa6f
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/56.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/56.txt b/core/test/data/blackbox/rssexpanded-3/56.txt
new file mode 100644
index 0000000..ab93c97
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/56.txt
@@ -0,0 +1 @@
+(01)91234567980129(3102)012233(15)991231
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/57.png b/core/test/data/blackbox/rssexpanded-3/57.png
new file mode 100644
index 0000000..401f53b
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/57.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/57.txt b/core/test/data/blackbox/rssexpanded-3/57.txt
new file mode 100644
index 0000000..fca726b
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/57.txt
@@ -0,0 +1 @@
+(01)91234567980129(3102)012233(15)000101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/58.png b/core/test/data/blackbox/rssexpanded-3/58.png
new file mode 100644
index 0000000..c66572e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/58.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/58.txt b/core/test/data/blackbox/rssexpanded-3/58.txt
new file mode 100644
index 0000000..b4113ac
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/58.txt
@@ -0,0 +1 @@
+(01)90012345678908(3103)001750
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/59.png b/core/test/data/blackbox/rssexpanded-3/59.png
new file mode 100644
index 0000000..796e27d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/59.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/59.txt b/core/test/data/blackbox/rssexpanded-3/59.txt
new file mode 100644
index 0000000..57a2c64
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/59.txt
@@ -0,0 +1 @@
+(01)92109876543213(3103)032767
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/6.png b/core/test/data/blackbox/rssexpanded-3/6.png
new file mode 100644
index 0000000..024c2d5
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/6.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/6.txt b/core/test/data/blackbox/rssexpanded-3/6.txt
new file mode 100644
index 0000000..57a2c64
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/6.txt
@@ -0,0 +1 @@
+(01)92109876543213(3103)032767
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/60.png b/core/test/data/blackbox/rssexpanded-3/60.png
new file mode 100644
index 0000000..fcfca2a
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/60.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/60.txt b/core/test/data/blackbox/rssexpanded-3/60.txt
new file mode 100644
index 0000000..bfa4177
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/60.txt
@@ -0,0 +1 @@
+(01)92109876543213(3103)000000
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/61.png b/core/test/data/blackbox/rssexpanded-3/61.png
new file mode 100644
index 0000000..7f192b7
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/61.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/61.txt b/core/test/data/blackbox/rssexpanded-3/61.txt
new file mode 100644
index 0000000..e0da7fa
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/61.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)000156
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/62.png b/core/test/data/blackbox/rssexpanded-3/62.png
new file mode 100644
index 0000000..6334770
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/62.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/62.txt b/core/test/data/blackbox/rssexpanded-3/62.txt
new file mode 100644
index 0000000..01af485
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/62.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)009999
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/63.png b/core/test/data/blackbox/rssexpanded-3/63.png
new file mode 100644
index 0000000..d93e34e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/63.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/63.txt b/core/test/data/blackbox/rssexpanded-3/63.txt
new file mode 100644
index 0000000..e8f98fe
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/63.txt
@@ -0,0 +1 @@
+(01)90012345678908(3203)010000
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/64.png b/core/test/data/blackbox/rssexpanded-3/64.png
new file mode 100644
index 0000000..6feffd1
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/64.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/64.txt b/core/test/data/blackbox/rssexpanded-3/64.txt
new file mode 100644
index 0000000..9895a67
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/64.txt
@@ -0,0 +1 @@
+(01)90012345678908(3203)032767
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/65.png b/core/test/data/blackbox/rssexpanded-3/65.png
new file mode 100644
index 0000000..5efd2c7
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/65.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/65.txt b/core/test/data/blackbox/rssexpanded-3/65.txt
new file mode 100644
index 0000000..dd36aab
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/65.txt
@@ -0,0 +1 @@
+(01)90012345678908(3922)795
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/66.png b/core/test/data/blackbox/rssexpanded-3/66.png
new file mode 100644
index 0000000..14e977a
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/66.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/66.txt b/core/test/data/blackbox/rssexpanded-3/66.txt
new file mode 100644
index 0000000..0429d93
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/66.txt
@@ -0,0 +1 @@
+(01)90012345678908(3922)795888888888888888888888888888888888888888888888888888
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/67.png b/core/test/data/blackbox/rssexpanded-3/67.png
new file mode 100644
index 0000000..1f5ad05
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/67.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/67.txt b/core/test/data/blackbox/rssexpanded-3/67.txt
new file mode 100644
index 0000000..fb00e31
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/67.txt
@@ -0,0 +1 @@
+(01)90012345678908(3932)0401234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/68.png b/core/test/data/blackbox/rssexpanded-3/68.png
new file mode 100644
index 0000000..ced3f5c
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/68.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/68.txt b/core/test/data/blackbox/rssexpanded-3/68.txt
new file mode 100644
index 0000000..b5f3fe9
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/68.txt
@@ -0,0 +1 @@
+(01)90012345678908(3932)040EUR
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/69.png b/core/test/data/blackbox/rssexpanded-3/69.png
new file mode 100644
index 0000000..7b1b0f9
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/69.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/69.txt b/core/test/data/blackbox/rssexpanded-3/69.txt
new file mode 100644
index 0000000..e95bc8d
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/69.txt
@@ -0,0 +1 @@
+(01)90012345678908(3932)04055GBP
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/7.png b/core/test/data/blackbox/rssexpanded-3/7.png
new file mode 100644
index 0000000..d342a7d
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/7.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/7.txt b/core/test/data/blackbox/rssexpanded-3/7.txt
new file mode 100644
index 0000000..bfa4177
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/7.txt
@@ -0,0 +1 @@
+(01)92109876543213(3103)000000
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/70.png b/core/test/data/blackbox/rssexpanded-3/70.png
new file mode 100644
index 0000000..98d0413
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/70.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/70.txt b/core/test/data/blackbox/rssexpanded-3/70.txt
new file mode 100644
index 0000000..37c6cb3
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/70.txt
@@ -0,0 +1 @@
+(01)90012345678908(3932)04066USD778899
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/71.png b/core/test/data/blackbox/rssexpanded-3/71.png
new file mode 100644
index 0000000..d016ab4
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/71.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/71.txt b/core/test/data/blackbox/rssexpanded-3/71.txt
new file mode 100644
index 0000000..9066194
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/71.txt
@@ -0,0 +1 @@
+(01)00012345678905(10)ABC123
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/72.png b/core/test/data/blackbox/rssexpanded-3/72.png
new file mode 100644
index 0000000..54b2443
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/72.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/72.txt b/core/test/data/blackbox/rssexpanded-3/72.txt
new file mode 100644
index 0000000..8f0841f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/72.txt
@@ -0,0 +1 @@
+(01)12345678901231(10)UNIVERSITY-OF-DEUSTO
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/73.png b/core/test/data/blackbox/rssexpanded-3/73.png
new file mode 100644
index 0000000..543d794
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/73.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/73.txt b/core/test/data/blackbox/rssexpanded-3/73.txt
new file mode 100644
index 0000000..89fda98
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/73.txt
@@ -0,0 +1 @@
+(01)12345678901231(10)PIRAMIDE-PROJECT
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/74.png b/core/test/data/blackbox/rssexpanded-3/74.png
new file mode 100644
index 0000000..7d6770e
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/74.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/74.txt b/core/test/data/blackbox/rssexpanded-3/74.txt
new file mode 100644
index 0000000..b120324
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/74.txt
@@ -0,0 +1 @@
+(01)12345678901231(10)TREELOGIC
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/75.png b/core/test/data/blackbox/rssexpanded-3/75.png
new file mode 100644
index 0000000..4c290bc
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/75.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/75.txt b/core/test/data/blackbox/rssexpanded-3/75.txt
new file mode 100644
index 0000000..09d4208
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/75.txt
@@ -0,0 +1 @@
+(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456(423)012345678901
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/76.png b/core/test/data/blackbox/rssexpanded-3/76.png
new file mode 100644
index 0000000..a94dcfc
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/76.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/76.txt b/core/test/data/blackbox/rssexpanded-3/76.txt
new file mode 100644
index 0000000..5e76631
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/76.txt
@@ -0,0 +1 @@
+(15)991231(3103)001750(10)12A(422)123(21)123456(423)0123456789012
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/77.png b/core/test/data/blackbox/rssexpanded-3/77.png
new file mode 100644
index 0000000..8374733
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/77.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/77.txt b/core/test/data/blackbox/rssexpanded-3/77.txt
new file mode 100644
index 0000000..17966ee
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/77.txt
@@ -0,0 +1 @@
+(10)5678(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/78.png b/core/test/data/blackbox/rssexpanded-3/78.png
new file mode 100644
index 0000000..42b71cf
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/78.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/78.txt b/core/test/data/blackbox/rssexpanded-3/78.txt
new file mode 100644
index 0000000..b948648
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/78.txt
@@ -0,0 +1 @@
+(10)5678(11)001010
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/79.png b/core/test/data/blackbox/rssexpanded-3/79.png
new file mode 100644
index 0000000..dd37cd7
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/79.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/79.txt b/core/test/data/blackbox/rssexpanded-3/79.txt
new file mode 100644
index 0000000..a7b3497
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/79.txt
@@ -0,0 +1 @@
+(10)567890(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/8.png b/core/test/data/blackbox/rssexpanded-3/8.png
new file mode 100644
index 0000000..16a99bc
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/8.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/8.txt b/core/test/data/blackbox/rssexpanded-3/8.txt
new file mode 100644
index 0000000..e0da7fa
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/8.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)000156
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/80.png b/core/test/data/blackbox/rssexpanded-3/80.png
new file mode 100644
index 0000000..818a86b
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/80.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/80.txt b/core/test/data/blackbox/rssexpanded-3/80.txt
new file mode 100644
index 0000000..e8c7268
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/80.txt
@@ -0,0 +1 @@
+(10)567(11)010101
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/81.png b/core/test/data/blackbox/rssexpanded-3/81.png
new file mode 100644
index 0000000..9b96bc0
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/81.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/81.txt b/core/test/data/blackbox/rssexpanded-3/81.txt
new file mode 100644
index 0000000..5263f7f
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/81.txt
@@ -0,0 +1 @@
+(10)1098-1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/82.png b/core/test/data/blackbox/rssexpanded-3/82.png
new file mode 100644
index 0000000..7ad1cd1
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/82.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/82.txt b/core/test/data/blackbox/rssexpanded-3/82.txt
new file mode 100644
index 0000000..f6413d5
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/82.txt
@@ -0,0 +1 @@
+(10)1098,1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/83.png b/core/test/data/blackbox/rssexpanded-3/83.png
new file mode 100644
index 0000000..e19548f
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/83.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/83.txt b/core/test/data/blackbox/rssexpanded-3/83.txt
new file mode 100644
index 0000000..9208d92
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/83.txt
@@ -0,0 +1 @@
+(10)1098/1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/84.png b/core/test/data/blackbox/rssexpanded-3/84.png
new file mode 100644
index 0000000..6e410cc
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/84.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/84.txt b/core/test/data/blackbox/rssexpanded-3/84.txt
new file mode 100644
index 0000000..b78623a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/84.txt
@@ -0,0 +1 @@
+(10)1098.1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/85.png b/core/test/data/blackbox/rssexpanded-3/85.png
new file mode 100644
index 0000000..93138ad
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/85.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/85.txt b/core/test/data/blackbox/rssexpanded-3/85.txt
new file mode 100644
index 0000000..82bfa6a
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/85.txt
@@ -0,0 +1 @@
+(10)1098*1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/86.png b/core/test/data/blackbox/rssexpanded-3/86.png
new file mode 100644
index 0000000..fa0400a
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/86.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/86.txt b/core/test/data/blackbox/rssexpanded-3/86.txt
new file mode 100644
index 0000000..6263d99
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/86.txt
@@ -0,0 +1 @@
+(10)1098a1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/87.png b/core/test/data/blackbox/rssexpanded-3/87.png
new file mode 100644
index 0000000..73dc0c9
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/87.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/87.txt b/core/test/data/blackbox/rssexpanded-3/87.txt
new file mode 100644
index 0000000..35fc529
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/87.txt
@@ -0,0 +1 @@
+(10)1098!1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/88.png b/core/test/data/blackbox/rssexpanded-3/88.png
new file mode 100644
index 0000000..b308e8a
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/88.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/88.txt b/core/test/data/blackbox/rssexpanded-3/88.txt
new file mode 100644
index 0000000..d0d95d0
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/88.txt
@@ -0,0 +1 @@
+(10)1098"1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/89.png b/core/test/data/blackbox/rssexpanded-3/89.png
new file mode 100644
index 0000000..a07af51
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/89.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/89.txt b/core/test/data/blackbox/rssexpanded-3/89.txt
new file mode 100644
index 0000000..53bf781
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/89.txt
@@ -0,0 +1 @@
+(10)1098%1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/9.png b/core/test/data/blackbox/rssexpanded-3/9.png
new file mode 100644
index 0000000..b33b814
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/9.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/9.txt b/core/test/data/blackbox/rssexpanded-3/9.txt
new file mode 100644
index 0000000..01af485
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/9.txt
@@ -0,0 +1 @@
+(01)90012345678908(3202)009999
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/90.png b/core/test/data/blackbox/rssexpanded-3/90.png
new file mode 100644
index 0000000..2c345fd
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/90.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/90.txt b/core/test/data/blackbox/rssexpanded-3/90.txt
new file mode 100644
index 0000000..5d1d351
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/90.txt
@@ -0,0 +1 @@
+(10)1098&1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/91.png b/core/test/data/blackbox/rssexpanded-3/91.png
new file mode 100644
index 0000000..14bc535
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/91.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/91.txt b/core/test/data/blackbox/rssexpanded-3/91.txt
new file mode 100644
index 0000000..f00c6bb
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/91.txt
@@ -0,0 +1 @@
+(10)1098'1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/92.png b/core/test/data/blackbox/rssexpanded-3/92.png
new file mode 100644
index 0000000..2fd7c03
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/92.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/92.txt b/core/test/data/blackbox/rssexpanded-3/92.txt
new file mode 100644
index 0000000..18b90ec
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/92.txt
@@ -0,0 +1 @@
+(10)1098+1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/93.png b/core/test/data/blackbox/rssexpanded-3/93.png
new file mode 100644
index 0000000..cad7bca
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/93.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/93.txt b/core/test/data/blackbox/rssexpanded-3/93.txt
new file mode 100644
index 0000000..96f9049
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/93.txt
@@ -0,0 +1 @@
+(10)1098:1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/94.png b/core/test/data/blackbox/rssexpanded-3/94.png
new file mode 100644
index 0000000..33be65c
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/94.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/94.txt b/core/test/data/blackbox/rssexpanded-3/94.txt
new file mode 100644
index 0000000..2dd84d5
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/94.txt
@@ -0,0 +1 @@
+(10)1098;1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/95.png b/core/test/data/blackbox/rssexpanded-3/95.png
new file mode 100644
index 0000000..1c66547
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/95.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/95.txt b/core/test/data/blackbox/rssexpanded-3/95.txt
new file mode 100644
index 0000000..a64a6db
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/95.txt
@@ -0,0 +1 @@
+(10)1098<1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/96.png b/core/test/data/blackbox/rssexpanded-3/96.png
new file mode 100644
index 0000000..4237df9
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/96.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/96.txt b/core/test/data/blackbox/rssexpanded-3/96.txt
new file mode 100644
index 0000000..c7cc606
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/96.txt
@@ -0,0 +1 @@
+(10)1098=1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/97.png b/core/test/data/blackbox/rssexpanded-3/97.png
new file mode 100644
index 0000000..5254329
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/97.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/97.txt b/core/test/data/blackbox/rssexpanded-3/97.txt
new file mode 100644
index 0000000..7345e4e
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/97.txt
@@ -0,0 +1 @@
+(10)1098>1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/98.png b/core/test/data/blackbox/rssexpanded-3/98.png
new file mode 100644
index 0000000..980bfed
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/98.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/98.txt b/core/test/data/blackbox/rssexpanded-3/98.txt
new file mode 100644
index 0000000..5e152de
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/98.txt
@@ -0,0 +1 @@
+(10)1098?1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/99.png b/core/test/data/blackbox/rssexpanded-3/99.png
new file mode 100644
index 0000000..25f8106
Binary files /dev/null and b/core/test/data/blackbox/rssexpanded-3/99.png differ
diff --git a/core/test/data/blackbox/rssexpanded-3/99.txt b/core/test/data/blackbox/rssexpanded-3/99.txt
new file mode 100644
index 0000000..aad1b28
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/99.txt
@@ -0,0 +1 @@
+(10)1098_1234
\ No newline at end of file
diff --git a/core/test/data/blackbox/rssexpanded-3/generate.py b/core/test/data/blackbox/rssexpanded-3/generate.py
new file mode 100644
index 0000000..5ec05c4
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/generate.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+
+import os
+import glob
+import sys
+import subprocess
+import traceback
+import hashlib
+import urllib
+import urllib2
+
+ZINT = 'zint'
+ZINT_RSS_EXPANDED_CODE = 31
+ZINT_BINARY = "zint" # If available in PATH
+
+POSTSCRIPT = 'postscript'
+
+TEST_FILE = "../../../src/com/google/zxing/oned/rss/RSSExpandedBlackBox3TestCase.java"
+
+def check_zint():
+    try:
+        subprocess.Popen("zint", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    except:
+        print >> sys.stderr, "zint not installed. Go to http://www.zint.org.uk/ and install it"
+        return False
+    return True
+
+def check_postscript():
+    return True
+
+GENERATORS = []
+if check_zint():
+    GENERATORS.append(ZINT)
+if check_postscript():
+    GENERATORS.append(POSTSCRIPT)
+
+def generate_image_zint(image_filename, barcode):
+    braces_barcode = barcode.replace("(","[").replace(")","]")
+    os.system('%s -o %s -b %s -d "%s"' % (ZINT_BINARY, image_filename, ZINT_RSS_EXPANDED_CODE, braces_barcode.replace('"','\\"')))
+
+def generate_image_postscript(image_filename, barcode):
+    hashname = "cache/%s.png" % hashlib.new("md5", barcode).hexdigest()
+    # If it exists in the cache, don't download it
+    if os.path.exists(hashname):
+        content = open(hashname).read()
+        open(image_filename,'w').write(content)
+        return
+
+    # We tried use the Python, Perl and LaTeX bindings without success :-(
+    baseurl = "http://www.terryburton.co.uk/barcodewriter/generator/"
+    encoded = urllib.urlencode({
+             "encoder"     : "rssexpanded",
+             "data"        : barcode,
+             "options"     : "",
+             "translate_x" : "50", "translate_y" : "50",
+             "scale_x"     : "2", "scale_y"     : "2",
+             "rotate"      : "0", "submit"      : "Make Barcode"
+         })
+    web_urlobject = urllib2.urlopen(baseurl, data = encoded)
+    web_content   = web_urlobject.read()
+    png_url       = web_content.split('">PNG</a>')[0].split('<a href="')[-1]
+    if not png_url.startswith("tmp"):
+        raise Exception("There was an error processing barcode %s in postscript" % barcode)
+    full_url      = baseurl + png_url
+    png_content   = urllib2.urlopen(full_url).read()
+    open(hashname,'w').write(png_content)
+    open(image_filename,'w').write(png_content)
+
+def generate_image(image_filename, barcode, generator):
+    if generator == ZINT:
+        generate_image_zint(image_filename, barcode)
+    elif generator == POSTSCRIPT:
+        generate_image_postscript(image_filename, barcode)
+    else:
+        raise Exception("Unknown generator: %s" % generator)
+
+def extract_barcodes():
+    for line in open("generation.config"):
+        content = line.split("#")[0].strip()
+        if content != "":
+            if content[0] == '-':
+                pos = content[1:].find('-')
+                exceptions = content[1:pos+1].split(",")
+                barcode = content[pos + 2:]
+                yield exceptions, barcode
+            else:
+                yield (), content
+
+if __name__ == '__main__':
+    counter = 0
+
+    for image_to_delete in glob.glob("*.png"):
+        os.remove(image_to_delete)
+
+    for text_to_delete in glob.glob("*.txt"):
+        os.remove(text_to_delete)
+
+    for generator in GENERATORS:
+        for exceptions, barcode in extract_barcodes():
+            if generator in exceptions:
+                continue
+            try:
+                counter += 1
+                image_filename = str(counter) + ".png"
+                text_filename  = str(counter) + ".txt"
+                open(text_filename, "w").write(barcode)
+                generate_image(image_filename, barcode, generator)
+            except Exception:
+                print "Error with generator %s and barcode %s" % (generator, barcode)
+                traceback.print_exc()
+                counter -= 1
+
+    open(TEST_FILE,'w').write("""package com.google.zxing.oned.rss;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.common.AbstractBlackBoxTestCase;
+
+public class RSSExpandedBlackBox3TestCase extends AbstractBlackBoxTestCase {
+    
+    public RSSExpandedBlackBox3TestCase() {
+        super("test/data/blackbox/rssexpanded-3", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED);
+        addTest(%(number)s, %(number)s, 0.0f);
+        addTest(%(number)s, %(number)s, 180.0f);
+    }
+}
+    """ % {"number" : counter})
+
diff --git a/core/test/data/blackbox/rssexpanded-3/generation.config b/core/test/data/blackbox/rssexpanded-3/generation.config
new file mode 100644
index 0000000..7a973a3
--- /dev/null
+++ b/core/test/data/blackbox/rssexpanded-3/generation.config
@@ -0,0 +1,127 @@
+###########################################################
+# 
+# Place codes in this file, and they will be automatically
+# generated by "generate.py". Everything placed after a "#"
+# will be ignored, as well as every space before and after 
+# the codes and empty lines.
+# 
+# If a generator can't generate a code, then place: 
+# -LIBRARY-. For example, if zint doesn't support a code,
+# place -zint-. If neither zint or postscript support it,
+# place -zint,postscript-. 
+# 
+# 
+
+#################################################
+# Fixed length examples
+
+# Encodation 0111000 - 0111111
+
+(01)90012345678908(3103)012233(15)991231  # Example taken from 7.2.5.4.4
+(01)91234567980129(3103)012233(15)991231  # Testing with other AI
+(01)91234567980129(3102)012233(15)991231  # Testing with 3102 instead of 3103
+(01)91234567980129(3102)012233(15)000101  # January 1st, 2000
+
+# Encodation 0100
+
+(01)90012345678908(3103)001750  # Example taken from 7.2.5.4.2
+(01)92109876543213(3103)032767  # Maximum weight value
+(01)92109876543213(3103)000000  # Minimum weight value
+
+# Encodation 0101
+
+(01)90012345678908(3202)000156  # Example taken from 7.2.5.4.3
+(01)90012345678908(3202)009999  # 9,999 has a different behaviour than 10,000
+(01)90012345678908(3203)010000  # 10,000 has a different behaviour than 9,999
+(01)90012345678908(3203)032767  # 10,000 has a different behaviour than 9,999
+
+#################################################
+# Variable length examples
+
+# Encodation 01100
+
+(01)90012345678908(3922)795    # Example taken from 7.2.5.4.5
+(01)90012345678908(3922)795888888888888888888888888888888888888888888888888888  # Longer information 
+
+# Encodation 01101 
+
+(01)90012345678908(3932)0401234         # Example taken from 7.2.5.4.6
+
+# These three examples don't work due to a bug in zint. It has been reported.
+# However, they work with http://www.terryburton.co.uk/barcodewriter/generator/
+# 
+-zint-(01)90012345678908(3932)040EUR          # Testing with alphanumeric instead of numeric
+-zint-(01)90012345678908(3932)04055GBP        # Testing with numeric + alphanumeric instead of only numeric
+-zint-(01)90012345678908(3932)04066USD778899  # Testing with numeric + alphanumeric + numeric instead of only numeric
+
+# Encodation 1
+
+(01)00012345678905(10)ABC123               # Example taken from 7.2.5.4.1
+(01)12345678901231(10)UNIVERSITY-OF-DEUSTO # Adding other type of information 
+(01)12345678901231(10)PIRAMIDE-PROJECT     # Adding other type of information
+(01)12345678901231(10)TREELOGIC            # Adding other type of information
+
+# 
+# Zint doesn't support this one because after 12A (alphanumeric) it goes back to numeric without a alpha to numeric latch
+-zint-(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456(423)012345678901 # Adding a lot of information
+
+# Encodation 00
+
+# # Zint doesn't support this one because after 12A (alphanumeric) it goes back to numeric without a alpha to numeric latch
+-zint-(15)991231(3103)001750(10)12A(422)123(21)123456(423)0123456789012 # Adding a lot of information
+(10)5678(11)010101 # This one optimizes the last 4 bits as detailed in the end of 7.2.5.5.1 
+(10)5678(11)001010
+(10)567890(11)010101
+(10)567(11)010101
+
+
+# Other tests with special characters, such as: '*',',','-','/','.', 
+# and ISO/IEC646 encodation characters
+(10)1098-1234
+(10)1098,1234
+(10)1098/1234
+(10)1098.1234
+(10)1098*1234
+(10)1098a1234
+(10)1098!1234
+(10)1098"1234
+(10)1098%1234
+(10)1098&1234
+(10)1098'1234
+(10)1098+1234
+(10)1098:1234
+(10)1098;1234
+(10)1098<1234
+(10)1098=1234
+(10)1098>1234
+(10)1098?1234
+(10)1098_1234
+(10)1098 1234
+
+# Testing transitions
+
+(10)123456A                # numeric -> alpha
+-zint-(10)123456A1         # numeric -> alpha
+-zint-(10)123456A123       # numeric -> alpha
+(10)123456A1234            # numeric -> alpha -> numeric
+(10)123456A1234A           # numeric -> alpha
+(10)123456A123456          # numeric -> alpha -> numeric
+(10)123456A12345678        # numeric -> alpha -> numeric
+-zint-(10)123456A1234A(15)991231 # numeric -> alpha -> FNC1
+
+(10)1ABCDEF;:/1234567 # numeric -> alpha -> 646 -> numeric
+(10)1ABCDEF;:/ABCDEFG # numeric -> alpha -> 646 -> alpha
+
+(10)1;:/ABCDEFGHIJKLM # numeric -> 646 -> alpha
+(10)1;:/0123456789012 # numeric -> 646 -> numeric
+(10)1;:/0123          # numeric -> 646
+(10)1;:/0123(15)991231 # numeric -> 646 -> FNC1 numeric
+
+# Another tests, from 7.2.5.5.2
+-zint-(10)1
+
+# Another bug in zint, it works with http://www.terryburton.co.uk/barcodewriter/generator/
+-zint-(10)12A
+# Another bug in zint, it works with the http://www.terryburton.co.uk/barcodewriter/generator/
+-zint-(10)123
+
diff --git a/core/test/src/com/google/zxing/client/result/ExpandedProductParsedResultTestCase.java b/core/test/src/com/google/zxing/client/result/ExpandedProductParsedResultTestCase.java
new file mode 100644
index 0000000..1858bd4
--- /dev/null
+++ b/core/test/src/com/google/zxing/client/result/ExpandedProductParsedResultTestCase.java
@@ -0,0 +1,78 @@
+/*
+ * 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 junit.framework.TestCase;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.Result;
+
+/**
+ * @author Antonio Manuel Benjumea Conde, Servinform, S.A.
+ * @author Agustín Delgado, Servinform, S.A.
+ */
+public final class ExpandedProductParsedResultTestCase extends TestCase {
+
+  public void test_RSSExpanded() {
+    String text = "(01)66546(13)001205(3932)4455(3102)6544(123)544654";
+    String productID = "66546";
+    String sscc = "-";
+    String lotNumber = "-";
+    String productionDate = "-";
+    String packagingDate = "001205";
+    String bestBeforeDate = "-";
+    String expirationDate = "-";
+    String weight = "6544";
+    String weightType = "KG";
+    String weightIncrement = "2";
+    String price = "5";
+    String priceIncrement = "2";
+    String priceCurrency = "445";
+    Hashtable uncommonAIs = new Hashtable();
+    uncommonAIs.put("123", "544654");
+
+    Result result = new Result(text, null, null, BarcodeFormat.RSS_EXPANDED);
+    ExpandedProductParsedResult o = ExpandedProductResultParser
+        .parse(result);
+    assertEquals(productID, o.getProductID());
+    assertEquals(sscc, o.getSscc());
+    assertEquals(lotNumber, o.getLotNumber());
+    assertEquals(productionDate, o.getProductionDate());
+    assertEquals(packagingDate, o.getPackagingDate());
+    assertEquals(bestBeforeDate, o.getBestBeforeDate());
+    assertEquals(expirationDate, o.getExpirationDate());
+    assertEquals(weight, o.getWeight());
+    assertEquals(weightType, o.getWeightType());
+    assertEquals(weightIncrement, o.getWeightIncrement());
+    assertEquals(price, o.getPrice());
+    assertEquals(priceIncrement, o.getPriceIncrement());
+    assertEquals(priceCurrency, o.getPriceCurrency());
+    assertEquals(uncommonAIs, o.getUncommonAIs());
+  }
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/BinaryUtil.java b/core/test/src/com/google/zxing/oned/rss/expanded/BinaryUtil.java
new file mode 100644
index 0000000..d30281a
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/BinaryUtil.java
@@ -0,0 +1,95 @@
+/*
+ * 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.common.BitArray;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ */
+public final class BinaryUtil {
+
+  private BinaryUtil() {
+  }
+
+  /*
+  * Constructs a BitArray from a String like the one returned from BitArray.toString()
+  */
+  public static BitArray buildBitArrayFromString(String data){
+    String dotsAndXs = data.replaceAll("1", "X").replaceAll("0",".");
+    BitArray binary = new BitArray(dotsAndXs.replaceAll(" ", "").length());
+    int counter = 0;
+
+    for(int i = 0; i < dotsAndXs.length(); ++i){
+      if(i % 9 == 0){ // spaces
+        if(dotsAndXs.charAt(i) != ' ') {
+          throw new IllegalStateException("space expected");
+        }
+        continue;
+      }
+
+      char currentChar = dotsAndXs.charAt(i);
+      if(currentChar == 'X' || currentChar == 'x') {
+        binary.set(counter);
+      }
+      counter++;
+    }
+    return binary;
+  }
+
+  public static BitArray buildBitArrayFromStringWithoutSpaces(String data){
+    StringBuilder sb = new StringBuilder();
+
+    String dotsAndXs = data.replaceAll("1", "X").replaceAll("0",".");
+
+    int current = 0;
+    while(current < dotsAndXs.length()){
+      sb.append(' ');
+      for(int i = 0; i < 8 && current < dotsAndXs.length(); ++i){
+        sb.append(dotsAndXs.charAt(current));
+        current++;
+      }
+    }
+
+    return buildBitArrayFromString(sb.toString());
+  }
+
+  public static int extractNumericValueFromBitArray(BitArray information, int pos, int bits) {
+    if(bits > 32) {
+      throw new IllegalArgumentException("extractNumberValueFromBitArray can't handle more than 32 bits");
+    }
+
+    BitArray numeric = new BitArray(bits);
+    for(int i = 0; i < bits; ++i) {
+      if (information.get(pos + i)) {
+        numeric.set(i);
+      }
+    }
+    numeric.reverse();
+    return numeric.bits[0];
+  }
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/BinaryUtilTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/BinaryUtilTest.java
new file mode 100644
index 0000000..88f42dc
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/BinaryUtilTest.java
@@ -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 com.google.zxing.common.BitArray;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ */
+public final class BinaryUtilTest extends TestCase{
+
+  public void testBuildBitArrayFromString(){
+
+    String data = " ..X..X.. ..XXX... XXXXXXXX ........";
+    check(data);
+
+    data = " XXX..X..";
+    check(data);
+
+    data = " XX";
+    check(data);
+
+    data = " ....XX.. ..XX";
+    check(data);
+
+    data = " ....XX.. ..XX..XX ....X.X. ........";
+    check(data);
+  }
+
+  private static void check(String data){
+    BitArray binary = BinaryUtil.buildBitArrayFromString(data);
+    assertEquals(data, binary.toString());
+  }
+
+  public void testBuildBitArrayFromStringWithoutSpaces(){
+    String data;
+
+    data = " ..X..X.. ..XXX... XXXXXXXX ........";
+    checkWithoutSpaces(data);
+
+    data = " XXX..X..";
+    checkWithoutSpaces(data);
+
+    data = " XX";
+    checkWithoutSpaces(data);
+
+    data = " ....XX.. ..XX";
+    checkWithoutSpaces(data);
+
+    data = " ....XX.. ..XX..XX ....X.X. ........";
+    checkWithoutSpaces(data);
+  }
+
+  private static void checkWithoutSpaces(String data){
+    String dataWithoutSpaces = data.replaceAll(" ", "");
+    BitArray binary = BinaryUtil.buildBitArrayFromStringWithoutSpaces(dataWithoutSpaces);
+    assertEquals(data, binary.toString());
+  }
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/BitArrayBuilderTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/BitArrayBuilderTest.java
new file mode 100644
index 0000000..92cc13c
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/BitArrayBuilderTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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;
+import com.google.zxing.oned.rss.DataCharacter;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at deusto.es)
+ */
+public final class BitArrayBuilderTest extends TestCase {
+
+  public void testBuildBitArray1(){
+    int [][] pairValues = {
+        { 19 },
+        { 673, 16 }
+    };
+
+    String expected = " .......X ..XX..X. X.X....X .......X ....";
+
+    checkBinary(pairValues, expected);
+  }
+
+  private void checkBinary(int[][] pairValues, String expected) {
+    BitArray binary = buildBitArray(pairValues);
+    assertEquals(expected, binary.toString());
+  }
+
+  private static BitArray buildBitArray(int[][] pairValues) {
+    Vector pairs = new Vector();
+    for(int i = 0; i < pairValues.length; ++i){
+      int [] pair = pairValues[i];
+
+      DataCharacter leftChar;
+      if(i == 0) {
+        leftChar = null;
+      } else {
+        leftChar = new DataCharacter(pair[0], 0);
+      }
+
+      DataCharacter rightChar;
+      if(i == 0) {
+        rightChar = new DataCharacter(pair[0], 0);
+      } else if(pair.length == 2) {
+        rightChar = new DataCharacter(pair[1], 0);
+      } else {
+        rightChar = null;
+      }
+
+      ExpandedPair expandedPair = new ExpandedPair(leftChar, rightChar, null, true);
+      pairs.add(expandedPair);
+    }
+
+    BitArray binary = BitArrayBuilder.buildBitArray(pairs);
+    return binary;
+  }
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/ExpandedInformationDecoderTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/ExpandedInformationDecoderTest.java
new file mode 100644
index 0000000..a9a3e37
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/ExpandedInformationDecoderTest.java
@@ -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;
+
+import com.google.zxing.common.BitArray;
+import com.google.zxing.oned.rss.expanded.decoders.AbstractExpandedDecoder;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at deusto.es)
+ */
+public final class ExpandedInformationDecoderTest extends TestCase {
+
+  public void testNoAi() throws Exception {
+    BitArray information = BinaryUtil.buildBitArrayFromString(" .......X ..XX..X. X.X....X .......X ....");
+
+    AbstractExpandedDecoder decoder = AbstractExpandedDecoder.createDecoder(information);
+    String decoded = decoder.parseInformation();
+    assertEquals("(10)12A", decoded);
+  }
+
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox1TestCase.java b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox1TestCase.java
new file mode 100644
index 0000000..f4cfdfb
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox1TestCase.java
@@ -0,0 +1,40 @@
+/*
+ * 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.BarcodeFormat;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.common.AbstractBlackBoxTestCase;
+
+public final class RSSExpandedBlackBox1TestCase extends AbstractBlackBoxTestCase {
+
+  public RSSExpandedBlackBox1TestCase() {
+    super("test/data/blackbox/rssexpanded-1", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED);
+    addTest(32, 32, 0.0f);
+    addTest(32, 32, 180.0f);
+  }
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox2TestCase.java b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox2TestCase.java
new file mode 100644
index 0000000..af18fd1
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox2TestCase.java
@@ -0,0 +1,40 @@
+/*
+ * 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.BarcodeFormat;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.common.AbstractBlackBoxTestCase;
+
+public class RSSExpandedBlackBox2TestCase extends AbstractBlackBoxTestCase {
+
+  public RSSExpandedBlackBox2TestCase() {
+    super("test/data/blackbox/rssexpanded-2", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED);
+    addTest(21, 23, 0.0f);
+    addTest(19, 23, 180.0f);
+  }
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox3TestCase.java b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox3TestCase.java
new file mode 100644
index 0000000..f513fc7
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedBlackBox3TestCase.java
@@ -0,0 +1,41 @@
+/*
+ * 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.BarcodeFormat;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.common.AbstractBlackBoxTestCase;
+
+public final class RSSExpandedBlackBox3TestCase extends AbstractBlackBoxTestCase {
+    
+    public RSSExpandedBlackBox3TestCase() {
+        super("test/data/blackbox/rssexpanded-3", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED);
+        addTest(117, 117, 0.0f);
+        addTest(117, 117, 180.0f);
+    }
+}
+    
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2binaryTestCase.java b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2binaryTestCase.java
new file mode 100644
index 0000000..2b45c09
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2binaryTestCase.java
@@ -0,0 +1,219 @@
+/*
+ * 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.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.Vector;
+
+import javax.imageio.ImageIO;
+
+import junit.framework.TestCase;
+
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.NotFoundException;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.common.BitArray;
+import com.google.zxing.common.GlobalHistogramBinarizer;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at deusto.es)
+ */
+public final class RSSExpandedImage2binaryTestCase extends TestCase {
+
+  public void testDecodeRow2binary_1() throws Exception{
+    // (11)100224(17)110224(3102)000100
+    String path = "test/data/blackbox/rssexpanded-1/1.jpg";
+    String expected = " ...X...X .X....X. .XX...X. X..X...X ...XX.X. ..X.X... ..X.X..X ...X..X. X.X....X .X....X. .....X.. X...X...";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_2() throws Exception{
+    // (01)90012345678908(3103)001750
+    String path = "test/data/blackbox/rssexpanded-1/2.jpg";
+    String expected = " ..X..... ......X. .XXX.X.X .X...XX. XXXXX.XX XX.X.... .XX.XX.X .XX.";
+
+    assertCorrectImage2binary(path, expected);
+
+  }
+
+  public void testDecodeRow2binary_3() throws Exception{
+    // (10)12A
+    String path = "test/data/blackbox/rssexpanded-1/3.jpg";
+    String expected = " .......X ..XX..X. X.X....X .......X ....";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_4() throws Exception{
+    // (01)98898765432106(3202)012345(15)991231
+    String path = "test/data/blackbox/rssexpanded-1/4.jpg";
+    String expected = " ..XXXX.X XX.XXXX. .XXX.XX. XX..X... .XXXXX.. XX.X..X. ..XX..XX XX.X.XXX X..XX..X .X.XXXXX XXXX";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_5() throws Exception{
+    // (01)90614141000015(3202)000150
+    String path = "test/data/blackbox/rssexpanded-1/5.jpg";
+    String expected = " ..X.X... .XXXX.X. XX..XXXX ....XX.. X....... ....X... ....X..X .XX.";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_10() throws Exception{
+    // (01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456(423)0123456789012
+    String path = "test/data/blackbox/rssexpanded-1/10.png";
+    String expected = " .X.XX..X XX.XXXX. .XXX.XX. XX..X... .XXXXX.. XX.X..X. ..XX...X XX.X.... X.X.X.X. X.X..X.X .X....X. XX...X.. ...XX.X. .XXXXXX. .X..XX.. X.X.X... .X...... XXXX.... XX.XX... XXXXX.X. ...XXXXX .....X.X ...X.... X.XXX..X X.X.X... XX.XX..X .X..X..X .X.X.X.X X.XX...X .XX.XXX. XXX.X.XX ..X.";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_11() throws Exception{
+    // (01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456
+    String expected = " .X.XX..X XX.XXXX. .XXX.XX. XX..X... .XXXXX.. XX.X..X. ..XX...X XX.X.... X.X.X.X. X.X..X.X .X....X. XX...X.. ...XX.X. .XXXXXX. .X..XX.. X.X.X... .X...... XXXX.... XX.XX... XXXXX.X. ...XXXXX .....X.X ...X.... X.XXX..X X.X.X... ....";
+    String path = "test/data/blackbox/rssexpanded-1/11.png";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_12() throws Exception{
+    // (01)98898765432106(3103)001750
+
+    String expected = " ..X..XX. XXXX..XX X.XX.XX. .X....XX XXX..XX. X..X.... .XX.XX.X .XX.";
+    String path = "test/data/blackbox/rssexpanded-1/12.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_13() throws Exception{
+    // (01)90012345678908(3922)795
+
+    String expected = " ..XX..X. ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. X.X.XXXX .X..X..X ......X.";
+    String path = "test/data/blackbox/rssexpanded-1/13.png";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_14() throws Exception{
+    // (01)90012345678908(3932)0401234
+
+    String expected = " ..XX.X.. ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. X.....X. X.....X. X.X.X.XX .X...... X...";
+    String path = "test/data/blackbox/rssexpanded-1/14.png";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_15() throws Exception{
+    // (01)90012345678908(3102)001750(11)100312
+
+    String expected = " ..XXX... ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. ..XX...X .X.....X .XX..... XXXX.X.. XX..";
+    String path = "test/data/blackbox/rssexpanded-1/15.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_16() throws Exception{
+    // (01)90012345678908(3202)001750(11)100312
+
+    String expected = " ..XXX..X ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. ..XX...X .X.....X .XX..... XXXX.X.. XX..";
+    String path = "test/data/blackbox/rssexpanded-1/16.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_17() throws Exception{
+    // (01)90012345678908(3102)001750(13)100312
+
+    String expected = " ..XXX.X. ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. ..XX...X .X.....X .XX..... XXXX.X.. XX..";
+    String path = "test/data/blackbox/rssexpanded-1/17.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_18() throws Exception{
+    // (01)90012345678908(3202)001750(13)100312
+
+    String expected = " ..XXX.XX ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. ..XX...X .X.....X .XX..... XXXX.X.. XX..";
+    String path = "test/data/blackbox/rssexpanded-1/18.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_19() throws Exception{
+    // (01)90012345678908(3102)001750(15)100312
+
+    String expected = " ..XXXX.. ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. ..XX...X .X.....X .XX..... XXXX.X.. XX..";
+    String path = "test/data/blackbox/rssexpanded-1/19.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_20() throws Exception{
+    // (01)90012345678908(3202)001750(15)100312
+
+    String expected = " ..XXXX.X ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. ..XX...X .X.....X .XX..... XXXX.X.. XX..";
+    String path = "test/data/blackbox/rssexpanded-1/20.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_21() throws Exception{
+    // (01)90012345678908(3102)001750(17)100312
+
+    String expected = " ..XXXXX. ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. ..XX...X .X.....X .XX..... XXXX.X.. XX..";
+    String path = "test/data/blackbox/rssexpanded-1/21.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  public void testDecodeRow2binary_22() throws Exception{
+    // (01)90012345678908(3202)001750(17)100312
+
+    String expected = " ..XXXXXX ........ .X..XXX. X.X.X... XX.XXXXX .XXXX.X. ..XX...X .X.....X .XX..... XXXX.X.. XX..";
+    String path = "test/data/blackbox/rssexpanded-1/22.jpg";
+
+    assertCorrectImage2binary(path, expected);
+  }
+
+  private static void assertCorrectImage2binary(String path,
+      String expected) throws IOException, NotFoundException {
+    RSSExpandedReader rssExpandedReader = new RSSExpandedReader();
+
+    BufferedImage image = ImageIO.read(new File(path));
+    BinaryBitmap binaryMap = new BinaryBitmap(new GlobalHistogramBinarizer(new BufferedImageLuminanceSource(image)));
+    int rowNumber = binaryMap.getHeight() / 2;
+    BitArray row = binaryMap.getBlackRow(rowNumber, null);
+
+    Vector pairs = rssExpandedReader.decodeRow2pairs(rowNumber, row);
+    BitArray binary = BitArrayBuilder.buildBitArray(pairs);
+    assertEquals(expected, binary.toString());
+  }
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2resultTestCase.java b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2resultTestCase.java
new file mode 100644
index 0000000..d9083f3
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2resultTestCase.java
@@ -0,0 +1,83 @@
+/**
+ * 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.
+ *
+ * This software consists of contributions made by many individuals,
+ * listed below:
+ *
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at deusto.es)
+ *
+ * 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", leaded by Treelogic
+ * ( http://www.treelogic.com/ ):
+ *
+ *   http://www.piramidepse.com/
+ *
+ */
+
+package com.google.zxing.oned.rss.expanded;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.Hashtable;
+
+import javax.imageio.ImageIO;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.Result;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.client.result.ExpandedProductParsedResult;
+import com.google.zxing.client.result.ParsedResult;
+import com.google.zxing.client.result.ResultParser;
+import com.google.zxing.common.BitArray;
+import com.google.zxing.common.GlobalHistogramBinarizer;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at deusto.es)
+ */
+public final class RSSExpandedImage2resultTestCase extends TestCase {
+
+  public void testDecodeRow2result_2() throws Exception{
+    // (01)90012345678908(3103)001750
+    String path = "test/data/blackbox/rssexpanded-1/2.jpg";
+    ExpandedProductParsedResult expected = new ExpandedProductParsedResult("90012345678908", "-", "-", "-", "-", "-", "-", "001750", ExpandedProductParsedResult.KILOGRAM, "3", "-", "-", "-", new Hashtable());
+
+    assertCorrectImage2result(path, expected);
+  }
+
+  private static void assertCorrectImage2result(String path, ExpandedProductParsedResult expected) throws Exception {
+    RSSExpandedReader rssExpandedReader = new RSSExpandedReader();
+
+    BufferedImage image = ImageIO.read(new File(path));
+    BinaryBitmap binaryMap = new BinaryBitmap(new GlobalHistogramBinarizer(new BufferedImageLuminanceSource(image)));
+    int rowNumber = binaryMap.getHeight() / 2;
+    BitArray row = binaryMap.getBlackRow(rowNumber, null);
+
+    Result theResult = rssExpandedReader.decodeRow(rowNumber, row, new Hashtable());
+
+    assertEquals(BarcodeFormat.RSS_EXPANDED, theResult.getBarcodeFormat());
+
+    ParsedResult result = ResultParser.parseResult(theResult);
+
+    assertEquals(expected, result);
+  }
+
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2stringTestCase.java b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2stringTestCase.java
new file mode 100644
index 0000000..b512090
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedImage2stringTestCase.java
@@ -0,0 +1,253 @@
+/*
+ * 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.awt.image.BufferedImage;
+import java.io.File;
+import java.util.Hashtable;
+
+import javax.imageio.ImageIO;
+
+import junit.framework.TestCase;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.Result;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.common.BitArray;
+import com.google.zxing.common.GlobalHistogramBinarizer;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at deusto.es)
+ */
+public final class RSSExpandedImage2stringTestCase extends TestCase {
+
+  public void testDecodeRow2string_1() throws Exception{
+    String path = "test/data/blackbox/rssexpanded-1/1.jpg";
+    String expected = "(11)100224(17)110224(3102)000100";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_2() throws Exception{
+    String path = "test/data/blackbox/rssexpanded-1/2.jpg";
+    String expected = "(01)90012345678908(3103)001750";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_3() throws Exception{
+    String path = "test/data/blackbox/rssexpanded-1/3.jpg";
+    String expected = "(10)12A";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_4() throws Exception{
+    String path = "test/data/blackbox/rssexpanded-1/4.jpg";
+    String expected = "(01)98898765432106(3202)012345(15)991231";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_5() throws Exception{
+    String path = "test/data/blackbox/rssexpanded-1/5.jpg";
+    String expected = "(01)90614141000015(3202)000150";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_7() throws Exception{
+    String path = "test/data/blackbox/rssexpanded-1/7.png";
+    String expected = "(10)567(11)010101";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_10() throws Exception{
+    String path = "test/data/blackbox/rssexpanded-1/10.png";
+    String expected = "(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456(423)012345678901";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_11() throws Exception{
+    String expected = "(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456";
+    String path = "test/data/blackbox/rssexpanded-1/11.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_12() throws Exception{
+    String expected = "(01)98898765432106(3103)001750";
+    String path = "test/data/blackbox/rssexpanded-1/12.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_13() throws Exception{
+    String expected = "(01)90012345678908(3922)795";
+    String path = "test/data/blackbox/rssexpanded-1/13.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_14() throws Exception{
+    String expected = "(01)90012345678908(3932)0401234";
+    String path = "test/data/blackbox/rssexpanded-1/14.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_15() throws Exception{
+    String expected = "(01)90012345678908(3102)001750(11)100312";
+    String path = "test/data/blackbox/rssexpanded-1/15.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_16() throws Exception{
+    String expected = "(01)90012345678908(3202)001750(11)100312";
+    String path = "test/data/blackbox/rssexpanded-1/16.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_17() throws Exception{
+    String expected = "(01)90012345678908(3102)001750(13)100312";
+    String path = "test/data/blackbox/rssexpanded-1/17.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_18() throws Exception{
+    String expected = "(01)90012345678908(3202)001750(13)100312";
+    String path = "test/data/blackbox/rssexpanded-1/18.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_19() throws Exception{
+    String expected = "(01)90012345678908(3102)001750(15)100312";
+    String path = "test/data/blackbox/rssexpanded-1/19.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_20() throws Exception{
+    String expected = "(01)90012345678908(3202)001750(15)100312";
+    String path = "test/data/blackbox/rssexpanded-1/20.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_21() throws Exception{
+    String expected = "(01)90012345678908(3102)001750(17)100312";
+    String path = "test/data/blackbox/rssexpanded-1/21.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_22() throws Exception{
+    String expected = "(01)90012345678908(3202)001750(17)100312";
+    String path = "test/data/blackbox/rssexpanded-1/22.jpg";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_25() throws Exception{
+    String expected = "(10)123";
+    String path = "test/data/blackbox/rssexpanded-1/25.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_26() throws Exception{
+    String expected = "(10)5678(11)010101";
+    String path = "test/data/blackbox/rssexpanded-1/26.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_27() throws Exception{
+    String expected = "(10)1098-1234";
+    String path = "test/data/blackbox/rssexpanded-1/27.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_28() throws Exception{
+    String expected = "(10)1098/1234";
+    String path = "test/data/blackbox/rssexpanded-1/28.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_29() throws Exception{
+    String expected = "(10)1098.1234";
+    String path = "test/data/blackbox/rssexpanded-1/29.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_30() throws Exception{
+    String expected = "(10)1098*1234";
+    String path = "test/data/blackbox/rssexpanded-1/30.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_31() throws Exception{
+    String expected = "(10)1098,1234";
+    String path = "test/data/blackbox/rssexpanded-1/31.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  public void testDecodeRow2string_32() throws Exception{
+    String expected = "(15)991231(3103)001750(10)12A(422)123(21)123456(423)0123456789012";
+    String path = "test/data/blackbox/rssexpanded-1/32.png";
+
+    assertCorrectImage2string(path, expected);
+  }
+
+  private static void assertCorrectImage2string(String path, String expected) throws Exception {
+    RSSExpandedReader rssExpandedReader = new RSSExpandedReader();
+
+    BufferedImage image = ImageIO.read(new File(path));
+    BinaryBitmap binaryMap = new BinaryBitmap(new GlobalHistogramBinarizer(new BufferedImageLuminanceSource(image)));
+    int rowNumber = binaryMap.getHeight() / 2;
+    BitArray row = binaryMap.getBlackRow(rowNumber, null);
+
+    Result result = rssExpandedReader.decodeRow(rowNumber, row, new Hashtable());
+
+    assertEquals(BarcodeFormat.RSS_EXPANDED, result.getBarcodeFormat());
+    assertEquals(expected, result.getText());
+  }
+
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedInternalTestCase.java b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedInternalTestCase.java
new file mode 100644
index 0000000..8d7fe0f
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/RSSExpandedInternalTestCase.java
@@ -0,0 +1,140 @@
+/*
+ * 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.awt.image.BufferedImage;
+import java.io.File;
+import java.util.Vector;
+
+import javax.imageio.ImageIO;
+
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.NotFoundException;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.common.BitArray;
+import com.google.zxing.common.GlobalHistogramBinarizer;
+import com.google.zxing.oned.rss.DataCharacter;
+import com.google.zxing.oned.rss.FinderPattern;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at deusto.es)
+ */
+public final class RSSExpandedInternalTestCase extends TestCase {
+
+  public void testFindFinderPatterns() throws Exception{
+    RSSExpandedReader rssExpandedReader = new RSSExpandedReader();
+
+    String path = "test/data/blackbox/rssexpanded-1/2.jpg";
+    BufferedImage image = ImageIO.read(new File(path));
+    BinaryBitmap binaryMap = new BinaryBitmap(new GlobalHistogramBinarizer(new BufferedImageLuminanceSource(image)));
+    int rowNumber = binaryMap.getHeight() / 2;
+    BitArray row = binaryMap.getBlackRow(rowNumber, null);
+    Vector<ExpandedPair> previousPairs = new Vector<ExpandedPair>();
+
+    ExpandedPair pair1 = rssExpandedReader.retrieveNextPair(row, previousPairs, rowNumber);
+    previousPairs.add(pair1);
+    assertEquals(0, pair1.getFinderPattern().getValue());
+    assertFalse(pair1.mayBeLast());
+
+    ExpandedPair pair2 = rssExpandedReader.retrieveNextPair(row, previousPairs, rowNumber);
+    previousPairs.add(pair2);
+    assertEquals(1, pair2.getFinderPattern().getValue());
+    assertFalse(pair2.mayBeLast());
+
+    ExpandedPair pair3 = rssExpandedReader.retrieveNextPair(row, previousPairs, rowNumber);
+    previousPairs.add(pair3);
+    assertEquals(1, pair3.getFinderPattern().getValue());
+    assertTrue(pair3.mayBeLast());
+
+    try{
+      rssExpandedReader.retrieveNextPair(row, previousPairs, rowNumber);
+      //   the previous was the last pair
+      fail(NotFoundException.class.getName() + " expected");
+    }catch(NotFoundException nfe){
+      // ok
+    }
+  }
+
+  public void testRetrieveNextPairPatterns() throws Exception{
+    RSSExpandedReader rssExpandedReader = new RSSExpandedReader();
+
+    String path = "test/data/blackbox/rssexpanded-1/3.jpg";
+    BufferedImage image = ImageIO.read(new File(path));
+    BinaryBitmap binaryMap = new BinaryBitmap(new GlobalHistogramBinarizer(new BufferedImageLuminanceSource(image)));
+    int rowNumber = binaryMap.getHeight() / 2;
+    BitArray row = binaryMap.getBlackRow(rowNumber, null);
+    Vector<ExpandedPair> previousPairs = new Vector<ExpandedPair>();
+
+    ExpandedPair pair1 = rssExpandedReader.retrieveNextPair(row, previousPairs, rowNumber);
+    previousPairs.add(pair1);
+    assertEquals(0, pair1.getFinderPattern().getValue());
+    assertFalse(pair1.mayBeLast());
+
+    ExpandedPair pair2 = rssExpandedReader.retrieveNextPair(row, previousPairs, rowNumber);
+    previousPairs.add(pair2);
+    assertEquals(0, pair2.getFinderPattern().getValue());
+    assertTrue(pair2.mayBeLast());
+  }
+
+  public void testDecodeCheckCharacter() throws Exception{
+    RSSExpandedReader rssExpandedReader = new RSSExpandedReader();
+
+    String path = "test/data/blackbox/rssexpanded-1/3.jpg";
+    BufferedImage image = ImageIO.read(new File(path));
+    BinaryBitmap binaryMap = new BinaryBitmap(new GlobalHistogramBinarizer(new BufferedImageLuminanceSource(image)));
+    BitArray row = binaryMap.getBlackRow(binaryMap.getHeight() / 2, null);
+
+    int[] startEnd = {145, 243};//image pixels where the A1 pattern starts (at 124) and ends (at 214)
+    int value = 0;// A
+    FinderPattern finderPatternA1 = new FinderPattern(value, startEnd, startEnd[0], startEnd[1], image.getHeight() / 2);
+    //{1, 8, 4, 1, 1};
+    DataCharacter dataCharacter = rssExpandedReader.decodeDataCharacter(row, finderPatternA1, true, true);
+
+    assertEquals(98, dataCharacter.getValue());
+  }
+
+  public void testDecodeDataCharacter() throws Exception{
+    RSSExpandedReader rssExpandedReader = new RSSExpandedReader();
+
+    String path = "test/data/blackbox/rssexpanded-1/3.jpg";
+    BufferedImage image = ImageIO.read(new File(path));
+    BinaryBitmap binaryMap = new BinaryBitmap(new GlobalHistogramBinarizer(new BufferedImageLuminanceSource(image)));
+    BitArray row = binaryMap.getBlackRow(binaryMap.getHeight() / 2, null);
+
+    int[] startEnd = {145, 243};//image pixels where the A1 pattern starts (at 124) and ends (at 214)
+    int value = 0; // A
+    FinderPattern finderPatternA1 = new FinderPattern(value, startEnd, startEnd[0], startEnd[1], image.getHeight() / 2);
+    //{1, 8, 4, 1, 1};
+    DataCharacter dataCharacter = rssExpandedReader.decodeDataCharacter(row, finderPatternA1, true, false);
+
+    assertEquals(19, dataCharacter.getValue());
+    assertEquals(1007, dataCharacter.getChecksumPortion());
+  }
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3103_DecoderTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3103_DecoderTest.java
new file mode 100644
index 0000000..d82f441
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3103_DecoderTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 at deusto.es)
+ */
+public class AI01_3103_DecoderTest extends AbstractDecoderTest {
+	
+	private static final String header = "..X..";
+	
+	public void test01_3103_1() throws Exception {
+		String data = header + compressedGtin_900123456798908 + compressed15bitWeight_1750;
+		String expected = "(01)90012345678908(3103)001750";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+
+	public void test01_3103_2() throws Exception {
+		String data = header + compressedGtin_900000000000008 + compressed15bitWeight_0;
+		String expected = "(01)90000000000003(3103)000000";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_3103_invalid() throws Exception {
+		String data = header + compressedGtin_900123456798908 + compressed15bitWeight_1750 + "..";
+		
+		try{
+			assertCorrectBinaryString(data, "");
+			fail(NotFoundException.class.getName() + " expected");
+		}catch(NotFoundException nfe){
+			// expected
+		}
+	}
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3202_3203_DecoderTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3202_3203_DecoderTest.java
new file mode 100644
index 0000000..1c7c0ae
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3202_3203_DecoderTest.java
@@ -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;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ */
+public class AI01_3202_3203_DecoderTest extends AbstractDecoderTest {
+	private static final String header = "..X.X";
+	
+	public void test01_3202_1() throws Exception {
+		String data = header + compressedGtin_900123456798908 + compressed15bitWeight_1750;
+		String expected = "(01)90012345678908(3202)001750";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+
+	public void test01_3203_1() throws Exception {
+		String data = header + compressedGtin_900123456798908 + compressed15bitWeight_11750;
+		String expected = "(01)90012345678908(3203)001750";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3X0X_1X_DecoderTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3X0X_1X_DecoderTest.java
new file mode 100644
index 0000000..a9f3543
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AI01_3X0X_1X_DecoderTest.java
@@ -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;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ */
+public class AI01_3X0X_1X_DecoderTest extends AbstractDecoderTest {
+	
+	private static final String header_310x_11 = "..XXX...";
+	private static final String header_320x_11 = "..XXX..X";
+	private static final String header_310x_13 = "..XXX.X.";
+	private static final String header_320x_13 = "..XXX.XX";
+	private static final String header_310x_15 = "..XXXX..";
+	private static final String header_320x_15 = "..XXXX.X";
+	private static final String header_310x_17 = "..XXXXX.";
+	private static final String header_320x_17 = "..XXXXXX";
+	
+	public void test01_310X_1X_endDate() throws Exception {
+		String data = header_310x_11 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_End;
+		String expected = "(01)90012345678908(3100)001750";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_310X_11_1() throws Exception {
+		String data = header_310x_11 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_March_12th_2010;
+		String expected = "(01)90012345678908(3100)001750(11)100312";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_320X_11_1() throws Exception {
+		String data = header_320x_11 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_March_12th_2010;
+		String expected = "(01)90012345678908(3200)001750(11)100312";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_310X_13_1() throws Exception {
+		String data = header_310x_13 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_March_12th_2010;
+		String expected = "(01)90012345678908(3100)001750(13)100312";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_320X_13_1() throws Exception {
+		String data = header_320x_13 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_March_12th_2010;
+		String expected = "(01)90012345678908(3200)001750(13)100312";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_310X_15_1() throws Exception {
+		String data = header_310x_15 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_March_12th_2010;
+		String expected = "(01)90012345678908(3100)001750(15)100312";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_320X_15_1() throws Exception {
+		String data = header_320x_15 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_March_12th_2010;
+		String expected = "(01)90012345678908(3200)001750(15)100312";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_310X_17_1() throws Exception {
+		String data = header_310x_17 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_March_12th_2010;
+		String expected = "(01)90012345678908(3100)001750(17)100312";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void test01_320X_17_1() throws Exception {
+		String data = header_320x_17 + compressedGtin_900123456798908 + compressed20bitWeight_1750 + compressedDate_March_12th_2010;
+		String expected = "(01)90012345678908(3200)001750(17)100312";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AbstractDecoderTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AbstractDecoderTest.java
new file mode 100644
index 0000000..29a5b28
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AbstractDecoderTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+import com.google.zxing.oned.rss.expanded.BinaryUtil;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ */
+public abstract class AbstractDecoderTest extends TestCase {
+
+	protected static final String numeric_10                     = "..X..XX";
+	protected static final String numeric_12                     = "..X.X.X";
+	protected static final String numeric_1FNC1                  = "..XXX.X";
+	protected static final String numeric_FNC11                  = "XXX.XXX";
+	                                                             
+	protected static final String numeric2alpha                  = "....";
+	                                                             
+	protected static final String alpha_A                        = "X.....";
+	protected static final String alpha_FNC1                      = ".XXXX";
+	protected static final String alpha2numeric                  = "...";
+	protected static final String alpha2isoiec646                = "..X..";
+	                                                             
+	protected static final String i646_B                         = "X.....X";
+	protected static final String i646_C                         = "X....X.";
+	protected static final String i646_FNC1                      = ".XXXX";
+	protected static final String isoiec646_2alpha               = "..X..";
+	
+	protected static final String compressedGtin_900123456798908 = ".........X..XXX.X.X.X...XX.XXXXX.XXXX.X.";
+	protected static final String compressedGtin_900000000000008 = "........................................";
+	
+	protected static final String compressed15bitWeight_1750     = "....XX.XX.X.XX.";
+	protected static final String compressed15bitWeight_11750    = ".X.XX.XXXX..XX.";
+	protected static final String compressed15bitWeight_0        = "...............";
+	
+	protected static final String compressed20bitWeight_1750     = ".........XX.XX.X.XX.";
+	
+	protected static final String compressedDate_March_12th_2010 = "....XXXX.X..XX..";
+	protected static final String compressedDate_End             = "X..X.XX.........";
+
+	protected void assertCorrectBinaryString(String binaryString, String expectedNumber) throws NotFoundException {
+		BitArray binary = BinaryUtil.buildBitArrayFromStringWithoutSpaces(binaryString);
+		AbstractExpandedDecoder decoder = AbstractExpandedDecoder.createDecoder(binary);
+		String result = decoder.parseInformation();
+		assertEquals(expectedNumber, result);
+	}
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoderTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoderTest.java
new file mode 100644
index 0000000..1afaab3
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/AnyAIDecoderTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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 at deusto.es)
+ */
+public class AnyAIDecoderTest extends AbstractDecoderTest {
+	
+	private static final String header           = ".....";
+	                                             
+	public void testAnyAIDecoder_1() throws Exception {
+		String data = header + numeric_10 + numeric_12 + numeric2alpha + alpha_A + alpha2numeric + numeric_12;
+		String expected = "(10)12A12";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void testAnyAIDecoder_2() throws Exception {
+		String data = header + numeric_10 + numeric_12 + numeric2alpha + alpha_A + alpha2isoiec646 + i646_B;
+		String expected = "(10)12AB";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void testAnyAIDecoder_3() throws Exception {
+		String data = header + numeric_10 + numeric2alpha + alpha2isoiec646 + i646_B + i646_C + isoiec646_2alpha + alpha_A + alpha2numeric + numeric_10;
+		String expected = "(10)BCA10";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void testAnyAIDecoder_numericFNC1_secondDigit() throws Exception {
+		String data = header + numeric_10 + numeric_1FNC1;
+		String expected = "(10)1";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void testAnyAIDecoder_alphaFNC1() throws Exception {
+		String data = header + numeric_10 + numeric2alpha + alpha_A + alpha_FNC1;
+		String expected = "(10)A";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+	
+	public void testAnyAIDecoder_646FNC1() throws Exception {
+		String data = header + numeric_10 + numeric2alpha + alpha_A + isoiec646_2alpha + i646_B + i646_FNC1;
+		String expected = "(10)AB";
+		
+		assertCorrectBinaryString(data, expected);
+	}
+}
diff --git a/core/test/src/com/google/zxing/oned/rss/expanded/decoders/FieldParserTest.java b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/FieldParserTest.java
new file mode 100644
index 0000000..e35c091
--- /dev/null
+++ b/core/test/src/com/google/zxing/oned/rss/expanded/decoders/FieldParserTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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 junit.framework.TestCase;
+
+/**
+ * @author Pablo Orduña, University of Deusto (pablo.orduna at deusto.es)
+ * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo at deusto.es)
+ */
+public class FieldParserTest extends TestCase{
+	
+	private static void checkFields(String expected) throws NotFoundException {
+		String field  = expected.replace("(", "").replace(")","");
+		String actual = FieldParser.parseFieldsInGeneralPurpose(field);
+		assertEquals(expected, actual);
+	}
+	
+	public void testParseField() throws Exception{
+		checkFields("(15)991231(3103)001750(10)12A");
+	}
+	
+	public void testParseField2() throws Exception{
+		checkFields("(15)991231(15)991231(3103)001750(10)12A");
+	}
+}

-- 
Multi-format 1D/2D barcode image processing library



More information about the Pkg-google-commits mailing list