Issue 583 RSS Expanded support, by Pablo Orduna and the Deusto crew, back-ported by ShumovichY
git-svn-id: https://zxing.googlecode.com/svn/trunk@2510 59b500cc-1b3d-0410-9834-0bbf25fbcc57
|
@ -34,4 +34,23 @@ public class DataCharacter {
|
||||||
return checksumPortion;
|
return checksumPortion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value + "(" + checksumPortion + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if(!(o instanceof DataCharacter)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DataCharacter that = (DataCharacter) o;
|
||||||
|
return value == that.value && checksumPortion == that.checksumPortion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return value ^ checksumPortion;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,18 @@ public final class FinderPattern {
|
||||||
return resultPoints;
|
return resultPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if(!(o instanceof FinderPattern)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FinderPattern that = (FinderPattern) o;
|
||||||
|
return value == that.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,10 +43,10 @@ final class ExpandedPair {
|
||||||
DataCharacter rightChar,
|
DataCharacter rightChar,
|
||||||
FinderPattern finderPattern,
|
FinderPattern finderPattern,
|
||||||
boolean mayBeLast) {
|
boolean mayBeLast) {
|
||||||
this.leftChar = leftChar;
|
this.leftChar = leftChar;
|
||||||
this.rightChar = rightChar;
|
this.rightChar = rightChar;
|
||||||
this.finderPattern = finderPattern;
|
this.finderPattern = finderPattern;
|
||||||
this.mayBeLast = mayBeLast;
|
this.mayBeLast = mayBeLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean mayBeLast(){
|
boolean mayBeLast(){
|
||||||
|
@ -68,4 +68,37 @@ final class ExpandedPair {
|
||||||
public boolean mustBeLast() {
|
public boolean mustBeLast() {
|
||||||
return this.rightChar == null;
|
return this.rightChar == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return
|
||||||
|
"[ " + leftChar + " , " + rightChar + " : " +
|
||||||
|
(finderPattern == null ? "null" : finderPattern.getValue()) + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof ExpandedPair)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ExpandedPair that = (ExpandedPair) o;
|
||||||
|
return
|
||||||
|
equalsOrNull(leftChar, that.leftChar) &&
|
||||||
|
equalsOrNull(rightChar, that.rightChar) &&
|
||||||
|
equalsOrNull(finderPattern, that.finderPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean equalsOrNull(Object o1, Object o2) {
|
||||||
|
return o1 == null ? o2 == null : o1.equals(o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return hashNotNull(leftChar) ^ hashNotNull(rightChar) ^ hashNotNull(finderPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int hashNotNull(Object o) {
|
||||||
|
return o == null ? 0 : o.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
76
core/src/com/google/zxing/oned/rss/expanded/ExpandedRow.java
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 ZXing authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.zxing.oned.rss.expanded;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One row of an RSS Expanded Stacked symbol, consisting of 1+ expanded pairs.
|
||||||
|
*/
|
||||||
|
final class ExpandedRow {
|
||||||
|
|
||||||
|
private final List<ExpandedPair> pairs;
|
||||||
|
private final int rowNumber;
|
||||||
|
/** Did this row of the image have to be reversed (mirrored) to recognize the pairs? */
|
||||||
|
private final boolean wasReversed;
|
||||||
|
|
||||||
|
ExpandedRow(List<ExpandedPair> pairs, int rowNumber, boolean wasReversed) {
|
||||||
|
this.pairs = new ArrayList<ExpandedPair>(pairs);
|
||||||
|
this.rowNumber = rowNumber;
|
||||||
|
this.wasReversed = wasReversed;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ExpandedPair> getPairs() {
|
||||||
|
return this.pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getRowNumber() {
|
||||||
|
return this.rowNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isReversed() {
|
||||||
|
return this.wasReversed;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isEquivalent(List<ExpandedPair> otherPairs) {
|
||||||
|
return this.pairs.equals(otherPairs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "{ " + pairs + " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Two rows are equal if they contain the same pairs in the same order.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof ExpandedRow)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ExpandedRow that = (ExpandedRow) o;
|
||||||
|
return this.pairs.equals(that.getPairs()) && wasReversed == that.wasReversed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return pairs.hashCode() ^ Boolean.valueOf(wasReversed).hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ import com.google.zxing.oned.rss.expanded.decoders.AbstractExpandedDecoder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
* @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
|
||||||
|
@ -112,41 +113,186 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
private static final int MAX_PAIRS = 11;
|
private static final int MAX_PAIRS = 11;
|
||||||
|
|
||||||
private final List<ExpandedPair> pairs = new ArrayList<ExpandedPair>(MAX_PAIRS);
|
private final List<ExpandedPair> pairs = new ArrayList<ExpandedPair>(MAX_PAIRS);
|
||||||
|
private final List<ExpandedRow> rows = new ArrayList<ExpandedRow>();
|
||||||
private final int [] startEnd = new int[2];
|
private final int [] startEnd = new int[2];
|
||||||
private final int [] currentSequence = new int[LONGEST_SEQUENCE_SIZE];
|
private final int [] currentSequence = new int[LONGEST_SEQUENCE_SIZE];
|
||||||
|
private boolean startFromEven = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result decodeRow(int rowNumber,
|
public Result decodeRow(int rowNumber,
|
||||||
BitArray row,
|
BitArray row,
|
||||||
Map<DecodeHintType,?> hints) throws NotFoundException {
|
Map<DecodeHintType,?> hints) throws NotFoundException {
|
||||||
this.reset();
|
// Rows can start with even pattern in case in prev rows there where odd number of patters.
|
||||||
decodeRow2pairs(rowNumber, row);
|
// So lets try twice
|
||||||
return constructResult(this.pairs);
|
this.pairs.clear();
|
||||||
|
this.startFromEven = false;
|
||||||
|
try {
|
||||||
|
List<ExpandedPair> pairs = decodeRow2pairs(rowNumber, row);
|
||||||
|
return constructResult(pairs);
|
||||||
|
} catch (NotFoundException e) {
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pairs.clear();
|
||||||
|
this.startFromEven = true;
|
||||||
|
List<ExpandedPair> pairs = decodeRow2pairs(rowNumber, row);
|
||||||
|
return constructResult(pairs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
this.pairs.clear();
|
this.pairs.clear();
|
||||||
|
this.rows.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not private for testing
|
// Not private for testing
|
||||||
List<ExpandedPair> decodeRow2pairs(int rowNumber, BitArray row) throws NotFoundException {
|
List<ExpandedPair> decodeRow2pairs(int rowNumber, BitArray row) throws NotFoundException {
|
||||||
while(true){
|
try {
|
||||||
ExpandedPair nextPair = retrieveNextPair(row, this.pairs, rowNumber);
|
while (true){
|
||||||
this.pairs.add(nextPair);
|
ExpandedPair nextPair = retrieveNextPair(row, this.pairs, rowNumber);
|
||||||
|
this.pairs.add(nextPair);
|
||||||
|
//System.out.println(this.pairs.size()+" pairs found so far on row "+rowNumber+": "+this.pairs);
|
||||||
|
// exit this loop when retrieveNextPair() fails and throws
|
||||||
|
}
|
||||||
|
} catch (NotFoundException nfe) {
|
||||||
|
if (this.pairs.isEmpty()) {
|
||||||
|
throw nfe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (nextPair.mayBeLast()) {
|
// TODO: verify sequence of finder patterns as in checkPairSequence()
|
||||||
if (checkChecksum()) {
|
if (checkChecksum()) {
|
||||||
return this.pairs;
|
return this.pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean tryStackedDecode = !this.rows.isEmpty();
|
||||||
|
boolean wasReversed = false; // TODO: deal with reversed rows
|
||||||
|
storeRow(rowNumber, wasReversed);
|
||||||
|
if (tryStackedDecode) {
|
||||||
|
// When the image is 180-rotated, then rows are sorted in wrong dirrection.
|
||||||
|
// Try twice with both the directions.
|
||||||
|
List<ExpandedPair> ps = checkRows(false);
|
||||||
|
if (ps != null) {
|
||||||
|
return ps;
|
||||||
|
}
|
||||||
|
ps = checkRows(true);
|
||||||
|
if (ps != null) {
|
||||||
|
return ps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw NotFoundException.getNotFoundInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ExpandedPair> checkRows(boolean reverse) {
|
||||||
|
this.pairs.clear();
|
||||||
|
if (reverse) {
|
||||||
|
Collections.reverse(this.rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(ExpandedRow erow : this.rows) {
|
||||||
|
this.pairs.addAll(erow.getPairs());
|
||||||
|
}
|
||||||
|
//System.out.println(this.pairs.size()+" pairs on MULTIPLE ROWS: "+this.rows);
|
||||||
|
if (checkChecksum()) {
|
||||||
|
return this.pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reverse) {
|
||||||
|
Collections.reverse(this.rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void storeRow(int rowNumber, boolean wasReversed) {
|
||||||
|
// Discard if duplicate above or below; otherwise insert in order by row number.
|
||||||
|
int insertPos = 0;
|
||||||
|
boolean prevIsSame = false;
|
||||||
|
boolean nextIsSame = false;
|
||||||
|
while (insertPos < this.rows.size()) {
|
||||||
|
ExpandedRow erow = this.rows.get(insertPos);
|
||||||
|
if (erow.getRowNumber() > rowNumber) {
|
||||||
|
nextIsSame = erow.isEquivalent(this.pairs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prevIsSame = erow.isEquivalent(this.pairs);
|
||||||
|
insertPos += 1;
|
||||||
|
}
|
||||||
|
if (nextIsSame || prevIsSame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the row was partially decoded (e.g. 2 pairs found instead of 3),
|
||||||
|
// it will prevent us from detecting the barcode.
|
||||||
|
// Try to merge partial rows
|
||||||
|
|
||||||
|
// Check whether the row is part of an allready detected row
|
||||||
|
if (isPartialRow(this.pairs, this.rows)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rows.add(insertPos, new ExpandedRow(this.pairs, rowNumber, wasReversed));
|
||||||
|
|
||||||
|
removePartialRows(this.pairs, this.rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all the rows that contains only specified pairs
|
||||||
|
private static void removePartialRows(List<ExpandedPair> pairs, List<ExpandedRow> rows) {
|
||||||
|
check:
|
||||||
|
for (ExpandedRow r : rows) {
|
||||||
|
if (r.getPairs().size() == pairs.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (ExpandedPair p : r.getPairs()) {
|
||||||
|
boolean found = false;
|
||||||
|
for (ExpandedPair pp : pairs) {
|
||||||
|
if (p.equals(pp)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (nextPair.mustBeLast()) {
|
if (!found) {
|
||||||
throw NotFoundException.getNotFoundInstance();
|
continue check;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 'pairs' contains all the pairs from the row 'r'
|
||||||
|
rows.remove(r);
|
||||||
|
// start from the begining
|
||||||
|
removePartialRows(pairs, rows);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Result constructResult(List<ExpandedPair> pairs) throws NotFoundException{
|
// Returns true when one of the rows already contains all the pairs
|
||||||
|
private static boolean isPartialRow(Iterable<ExpandedPair> pairs, Iterable<ExpandedRow> rows) {
|
||||||
|
check:
|
||||||
|
for (ExpandedRow r : rows) {
|
||||||
|
for (ExpandedPair p : pairs) {
|
||||||
|
boolean found = false;
|
||||||
|
for (ExpandedPair pp : r.getPairs()) {
|
||||||
|
if (p.equals(pp)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
continue check;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// the row 'r' contain all the pairs from 'pairs'
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only used for unit testing
|
||||||
|
List<ExpandedRow> getRows() {
|
||||||
|
return this.rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not private for unit testing
|
||||||
|
static Result constructResult(List<ExpandedPair> pairs) throws NotFoundException{
|
||||||
BitArray binary = BitArrayBuilder.buildBitArray(pairs);
|
BitArray binary = BitArrayBuilder.buildBitArray(pairs);
|
||||||
|
|
||||||
AbstractExpandedDecoder decoder = AbstractExpandedDecoder.createDecoder(binary);
|
AbstractExpandedDecoder decoder = AbstractExpandedDecoder.createDecoder(binary);
|
||||||
|
@ -168,6 +314,10 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
DataCharacter checkCharacter = firstPair.getLeftChar();
|
DataCharacter checkCharacter = firstPair.getLeftChar();
|
||||||
DataCharacter firstCharacter = firstPair.getRightChar();
|
DataCharacter firstCharacter = firstPair.getRightChar();
|
||||||
|
|
||||||
|
if (firstCharacter == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int checksum = firstCharacter.getChecksumPortion();
|
int checksum = firstCharacter.getChecksumPortion();
|
||||||
int s = 2;
|
int s = 2;
|
||||||
|
|
||||||
|
@ -205,6 +355,9 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
ExpandedPair retrieveNextPair(BitArray row, List<ExpandedPair> previousPairs, int rowNumber)
|
ExpandedPair retrieveNextPair(BitArray row, List<ExpandedPair> previousPairs, int rowNumber)
|
||||||
throws NotFoundException {
|
throws NotFoundException {
|
||||||
boolean isOddPattern = previousPairs.size() % 2 == 0;
|
boolean isOddPattern = previousPairs.size() % 2 == 0;
|
||||||
|
if (startFromEven) {
|
||||||
|
isOddPattern = !isOddPattern;
|
||||||
|
}
|
||||||
|
|
||||||
FinderPattern pattern;
|
FinderPattern pattern;
|
||||||
|
|
||||||
|
@ -220,54 +373,27 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
}
|
}
|
||||||
}while(keepFinding);
|
}while(keepFinding);
|
||||||
|
|
||||||
boolean mayBeLast = checkPairSequence(previousPairs, pattern);
|
// When stacked symbol is split over multiple rows, there's no way to guess if this pair can be last or not.
|
||||||
|
// boolean mayBeLast = checkPairSequence(previousPairs, pattern);
|
||||||
|
|
||||||
DataCharacter leftChar = this.decodeDataCharacter(row, pattern, isOddPattern, true);
|
DataCharacter leftChar = this.decodeDataCharacter(row, pattern, isOddPattern, true);
|
||||||
|
|
||||||
|
if (!previousPairs.isEmpty()){
|
||||||
|
if (previousPairs.get(previousPairs.size()-1).mustBeLast()){
|
||||||
|
throw NotFoundException.getNotFoundInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DataCharacter rightChar;
|
DataCharacter rightChar;
|
||||||
try{
|
try {
|
||||||
rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);
|
rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);
|
||||||
}catch(NotFoundException nfe){
|
} catch(NotFoundException nfe) {
|
||||||
if(mayBeLast) {
|
rightChar = null;
|
||||||
rightChar = null;
|
|
||||||
} else {
|
|
||||||
throw nfe;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
boolean mayBeLast = true;
|
||||||
return new ExpandedPair(leftChar, rightChar, pattern, mayBeLast);
|
return new ExpandedPair(leftChar, rightChar, pattern, mayBeLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkPairSequence(List<ExpandedPair> 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] = previousPairs.get(pos).getFinderPattern().getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentSequence[currentSequenceLength - 1] = pattern.getValue();
|
|
||||||
|
|
||||||
for (int[] validSequence : FINDER_PATTERN_SEQUENCES) {
|
|
||||||
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, List<ExpandedPair> previousPairs, int forcedOffset)
|
private void findNextPair(BitArray row, List<ExpandedPair> previousPairs, int forcedOffset)
|
||||||
throws NotFoundException {
|
throws NotFoundException {
|
||||||
int[] counters = this.getDecodeFinderCounters();
|
int[] counters = this.getDecodeFinderCounters();
|
||||||
|
@ -288,6 +414,9 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
rowOffset = lastPair.getFinderPattern().getStartEnd()[1];
|
rowOffset = lastPair.getFinderPattern().getStartEnd()[1];
|
||||||
}
|
}
|
||||||
boolean searchingEvenPair = previousPairs.size() % 2 != 0;
|
boolean searchingEvenPair = previousPairs.size() % 2 != 0;
|
||||||
|
if (startFromEven) {
|
||||||
|
searchingEvenPair = !searchingEvenPair;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isWhite = false;
|
boolean isWhite = false;
|
||||||
while (rowOffset < width) {
|
while (rowOffset < width) {
|
||||||
|
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/1.png
Normal file
After Width: | Height: | Size: 347 B |
1
core/test/data/blackbox/rssexpandedstacked-1/1.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3103)012233(15)991231
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/10.png
Normal file
After Width: | Height: | Size: 336 B |
1
core/test/data/blackbox/rssexpandedstacked-1/10.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3203)010000
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/11.png
Normal file
After Width: | Height: | Size: 347 B |
1
core/test/data/blackbox/rssexpandedstacked-1/11.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3203)032767
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/12.png
Normal file
After Width: | Height: | Size: 347 B |
1
core/test/data/blackbox/rssexpandedstacked-1/12.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3922)795
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/13.png
Normal file
After Width: | Height: | Size: 509 B |
1
core/test/data/blackbox/rssexpandedstacked-1/13.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3922)795888888888888888888888888888888888888888888888888888
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/14.png
Normal file
After Width: | Height: | Size: 349 B |
1
core/test/data/blackbox/rssexpandedstacked-1/14.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3932)0401234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/15.png
Normal file
After Width: | Height: | Size: 348 B |
1
core/test/data/blackbox/rssexpandedstacked-1/15.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3932)040EUR
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/16.png
Normal file
After Width: | Height: | Size: 383 B |
1
core/test/data/blackbox/rssexpandedstacked-1/16.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3932)04055GBP
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/17.png
Normal file
After Width: | Height: | Size: 391 B |
1
core/test/data/blackbox/rssexpandedstacked-1/17.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3932)04066USD778899
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/18.png
Normal file
After Width: | Height: | Size: 382 B |
1
core/test/data/blackbox/rssexpandedstacked-1/18.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)00012345678905(10)ABC123
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/19.png
Normal file
After Width: | Height: | Size: 439 B |
1
core/test/data/blackbox/rssexpandedstacked-1/19.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)12345678901231(10)UNIVERSITY-OF-DEUSTO
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/2.png
Normal file
After Width: | Height: | Size: 347 B |
1
core/test/data/blackbox/rssexpandedstacked-1/2.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)91234567980129(3103)012233(15)991231
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/20.png
Normal file
After Width: | Height: | Size: 425 B |
1
core/test/data/blackbox/rssexpandedstacked-1/20.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)12345678901231(10)PIRAMIDE-PROJECT
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/21.png
Normal file
After Width: | Height: | Size: 392 B |
1
core/test/data/blackbox/rssexpandedstacked-1/21.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)12345678901231(10)TREELOGIC
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/22.png
Normal file
After Width: | Height: | Size: 514 B |
1
core/test/data/blackbox/rssexpandedstacked-1/22.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)98898765432106(15)991231(3103)001750(10)12A(422)123(21)123456(423)012345678901
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/23.png
Normal file
After Width: | Height: | Size: 476 B |
1
core/test/data/blackbox/rssexpandedstacked-1/23.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(15)991231(3103)001750(10)12A(422)123(21)123456(423)0123456789012
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/24.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/24.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)5678(11)010101
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/25.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/25.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)5678(11)001010
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/26.png
Normal file
After Width: | Height: | Size: 349 B |
1
core/test/data/blackbox/rssexpandedstacked-1/26.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)567890(11)010101
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/27.png
Normal file
After Width: | Height: | Size: 339 B |
1
core/test/data/blackbox/rssexpandedstacked-1/27.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)567(11)010101
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/28.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/28.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098-1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/29.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/29.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098,1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/3.png
Normal file
After Width: | Height: | Size: 348 B |
1
core/test/data/blackbox/rssexpandedstacked-1/3.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)91234567980129(3102)012233(15)991231
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/30.png
Normal file
After Width: | Height: | Size: 339 B |
1
core/test/data/blackbox/rssexpandedstacked-1/30.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098/1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/31.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/31.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098.1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/32.png
Normal file
After Width: | Height: | Size: 339 B |
1
core/test/data/blackbox/rssexpandedstacked-1/32.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098*1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/33.png
Normal file
After Width: | Height: | Size: 336 B |
1
core/test/data/blackbox/rssexpandedstacked-1/33.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098a1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/34.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/34.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098!1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/35.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/35.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098"1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/36.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/36.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098%1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/37.png
Normal file
After Width: | Height: | Size: 336 B |
1
core/test/data/blackbox/rssexpandedstacked-1/37.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098&1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/38.png
Normal file
After Width: | Height: | Size: 336 B |
1
core/test/data/blackbox/rssexpandedstacked-1/38.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098'1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/39.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/39.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098+1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/4.png
Normal file
After Width: | Height: | Size: 348 B |
1
core/test/data/blackbox/rssexpandedstacked-1/4.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)91234567980129(3102)012233(15)000101
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/40.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/40.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098:1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/41.png
Normal file
After Width: | Height: | Size: 336 B |
1
core/test/data/blackbox/rssexpandedstacked-1/41.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098;1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/42.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/42.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098<1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/43.png
Normal file
After Width: | Height: | Size: 337 B |
1
core/test/data/blackbox/rssexpandedstacked-1/43.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098=1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/44.png
Normal file
After Width: | Height: | Size: 339 B |
1
core/test/data/blackbox/rssexpandedstacked-1/44.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098>1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/45.png
Normal file
After Width: | Height: | Size: 335 B |
1
core/test/data/blackbox/rssexpandedstacked-1/45.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098?1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/46.png
Normal file
After Width: | Height: | Size: 339 B |
1
core/test/data/blackbox/rssexpandedstacked-1/46.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098_1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/47.png
Normal file
After Width: | Height: | Size: 336 B |
1
core/test/data/blackbox/rssexpandedstacked-1/47.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)1098 1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/48.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/48.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)123456A
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/49.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/49.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)123456A1
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/5.png
Normal file
After Width: | Height: | Size: 337 B |
1
core/test/data/blackbox/rssexpandedstacked-1/5.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(01)90012345678908(3103)001750
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/50.png
Normal file
After Width: | Height: | Size: 336 B |
1
core/test/data/blackbox/rssexpandedstacked-1/50.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)123456A123
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/51.png
Normal file
After Width: | Height: | Size: 338 B |
1
core/test/data/blackbox/rssexpandedstacked-1/51.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(10)123456A1234
|
BIN
core/test/data/blackbox/rssexpandedstacked-1/52.png
Normal file
After Width: | Height: | Size: 343 B |