mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Style changes mostly
git-svn-id: https://zxing.googlecode.com/svn/trunk@985 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
372dfa1145
commit
969088fa82
|
@ -1,3 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 ZXing authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.google.zxing.pdf417;
|
package com.google.zxing.pdf417;
|
||||||
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
@ -21,6 +37,7 @@ import java.util.Hashtable;
|
||||||
* @author SITA Lab (kevin.osullivan@sita.aero)
|
* @author SITA Lab (kevin.osullivan@sita.aero)
|
||||||
*/
|
*/
|
||||||
public final class PDF417Reader implements Reader {
|
public final class PDF417Reader implements Reader {
|
||||||
|
|
||||||
private static final ResultPoint[] NO_POINTS = new ResultPoint[0];
|
private static final ResultPoint[] NO_POINTS = new ResultPoint[0];
|
||||||
|
|
||||||
private final Decoder decoder = new Decoder();
|
private final Decoder decoder = new Decoder();
|
||||||
|
@ -48,8 +65,7 @@ public final class PDF417Reader implements Reader {
|
||||||
decoderResult = decoder.decode(detectorResult.getBits());
|
decoderResult = decoder.decode(detectorResult.getBits());
|
||||||
points = detectorResult.getPoints();
|
points = detectorResult.getPoints();
|
||||||
}
|
}
|
||||||
Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.PDF417);
|
return new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.PDF417);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2007 ZXing authors
|
* Copyright 2009 ZXing authors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.zxing.pdf417.decoder;
|
package com.google.zxing.pdf417.decoder;
|
||||||
|
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
|
@ -26,7 +27,7 @@ import com.google.zxing.common.BitMatrix;
|
||||||
* @author SITA Lab (kevin.osullivan@sita.aero)
|
* @author SITA Lab (kevin.osullivan@sita.aero)
|
||||||
*/
|
*/
|
||||||
final class BitMatrixParser {
|
final class BitMatrixParser {
|
||||||
public static final boolean debug = false;
|
|
||||||
private static final int MAX_ROW_DIFFERENCE = 6;
|
private static final int MAX_ROW_DIFFERENCE = 6;
|
||||||
private static final int MAX_ROWS = 90;
|
private static final int MAX_ROWS = 90;
|
||||||
private static final int MAX_COLUMNS = 30;
|
private static final int MAX_COLUMNS = 30;
|
||||||
|
@ -35,14 +36,14 @@ final class BitMatrixParser {
|
||||||
private static final int MODULES_IN_SYMBOL = 17;
|
private static final int MODULES_IN_SYMBOL = 17;
|
||||||
|
|
||||||
private final BitMatrix bitMatrix;
|
private final BitMatrix bitMatrix;
|
||||||
int rows = 0;
|
private int rows = 0;
|
||||||
int columns = 0;
|
private int columns = 0;
|
||||||
|
|
||||||
int leftColumnECData = 0;
|
private int leftColumnECData = 0;
|
||||||
int rightColumnECData = 0;
|
private int rightColumnECData = 0;
|
||||||
int eraseCount = 0;
|
private int eraseCount = 0;
|
||||||
int erasures[] = null;
|
private int[] erasures = null;
|
||||||
int ecLevel = -1;
|
private int ecLevel = -1;
|
||||||
|
|
||||||
BitMatrixParser(BitMatrix bitMatrix) {
|
BitMatrixParser(BitMatrix bitMatrix) {
|
||||||
this.bitMatrix = bitMatrix;
|
this.bitMatrix = bitMatrix;
|
||||||
|
@ -62,20 +63,19 @@ final class BitMatrixParser {
|
||||||
// TODO should be a rectangular matrix
|
// TODO should be a rectangular matrix
|
||||||
int height = width;
|
int height = width;
|
||||||
|
|
||||||
int rowHeight = 0;
|
|
||||||
int rowNumber = 0;
|
|
||||||
boolean rowInProgress = false;
|
|
||||||
int matchingConsecutiveScans = 0;
|
|
||||||
|
|
||||||
int next = 0;
|
|
||||||
int codewords[] = new int[MAX_CW_CAPACITY];
|
|
||||||
erasures = new int[MAX_CW_CAPACITY];
|
erasures = new int[MAX_CW_CAPACITY];
|
||||||
|
|
||||||
// Get the number of pixels in a module across the X dimension
|
// Get the number of pixels in a module across the X dimension
|
||||||
//float moduleWidth = bitMatrix.getModuleWidth();
|
//float moduleWidth = bitMatrix.getModuleWidth();
|
||||||
float moduleWidth = 1.0f; // Image has been sampled and reduced
|
float moduleWidth = 1.0f; // Image has been sampled and reduced
|
||||||
|
|
||||||
int rowCounters[] = new int[width];
|
int[] rowCounters = new int[width];
|
||||||
|
int[] codewords = new int[MAX_CW_CAPACITY];
|
||||||
|
int next = 0;
|
||||||
|
int matchingConsecutiveScans = 0;
|
||||||
|
boolean rowInProgress = false;
|
||||||
|
int rowNumber = 0;
|
||||||
|
int rowHeight = 0;
|
||||||
for (int i = 1; i < height; i++) {
|
for (int i = 1; i < height; i++) {
|
||||||
if (rowNumber >= MAX_ROWS) {
|
if (rowNumber >= MAX_ROWS) {
|
||||||
// Something is wrong, since we have exceeded
|
// Something is wrong, since we have exceeded
|
||||||
|
@ -113,9 +113,6 @@ final class BitMatrixParser {
|
||||||
} else {
|
} else {
|
||||||
if (rowInProgress) {
|
if (rowInProgress) {
|
||||||
// Process Row
|
// Process Row
|
||||||
if (debug)
|
|
||||||
System.out.println("Row Height=" + rowHeight + " Row Number="
|
|
||||||
+ rowNumber);
|
|
||||||
next = processRow(rowCounters, rowNumber, rowHeight,
|
next = processRow(rowCounters, rowNumber, rowHeight,
|
||||||
moduleWidth, codewords, next);
|
moduleWidth, codewords, next);
|
||||||
if (next == -1) {
|
if (next == -1) {
|
||||||
|
@ -139,9 +136,6 @@ final class BitMatrixParser {
|
||||||
// Check for a row that was in progress before we exited above.
|
// Check for a row that was in progress before we exited above.
|
||||||
if (rowInProgress) {
|
if (rowInProgress) {
|
||||||
// Process Row
|
// Process Row
|
||||||
if (debug)
|
|
||||||
System.out.println("Row Height=" + rowHeight + " Row Number="
|
|
||||||
+ rowNumber);
|
|
||||||
if (rowNumber >= MAX_ROWS) {
|
if (rowNumber >= MAX_ROWS) {
|
||||||
// Something is wrong, since we have exceeded
|
// Something is wrong, since we have exceeded
|
||||||
// the maximum rows in the specification.
|
// the maximum rows in the specification.
|
||||||
|
@ -153,8 +147,6 @@ final class BitMatrixParser {
|
||||||
rowNumber++;
|
rowNumber++;
|
||||||
rows = rowNumber;
|
rows = rowNumber;
|
||||||
}
|
}
|
||||||
if (debug)
|
|
||||||
System.out.println("Errors=" + eraseCount);
|
|
||||||
erasures = trimArray(erasures, eraseCount);
|
erasures = trimArray(erasures, eraseCount);
|
||||||
return trimArray(codewords, next);
|
return trimArray(codewords, next);
|
||||||
}
|
}
|
||||||
|
@ -162,13 +154,11 @@ final class BitMatrixParser {
|
||||||
/**
|
/**
|
||||||
* Trim the array to the required size.
|
* Trim the array to the required size.
|
||||||
*
|
*
|
||||||
* @param array
|
* @param array the array
|
||||||
* the array
|
* @param size the size to trim it to
|
||||||
* @param size
|
|
||||||
* the size to trim it to
|
|
||||||
* @return the new trimmed array
|
* @return the new trimmed array
|
||||||
*/
|
*/
|
||||||
private int[] trimArray(int array[], int size) {
|
private static int[] trimArray(int[] array, int size) {
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
int a[] = new int[size];
|
int a[] = new int[size];
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
|
@ -183,19 +173,13 @@ final class BitMatrixParser {
|
||||||
/**
|
/**
|
||||||
* Convert the symbols in the row to codewords.
|
* Convert the symbols in the row to codewords.
|
||||||
*
|
*
|
||||||
* @param rowCounters
|
* @param rowCounters an array containing the counts of black pixels for each column
|
||||||
* an array containing the counts of black pixels for each column
|
|
||||||
* in the row.
|
* in the row.
|
||||||
* @param rowNumber
|
* @param rowNumber the current row number of codewords.
|
||||||
* the current row number of codewords.
|
* @param rowHeight the height of this row in pixels.
|
||||||
* @param rowHeight
|
* @param moduleWidth the size of a module in pixels.
|
||||||
* the height of this row in pixels.
|
* @param codewords the codeword array to save codewords into.
|
||||||
* @param moduleWidth
|
* @param next the next available index into the codewords array.
|
||||||
* the size of a module in pixels.
|
|
||||||
* @param codewords
|
|
||||||
* the codeword array to save codewords into.
|
|
||||||
* @param next
|
|
||||||
* the next available index into the codewords array.
|
|
||||||
* @return the next available index into the codeword array after processing
|
* @return the next available index into the codeword array after processing
|
||||||
* this row.
|
* this row.
|
||||||
* @throws ReaderException
|
* @throws ReaderException
|
||||||
|
@ -205,8 +189,8 @@ final class BitMatrixParser {
|
||||||
* elements, each of which can be one to six modules wide. The four bar and
|
* elements, each of which can be one to six modules wide. The four bar and
|
||||||
* four space elements shall measure 17 modules in total.
|
* four space elements shall measure 17 modules in total.
|
||||||
*/
|
*/
|
||||||
int processRow(int rowCounters[], int rowNumber, int rowHeight,
|
int processRow(int[] rowCounters, int rowNumber, int rowHeight,
|
||||||
float moduleWidth, int codewords[], int next) throws ReaderException {
|
float moduleWidth, int[] codewords, int next) throws ReaderException {
|
||||||
int width = bitMatrix.getDimension();
|
int width = bitMatrix.getDimension();
|
||||||
int columnNumber = 0;
|
int columnNumber = 0;
|
||||||
long symbol = 0;
|
long symbol = 0;
|
||||||
|
@ -277,8 +261,7 @@ final class BitMatrixParser {
|
||||||
/**
|
/**
|
||||||
* Build a symbol from the pixels
|
* Build a symbol from the pixels
|
||||||
*
|
*
|
||||||
* @param counters
|
* @param counters array of pixel counter corresponding to each Bar/Space pattern.
|
||||||
* array of pixel counter corresponding to each Bar/Space pattern.
|
|
||||||
* @param rowNumber
|
* @param rowNumber
|
||||||
* @return the symbol
|
* @return the symbol
|
||||||
*/
|
*/
|
||||||
|
@ -287,17 +270,15 @@ final class BitMatrixParser {
|
||||||
* represents the module widths of the eight elements of that symbol
|
* represents the module widths of the eight elements of that symbol
|
||||||
* character.
|
* character.
|
||||||
*/
|
*/
|
||||||
private long getSymbol(int counters[], int rowNumber, float moduleWidth) {
|
private static long getSymbol(int[] counters, int rowNumber, float moduleWidth) {
|
||||||
int symbol = 0;
|
|
||||||
int pixelsInSymbol = 0;
|
int pixelsInSymbol = 0;
|
||||||
for (int j = 0; j < counters.length; j++) {
|
for (int j = 0; j < counters.length; j++) {
|
||||||
pixelsInSymbol += counters[j];
|
pixelsInSymbol += counters[j];
|
||||||
}
|
}
|
||||||
float avgModuleWidth = (pixelsInSymbol / 17.0f);
|
float avgModuleWidth = (pixelsInSymbol / 17.0f);
|
||||||
if (debug)
|
|
||||||
System.out.println("Average Module Width = " + avgModuleWidth);
|
|
||||||
boolean toggle = true;
|
boolean toggle = true;
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
|
int symbol = 0;
|
||||||
for (int j = 0; j < counters.length; j++) {
|
for (int j = 0; j < counters.length; j++) {
|
||||||
if (counters[j] < moduleWidth && counters[j] > 0) {
|
if (counters[j] < moduleWidth && counters[j] > 0) {
|
||||||
// Give a very narrow bar/space a chance
|
// Give a very narrow bar/space a chance
|
||||||
|
@ -335,18 +316,16 @@ final class BitMatrixParser {
|
||||||
* @throws ReaderException
|
* @throws ReaderException
|
||||||
*/
|
*/
|
||||||
private int getCodeword(long symbol, int row) throws ReaderException {
|
private int getCodeword(long symbol, int row) throws ReaderException {
|
||||||
long cw = 0;
|
|
||||||
|
|
||||||
long sym = symbol;
|
long sym = symbol;
|
||||||
sym &= 0x3ffff;
|
sym &= 0x3ffff;
|
||||||
int i = findCodewordIndex(sym);
|
int i = findCodewordIndex(sym);
|
||||||
if (i != -1) {
|
long cw = 0;
|
||||||
cw = codewordTable[i] - 1;
|
if (i == -1) {
|
||||||
cw = cw % 929;
|
|
||||||
} else {
|
|
||||||
if (debug)
|
|
||||||
System.out.println("UNABLE TO FIND " + symbol); // Long.toBinaryString(symbol));
|
|
||||||
return -1;
|
return -1;
|
||||||
|
} else {
|
||||||
|
cw = CODEWORD_TABLE[i] - 1;
|
||||||
|
cw %= 929;
|
||||||
}
|
}
|
||||||
return (int) cw;
|
return (int) cw;
|
||||||
}
|
}
|
||||||
|
@ -355,18 +334,17 @@ final class BitMatrixParser {
|
||||||
* Use a binary search to find the index of the codeword corresponding to
|
* Use a binary search to find the index of the codeword corresponding to
|
||||||
* this symbol.
|
* this symbol.
|
||||||
*
|
*
|
||||||
* @param symbol
|
* @param symbol the symbol from the barcode.
|
||||||
* the symbol from the barcode.
|
|
||||||
* @return the index into the codeword table.
|
* @return the index into the codeword table.
|
||||||
*/
|
*/
|
||||||
private int findCodewordIndex(long symbol) throws ReaderException {
|
private int findCodewordIndex(long symbol) {
|
||||||
int first = 0;
|
int first = 0;
|
||||||
int upto = symbolTable.length;
|
int upto = SYMBOL_TABLE.length;
|
||||||
while (first < upto) {
|
while (first < upto) {
|
||||||
int mid = (first + upto) / 2; // Compute mid point.
|
int mid = (first + upto) / 2; // Compute mid point.
|
||||||
if (symbol < symbolTable[mid]) {
|
if (symbol < SYMBOL_TABLE[mid]) {
|
||||||
upto = mid; // repeat search in bottom half.
|
upto = mid; // repeat search in bottom half.
|
||||||
} else if (symbol > symbolTable[mid]) {
|
} else if (symbol > SYMBOL_TABLE[mid]) {
|
||||||
first = mid + 1; // Repeat search in top half.
|
first = mid + 1; // Repeat search in top half.
|
||||||
} else {
|
} else {
|
||||||
return mid; // Found it. return position
|
return mid; // Found it. return position
|
||||||
|
@ -405,33 +383,24 @@ final class BitMatrixParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the symbols in the row to codewords.
|
* Convert the symbols in the row to codewords.
|
||||||
|
* Each PDF417 symbol character consists of four bar elements and four space
|
||||||
|
* elements, each of which can be one to six modules wide. The four bar and
|
||||||
|
* four space elements shall measure 17 modules in total.
|
||||||
*
|
*
|
||||||
* @param rowCounters
|
* @param rowCounters an array containing the counts of black pixels for each column
|
||||||
* an array containing the counts of black pixels for each column
|
|
||||||
* in the row.
|
* in the row.
|
||||||
* @param rowNumber
|
* @param rowNumber the current row number of codewords.
|
||||||
* the current row number of codewords.
|
* @param rowHeight the height of this row in pixels.
|
||||||
* @param rowHeight
|
* @param moduleWidth the size of a module in pixels.
|
||||||
* the height of this row in pixels.
|
* @param codewords the codeword array to save codewords into.
|
||||||
* @param moduleWidth
|
* @param next the next available index into the codewords array.
|
||||||
* the size of a module in pixels.
|
|
||||||
* @param codewords
|
|
||||||
* the codeword array to save codewords into.
|
|
||||||
* @param next
|
|
||||||
* the next available index into the codewords array.
|
|
||||||
* @return the next available index into the codeword array after processing
|
* @return the next available index into the codeword array after processing
|
||||||
* this row.
|
* this row.
|
||||||
* @throws ReaderException
|
* @throws ReaderException
|
||||||
*/
|
*/
|
||||||
/*
|
int processRow1(int[] rowCounters, int rowNumber, int rowHeight,
|
||||||
* Each PDF417 symbol character consists of four bar elements and four space
|
float moduleWidth, int[] codewords, int next) throws ReaderException {
|
||||||
* elements, each of which can be one to six modules wide. The four bar and
|
|
||||||
* four space elements shall measure 17 modules in total.
|
|
||||||
*/
|
|
||||||
int processRow1(int rowCounters[], int rowNumber, int rowHeight,
|
|
||||||
float moduleWidth, int codewords[], int next) throws ReaderException {
|
|
||||||
int width = bitMatrix.getDimension();
|
int width = bitMatrix.getDimension();
|
||||||
int columnNumber = 0;
|
|
||||||
int firstBlack = 0;
|
int firstBlack = 0;
|
||||||
|
|
||||||
for (firstBlack = 0; firstBlack < width; firstBlack++) {
|
for (firstBlack = 0; firstBlack < width; firstBlack++) {
|
||||||
|
@ -441,9 +410,10 @@ final class BitMatrixParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int counters[] = new int[8];
|
int[] counters = new int[8];
|
||||||
int state = 0; // In black pixels, looking for white, first or second time
|
int state = 0; // In black pixels, looking for white, first or second time
|
||||||
long symbol = 0;
|
long symbol = 0;
|
||||||
|
int columnNumber = 0;
|
||||||
for (int i = firstBlack; i < width; i++) {
|
for (int i = firstBlack; i < width; i++) {
|
||||||
if (state == 1 || state == 3 || state == 5 || state == 7) { // In white
|
if (state == 1 || state == 3 || state == 5 || state == 7) { // In white
|
||||||
// pixels,
|
// pixels,
|
||||||
|
@ -508,10 +478,6 @@ final class BitMatrixParser {
|
||||||
// Left row indicator column
|
// Left row indicator column
|
||||||
symbol = getSymbol(counters, rowNumber, moduleWidth);
|
symbol = getSymbol(counters, rowNumber, moduleWidth);
|
||||||
int cw = getCodeword(symbol, rowNumber);
|
int cw = getCodeword(symbol, rowNumber);
|
||||||
if (debug) {
|
|
||||||
System.out.println("Left Column CW=" + cw + " Cluster="
|
|
||||||
+ rowNumber % 3);
|
|
||||||
}
|
|
||||||
if (ecLevel < 0) {
|
if (ecLevel < 0) {
|
||||||
switch (rowNumber % 3) {
|
switch (rowNumber % 3) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -564,9 +530,6 @@ final class BitMatrixParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
codewords[next] = 0;
|
codewords[next] = 0;
|
||||||
if (debug)
|
|
||||||
System.out.println("Right Column CW=" + codewords[next]
|
|
||||||
+ " Cluster=" + rowNumber % 3);
|
|
||||||
}
|
}
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
@ -576,7 +539,7 @@ final class BitMatrixParser {
|
||||||
* specification. The index of a symbol in this table corresponds to the
|
* specification. The index of a symbol in this table corresponds to the
|
||||||
* index into the codeword table.
|
* index into the codeword table.
|
||||||
*/
|
*/
|
||||||
private static final int symbolTable[] = { 0x1025e, 0x1027a, 0x1029e,
|
private static final int[] SYMBOL_TABLE = {0x1025e, 0x1027a, 0x1029e,
|
||||||
0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396,
|
0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396,
|
||||||
0x103a6, 0x103ac, 0x10422, 0x10428, 0x10436, 0x10442, 0x10444,
|
0x103a6, 0x103ac, 0x10422, 0x10428, 0x10436, 0x10442, 0x10444,
|
||||||
0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482,
|
0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482,
|
||||||
|
@ -974,12 +937,12 @@ final class BitMatrixParser {
|
||||||
0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6,
|
0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6,
|
||||||
0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c, 0x1fb3a, 0x1fb46, 0x1fb4c,
|
0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c, 0x1fb3a, 0x1fb46, 0x1fb4c,
|
||||||
0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94,
|
0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94,
|
||||||
0x1fba2, 0x1fba4, 0x1fba8, 0x1fbb6, 0x1fbda };
|
0x1fba2, 0x1fba4, 0x1fba8, 0x1fbb6, 0x1fbda};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This table contains to codewords for all symbols.
|
* This table contains to codewords for all symbols.
|
||||||
*/
|
*/
|
||||||
private static final int codewordTable[] = { 2627, 1819, 2622, 2621, 1813,
|
private static final int[] CODEWORD_TABLE = {2627, 1819, 2622, 2621, 1813,
|
||||||
1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865,
|
1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865,
|
||||||
861, 859, 2511, 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844,
|
861, 859, 2511, 873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844,
|
||||||
1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815, 814, 813,
|
1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815, 814, 813,
|
||||||
|
@ -1207,5 +1170,5 @@ final class BitMatrixParser {
|
||||||
2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954, 1001, 998, 1924, 1921,
|
2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954, 1001, 998, 1924, 1921,
|
||||||
1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882,
|
1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882,
|
||||||
1323, 1273, 1270, 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576,
|
1323, 1273, 1270, 2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576,
|
||||||
1543, 1540, 1484, 1481, 1478, 1491, 1700 };
|
1543, 1540, 1484, 1481, 1478, 1491, 1700};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2007 ZXing authors
|
* Copyright 2009 ZXing authors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.zxing.pdf417.decoder;
|
package com.google.zxing.pdf417.decoder;
|
||||||
|
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
|
@ -24,7 +25,6 @@ import com.google.zxing.common.DecoderResult;
|
||||||
* @author SITA Lab (kevin.osullivan@sita.aero)
|
* @author SITA Lab (kevin.osullivan@sita.aero)
|
||||||
*/
|
*/
|
||||||
final class DecodedBitStreamParser {
|
final class DecodedBitStreamParser {
|
||||||
public static final boolean debug = true;
|
|
||||||
|
|
||||||
private static final int TEXT_COMPACTION_MODE_LATCH = 900;
|
private static final int TEXT_COMPACTION_MODE_LATCH = 900;
|
||||||
private static final int BYTE_COMPACTION_MODE_LATCH = 901;
|
private static final int BYTE_COMPACTION_MODE_LATCH = 901;
|
||||||
|
@ -50,18 +50,18 @@ final class DecodedBitStreamParser {
|
||||||
private static final int PS = 29;
|
private static final int PS = 29;
|
||||||
private static final int PAL = 29;
|
private static final int PAL = 29;
|
||||||
|
|
||||||
private static final char punct_chars[] = {';', '<', '>', '@', '[', 92, '}', '_', 96, '~', '!',
|
private static final char[] PUNCT_CHARS = {';', '<', '>', '@', '[', 92, '}', '_', 96, '~', '!',
|
||||||
13, 9, ',', ':', 10, '-', '.', '$', '/', 34, '|', '*',
|
13, 9, ',', ':', 10, '-', '.', '$', '/', 34, '|', '*',
|
||||||
'(', ')', '?', '{', '}', 39};
|
'(', ')', '?', '{', '}', 39};
|
||||||
|
|
||||||
private static final char mixed_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&',
|
private static final char[] MIXED_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&',
|
||||||
13, 9, ',', ':', '#', '-', '.', '$', '/', '+', '%', '*',
|
13, 9, ',', ':', '#', '-', '.', '$', '/', '+', '%', '*',
|
||||||
'=', '^'};
|
'=', '^'};
|
||||||
|
|
||||||
// Table containing values for the exponent of 900.
|
// Table containing values for the exponent of 900.
|
||||||
// This is used in the numeric compaction decode algorithm.
|
// This is used in the numeric compaction decode algorithm.
|
||||||
private static final String exp900[] =
|
private static final String[] EXP900 =
|
||||||
{"000000000000000000000000000000000000000000001",
|
{ "000000000000000000000000000000000000000000001",
|
||||||
"000000000000000000000000000000000000000000900",
|
"000000000000000000000000000000000000000000900",
|
||||||
"000000000000000000000000000000000000000810000",
|
"000000000000000000000000000000000000000810000",
|
||||||
"000000000000000000000000000000000000729000000",
|
"000000000000000000000000000000000000729000000",
|
||||||
|
@ -81,13 +81,13 @@ final class DecodedBitStreamParser {
|
||||||
private DecodedBitStreamParser() {
|
private DecodedBitStreamParser() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static DecoderResult decode(int codewords[]) throws ReaderException {
|
static DecoderResult decode(int[] codewords) throws ReaderException {
|
||||||
StringBuffer result = new StringBuffer(100);
|
StringBuffer result = new StringBuffer(100);
|
||||||
// Get compaction mode
|
// Get compaction mode
|
||||||
int codeIndex = 1;
|
int codeIndex = 1;
|
||||||
int code = codewords[codeIndex++];
|
int code = codewords[codeIndex++];
|
||||||
while (codeIndex < codewords[0]) {
|
while (codeIndex < codewords[0]) {
|
||||||
switch(code) {
|
switch (code) {
|
||||||
case TEXT_COMPACTION_MODE_LATCH: {
|
case TEXT_COMPACTION_MODE_LATCH: {
|
||||||
codeIndex = textCompaction(codewords, codeIndex, result);
|
codeIndex = textCompaction(codewords, codeIndex, result);
|
||||||
break;
|
break;
|
||||||
|
@ -123,7 +123,6 @@ final class DecodedBitStreamParser {
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debug) System.out.println(result);
|
|
||||||
return new DecoderResult(null, result.toString(), null);
|
return new DecoderResult(null, result.toString(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,20 +136,20 @@ final class DecodedBitStreamParser {
|
||||||
* @param result The decoded data is appended to the result.
|
* @param result The decoded data is appended to the result.
|
||||||
* @return The next index into the codeword array.
|
* @return The next index into the codeword array.
|
||||||
*/
|
*/
|
||||||
private static int textCompaction(int codewords[], int codeIndex, StringBuffer result) {
|
private static int textCompaction(int[] codewords, int codeIndex, StringBuffer result) {
|
||||||
// 2 character per codeword
|
// 2 character per codeword
|
||||||
int textCompactionData[] = new int[codewords[0] * 2];
|
int[] textCompactionData = new int[codewords[0] * 2];
|
||||||
// Used to hold the byte compaction value if there is a mode shift
|
// Used to hold the byte compaction value if there is a mode shift
|
||||||
int byteCompactionData[] = new int[codewords[0] * 2];
|
int[] byteCompactionData = new int[codewords[0] * 2];
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int code = 0;
|
int code = 0;
|
||||||
boolean end = false;
|
boolean end = false;
|
||||||
while((codeIndex < codewords[0]) && !end) {
|
while ((codeIndex < codewords[0]) && !end) {
|
||||||
code = codewords[codeIndex++];
|
code = codewords[codeIndex++];
|
||||||
if (code < TEXT_COMPACTION_MODE_LATCH) {
|
if (code < TEXT_COMPACTION_MODE_LATCH) {
|
||||||
textCompactionData[index] = code / 30;
|
textCompactionData[index] = code / 30;
|
||||||
textCompactionData[index+1] = code % 30;
|
textCompactionData[index + 1] = code % 30;
|
||||||
index += 2;
|
index += 2;
|
||||||
} else {
|
} else {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
@ -209,8 +208,8 @@ final class DecodedBitStreamParser {
|
||||||
* @param length The size of the text compaction and byte compaction data.
|
* @param length The size of the text compaction and byte compaction data.
|
||||||
* @param result The decoded data is appended to the result.
|
* @param result The decoded data is appended to the result.
|
||||||
*/
|
*/
|
||||||
private static void decodeTextCompaction(int textCompactionData[],
|
private static void decodeTextCompaction(int[] textCompactionData,
|
||||||
int byteCompactionData[],
|
int[] byteCompactionData,
|
||||||
int length,
|
int length,
|
||||||
StringBuffer result) {
|
StringBuffer result) {
|
||||||
// Beginning from an initial state of the Alpha sub-mode
|
// Beginning from an initial state of the Alpha sub-mode
|
||||||
|
@ -223,12 +222,12 @@ final class DecodedBitStreamParser {
|
||||||
while (i < length) {
|
while (i < length) {
|
||||||
int subModeCh = textCompactionData[i];
|
int subModeCh = textCompactionData[i];
|
||||||
char ch = 0;
|
char ch = 0;
|
||||||
switch(subMode) {
|
switch (subMode) {
|
||||||
case ALPHA :
|
case ALPHA:
|
||||||
// Alpha (uppercase alphabetic)
|
// Alpha (uppercase alphabetic)
|
||||||
if (subModeCh < 26) {
|
if (subModeCh < 26) {
|
||||||
// Upper case Alpha Character
|
// Upper case Alpha Character
|
||||||
ch = (char)('A' + subModeCh);
|
ch = (char) ('A' + subModeCh);
|
||||||
} else {
|
} else {
|
||||||
if (subModeCh == 26) {
|
if (subModeCh == 26) {
|
||||||
ch = ' ';
|
ch = ' ';
|
||||||
|
@ -241,15 +240,15 @@ final class DecodedBitStreamParser {
|
||||||
priorToShiftMode = subMode;
|
priorToShiftMode = subMode;
|
||||||
subMode = PUNCT_SHIFT;
|
subMode = PUNCT_SHIFT;
|
||||||
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
||||||
result.append((char)byteCompactionData[i]);
|
result.append((char) byteCompactionData[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOWER :
|
case LOWER:
|
||||||
// Lower (lowercase alphabetic)
|
// Lower (lowercase alphabetic)
|
||||||
if (subModeCh < 26) {
|
if (subModeCh < 26) {
|
||||||
ch = (char)('a' + subModeCh);
|
ch = (char) ('a' + subModeCh);
|
||||||
} else {
|
} else {
|
||||||
if (subModeCh == 26) {
|
if (subModeCh == 26) {
|
||||||
ch = ' ';
|
ch = ' ';
|
||||||
|
@ -262,15 +261,15 @@ final class DecodedBitStreamParser {
|
||||||
priorToShiftMode = subMode;
|
priorToShiftMode = subMode;
|
||||||
subMode = PUNCT_SHIFT;
|
subMode = PUNCT_SHIFT;
|
||||||
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
||||||
result.append((char)byteCompactionData[i]);
|
result.append((char) byteCompactionData[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIXED :
|
case MIXED:
|
||||||
// Mixed (numeric and some punctuation)
|
// Mixed (numeric and some punctuation)
|
||||||
if ( subModeCh < PL ) {
|
if (subModeCh < PL) {
|
||||||
ch = mixed_chars[subModeCh];
|
ch = MIXED_CHARS[subModeCh];
|
||||||
} else {
|
} else {
|
||||||
if (subModeCh == PL) {
|
if (subModeCh == PL) {
|
||||||
subMode = PUNCT;
|
subMode = PUNCT;
|
||||||
|
@ -285,29 +284,29 @@ final class DecodedBitStreamParser {
|
||||||
priorToShiftMode = subMode;
|
priorToShiftMode = subMode;
|
||||||
subMode = PUNCT_SHIFT;
|
subMode = PUNCT_SHIFT;
|
||||||
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
||||||
result.append((char)byteCompactionData[i]);
|
result.append((char) byteCompactionData[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PUNCT :
|
case PUNCT:
|
||||||
// Punctuation
|
// Punctuation
|
||||||
if (subModeCh < PS) {
|
if (subModeCh < PS) {
|
||||||
ch = punct_chars[subModeCh];
|
ch = PUNCT_CHARS[subModeCh];
|
||||||
} else {
|
} else {
|
||||||
if (subModeCh == PAL) {
|
if (subModeCh == PAL) {
|
||||||
subMode = ALPHA;
|
subMode = ALPHA;
|
||||||
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
||||||
result.append((char)byteCompactionData[i]);
|
result.append((char) byteCompactionData[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PUNCT_SHIFT :
|
case PUNCT_SHIFT:
|
||||||
// Restore sub-mode
|
// Restore sub-mode
|
||||||
subMode = priorToShiftMode;
|
subMode = priorToShiftMode;
|
||||||
if (subModeCh < PS) {
|
if (subModeCh < PS) {
|
||||||
ch = punct_chars[subModeCh];
|
ch = PUNCT_CHARS[subModeCh];
|
||||||
} else {
|
} else {
|
||||||
if (subModeCh == PAL) {
|
if (subModeCh == PAL) {
|
||||||
subMode = ALPHA;
|
subMode = ALPHA;
|
||||||
|
@ -315,7 +314,7 @@ final class DecodedBitStreamParser {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ch !=0) {
|
if (ch != 0) {
|
||||||
// Append decoded character to result
|
// Append decoded character to result
|
||||||
result.append(ch);
|
result.append(ch);
|
||||||
}
|
}
|
||||||
|
@ -327,23 +326,24 @@ final class DecodedBitStreamParser {
|
||||||
* Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded.
|
* Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded.
|
||||||
* This includes all ASCII characters value 0 to 127 inclusive and provides for international
|
* This includes all ASCII characters value 0 to 127 inclusive and provides for international
|
||||||
* character set support.
|
* character set support.
|
||||||
|
*
|
||||||
* @param mode The byte compaction mode i.e. 901 or 924
|
* @param mode The byte compaction mode i.e. 901 or 924
|
||||||
* @param codewords The array of codewords (data + error)
|
* @param codewords The array of codewords (data + error)
|
||||||
* @param codeIndex The current index into the codeword array.
|
* @param codeIndex The current index into the codeword array.
|
||||||
* @param result The decoded data is appended to the result.
|
* @param result The decoded data is appended to the result.
|
||||||
* @return The next index into the codeword array.
|
* @return The next index into the codeword array.
|
||||||
*/
|
*/
|
||||||
private static int byteCompaction(int mode, int codewords[], int codeIndex, StringBuffer result) {
|
private static int byteCompaction(int mode, int[] codewords, int codeIndex, StringBuffer result) {
|
||||||
if (mode == BYTE_COMPACTION_MODE_LATCH) {
|
if (mode == BYTE_COMPACTION_MODE_LATCH) {
|
||||||
// Total number of Byte Compaction characters to be encoded
|
// Total number of Byte Compaction characters to be encoded
|
||||||
// is not a multiple of 6
|
// is not a multiple of 6
|
||||||
int count = 0;
|
int count = 0;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
char decodedData[] = new char[6];
|
char[] decodedData = new char[6];
|
||||||
int byteCompactedCodewords[] = new int[6];
|
int[] byteCompactedCodewords = new int[6];
|
||||||
int code = 0;
|
int code = 0;
|
||||||
boolean end = false;
|
boolean end = false;
|
||||||
while(( codeIndex < codewords[0]) && !end) {
|
while ((codeIndex < codewords[0]) && !end) {
|
||||||
code = codewords[codeIndex++];
|
code = codewords[codeIndex++];
|
||||||
if (code < TEXT_COMPACTION_MODE_LATCH) {
|
if (code < TEXT_COMPACTION_MODE_LATCH) {
|
||||||
byteCompactedCodewords[count] = code;
|
byteCompactedCodewords[count] = code;
|
||||||
|
@ -377,8 +377,8 @@ final class DecodedBitStreamParser {
|
||||||
// If Byte Compaction mode is invoked with codeword 901,
|
// If Byte Compaction mode is invoked with codeword 901,
|
||||||
// the final group of codewords is interpreted directly
|
// the final group of codewords is interpreted directly
|
||||||
// as one byte per codeword, without compaction.
|
// as one byte per codeword, without compaction.
|
||||||
for (int i = (( count / 5) * 5); i < count; i++) {
|
for (int i = ((count / 5) * 5); i < count; i++) {
|
||||||
result.append((char)byteCompactedCodewords[i]);
|
result.append((char) byteCompactedCodewords[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (mode == BYTE_COMPACTION_MODE_LATCH_6) {
|
} else if (mode == BYTE_COMPACTION_MODE_LATCH_6) {
|
||||||
|
@ -388,9 +388,8 @@ final class DecodedBitStreamParser {
|
||||||
long value = 0;
|
long value = 0;
|
||||||
int code = 0;
|
int code = 0;
|
||||||
boolean end = false;
|
boolean end = false;
|
||||||
while(( codeIndex < codewords[0]) && !end) {
|
while ((codeIndex < codewords[0]) && !end) {
|
||||||
code = codewords[codeIndex++];
|
code = codewords[codeIndex++];
|
||||||
char decodedData[] = new char[6];
|
|
||||||
if (code < TEXT_COMPACTION_MODE_LATCH) {
|
if (code < TEXT_COMPACTION_MODE_LATCH) {
|
||||||
count += 1;
|
count += 1;
|
||||||
// Base 900
|
// Base 900
|
||||||
|
@ -408,9 +407,10 @@ final class DecodedBitStreamParser {
|
||||||
codeIndex--;
|
codeIndex--;
|
||||||
end = true;
|
end = true;
|
||||||
}
|
}
|
||||||
if ((count % 5 == 0) && ( count > 0)) {
|
if ((count % 5 == 0) && (count > 0)) {
|
||||||
// Decode every 5 codewords
|
// Decode every 5 codewords
|
||||||
// Convert to Base 256
|
// Convert to Base 256
|
||||||
|
char[] decodedData = new char[6];
|
||||||
for (int j = 0; j < 6; ++j) {
|
for (int j = 0; j < 6; ++j) {
|
||||||
decodedData[5 - j] = (char) (value % 256);
|
decodedData[5 - j] = (char) (value % 256);
|
||||||
value >>= 8;
|
value >>= 8;
|
||||||
|
@ -430,15 +430,14 @@ final class DecodedBitStreamParser {
|
||||||
* @param result The decoded data is appended to the result.
|
* @param result The decoded data is appended to the result.
|
||||||
* @return The next index into the codeword array.
|
* @return The next index into the codeword array.
|
||||||
*/
|
*/
|
||||||
private static int numericCompaction(int codewords[], int codeIndex, StringBuffer result) {
|
private static int numericCompaction(int[] codewords, int codeIndex, StringBuffer result) {
|
||||||
int code;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
boolean end = false;
|
boolean end = false;
|
||||||
|
|
||||||
int numericCodewords[] = new int[MAX_NUMERIC_CODEWORDS];
|
int[] numericCodewords = new int[MAX_NUMERIC_CODEWORDS];
|
||||||
|
|
||||||
while ((codeIndex < codewords.length) && !end) {
|
while ((codeIndex < codewords.length) && !end) {
|
||||||
code = codewords[codeIndex++];
|
int code = codewords[codeIndex++];
|
||||||
if (code < TEXT_COMPACTION_MODE_LATCH) {
|
if (code < TEXT_COMPACTION_MODE_LATCH) {
|
||||||
numericCodewords[count] = code;
|
numericCodewords[count] = code;
|
||||||
count++;
|
count++;
|
||||||
|
@ -469,6 +468,7 @@ final class DecodedBitStreamParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a list of Numeric Compacted codewords from Base 900 to Base 10.
|
* Convert a list of Numeric Compacted codewords from Base 900 to Base 10.
|
||||||
|
*
|
||||||
* @param codewords The array of codewords
|
* @param codewords The array of codewords
|
||||||
* @param count The number of codewords
|
* @param count The number of codewords
|
||||||
* @return The decoded string representing the Numeric data.
|
* @return The decoded string representing the Numeric data.
|
||||||
|
@ -513,11 +513,11 @@ final class DecodedBitStreamParser {
|
||||||
tokens for the numbers.
|
tokens for the numbers.
|
||||||
BigDecimal is not supported by J2ME.
|
BigDecimal is not supported by J2ME.
|
||||||
*/
|
*/
|
||||||
private static String decodeBase900toBase10(int codewords[], int count) {
|
private static String decodeBase900toBase10(int[] codewords, int count) {
|
||||||
StringBuffer accum = null;
|
StringBuffer accum = null;
|
||||||
StringBuffer value = null;
|
StringBuffer value = null;
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
value = multiply(exp900[count - i - 1], codewords[i]);
|
value = multiply(EXP900[count - i - 1], codewords[i]);
|
||||||
if (accum == null) {
|
if (accum == null) {
|
||||||
// First time in accum=0
|
// First time in accum=0
|
||||||
accum = value;
|
accum = value;
|
||||||
|
@ -531,7 +531,7 @@ final class DecodedBitStreamParser {
|
||||||
for (int i = 0; i < accum.length(); i++) {
|
for (int i = 0; i < accum.length(); i++) {
|
||||||
if (accum.charAt(i) == '1') {
|
if (accum.charAt(i) == '1') {
|
||||||
//result = accum.substring(i + 1);
|
//result = accum.substring(i + 1);
|
||||||
result = accum.toString().substring(i+1);
|
result = accum.toString().substring(i + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,12 +539,12 @@ final class DecodedBitStreamParser {
|
||||||
// No leading 1 => just write the converted number.
|
// No leading 1 => just write the converted number.
|
||||||
result = accum.toString();
|
result = accum.toString();
|
||||||
}
|
}
|
||||||
if (debug) System.out.println("Big Integer=" + result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiplies two String numbers
|
* Multiplies two String numbers
|
||||||
|
*
|
||||||
* @param value1 Any number represented as a string.
|
* @param value1 Any number represented as a string.
|
||||||
* @param value2 A number <= 999.
|
* @param value2 A number <= 999.
|
||||||
* @return the result of value1 * value2.
|
* @return the result of value1 * value2.
|
||||||
|
@ -559,15 +559,15 @@ final class DecodedBitStreamParser {
|
||||||
int tens = (value2 / 10) % 10;
|
int tens = (value2 / 10) % 10;
|
||||||
int ones = value2 % 10;
|
int ones = value2 % 10;
|
||||||
// Multiply by ones
|
// Multiply by ones
|
||||||
for (int j = 0; j < ones ; j++) {
|
for (int j = 0; j < ones; j++) {
|
||||||
result = add(result.toString(), value1);
|
result = add(result.toString(), value1);
|
||||||
}
|
}
|
||||||
// Multiply by tens
|
// Multiply by tens
|
||||||
for (int j = 0; j < tens ; j++) {
|
for (int j = 0; j < tens; j++) {
|
||||||
result = add(result.toString(), (value1 + "0").substring(1));
|
result = add(result.toString(), (value1 + '0').substring(1));
|
||||||
}
|
}
|
||||||
// Multiply by hundreds
|
// Multiply by hundreds
|
||||||
for (int j = 0; j < hundreds ; j++) {
|
for (int j = 0; j < hundreds; j++) {
|
||||||
result = add(result.toString(), (value1 + "00").substring(2));
|
result = add(result.toString(), (value1 + "00").substring(2));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -575,6 +575,7 @@ final class DecodedBitStreamParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add two numbers which are represented as strings.
|
* Add two numbers which are represented as strings.
|
||||||
|
*
|
||||||
* @param value1
|
* @param value1
|
||||||
* @param value2
|
* @param value2
|
||||||
* @return the result of value1 + value2
|
* @return the result of value1 + value2
|
||||||
|
@ -588,7 +589,7 @@ final class DecodedBitStreamParser {
|
||||||
result.append('0');
|
result.append('0');
|
||||||
}
|
}
|
||||||
int carry = 0;
|
int carry = 0;
|
||||||
for (int i = value1.length()-3; i > -1 ; i-=3) {
|
for (int i = value1.length() - 3; i > -1; i -= 3) {
|
||||||
|
|
||||||
temp1.setLength(0);
|
temp1.setLength(0);
|
||||||
temp1.append(value1.charAt(i));
|
temp1.append(value1.charAt(i));
|
||||||
|
@ -603,12 +604,12 @@ final class DecodedBitStreamParser {
|
||||||
int intValue1 = Integer.parseInt(temp1.toString());
|
int intValue1 = Integer.parseInt(temp1.toString());
|
||||||
int intValue2 = Integer.parseInt(temp2.toString());
|
int intValue2 = Integer.parseInt(temp2.toString());
|
||||||
|
|
||||||
int sumval = ( intValue1 + intValue2 + carry) % 1000;
|
int sumval = (intValue1 + intValue2 + carry) % 1000;
|
||||||
carry = (intValue1 + intValue2 + carry) / 1000;
|
carry = (intValue1 + intValue2 + carry) / 1000;
|
||||||
|
|
||||||
result.setCharAt(i + 2, (char)((sumval % 10) + '0'));
|
result.setCharAt(i + 2, (char) ((sumval % 10) + '0'));
|
||||||
result.setCharAt(i + 1, (char)(((sumval / 10) % 10) + '0'));
|
result.setCharAt(i + 1, (char) (((sumval / 10) % 10) + '0'));
|
||||||
result.setCharAt(i, (char) (( sumval / 100) + '0'));
|
result.setCharAt(i, (char) ((sumval / 100) + '0'));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2007 ZXing authors
|
* Copyright 2009 ZXing authors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.google.zxing.pdf417.decoder;
|
package com.google.zxing.pdf417.decoder;
|
||||||
|
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
|
@ -27,7 +28,7 @@ import com.google.zxing.common.DecoderResult;
|
||||||
* @author SITA Lab (kevin.osullivan@sita.aero)
|
* @author SITA Lab (kevin.osullivan@sita.aero)
|
||||||
*/
|
*/
|
||||||
public final class Decoder {
|
public final class Decoder {
|
||||||
public static final boolean debug = false;
|
|
||||||
private static final int MAX_ERRORS = 3;
|
private static final int MAX_ERRORS = 3;
|
||||||
private static final int MAX_EC_CODEWORDS = 512;
|
private static final int MAX_EC_CODEWORDS = 512;
|
||||||
//private final ReedSolomonDecoder rsDecoder;
|
//private final ReedSolomonDecoder rsDecoder;
|
||||||
|
@ -68,70 +69,48 @@ public final class Decoder {
|
||||||
*/
|
*/
|
||||||
public DecoderResult decode(BitMatrix bits) throws ReaderException {
|
public DecoderResult decode(BitMatrix bits) throws ReaderException {
|
||||||
// Construct a parser to read the data codewords and error-correction level
|
// Construct a parser to read the data codewords and error-correction level
|
||||||
long t2;
|
|
||||||
long t1 = System.currentTimeMillis();
|
|
||||||
BitMatrixParser parser = new BitMatrixParser(bits);
|
BitMatrixParser parser = new BitMatrixParser(bits);
|
||||||
int[] codewords = parser.readCodewords();
|
int[] codewords = parser.readCodewords();
|
||||||
if (codewords == null || codewords.length == 0) {
|
if (codewords == null || codewords.length == 0) {
|
||||||
if (debug) System.out.println("No codewords read");
|
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
if (debug) {
|
|
||||||
t2 = System.currentTimeMillis();
|
|
||||||
System.out.println("Elapsed time in ms - BitMatrixParser " +(t2-t1));
|
|
||||||
}
|
|
||||||
|
|
||||||
int ecLevel = parser.getECLevel();
|
int ecLevel = parser.getECLevel();
|
||||||
int numECCodewords = 1 << (ecLevel+1);
|
int numECCodewords = 1 << (ecLevel + 1);
|
||||||
int erasures[] = parser.getErasures();
|
int[] erasures = parser.getErasures();
|
||||||
|
|
||||||
t1 = System.currentTimeMillis();
|
|
||||||
correctErrors(codewords, erasures, numECCodewords);
|
correctErrors(codewords, erasures, numECCodewords);
|
||||||
if (debug) {
|
|
||||||
t2 = System.currentTimeMillis();
|
|
||||||
System.out.println("Elapsed time in ms - Reed Solomon " +(t2-t1));
|
|
||||||
}
|
|
||||||
verifyCodewordCount(codewords, numECCodewords);
|
verifyCodewordCount(codewords, numECCodewords);
|
||||||
|
|
||||||
t1 = System.currentTimeMillis();
|
|
||||||
DecoderResult dr = DecodedBitStreamParser.decode(codewords);
|
|
||||||
if (debug) {
|
|
||||||
t2 = System.currentTimeMillis();
|
|
||||||
System.out.println("Elapsed time in ms - DecodeBitStreamParser " +(t2-t1));
|
|
||||||
}
|
|
||||||
// Decode the codewords
|
// Decode the codewords
|
||||||
return dr;
|
return DecodedBitStreamParser.decode(codewords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that all is OK with the codeword array.
|
* Verify that all is OK with the codeword array.
|
||||||
|
*
|
||||||
* @param codewords
|
* @param codewords
|
||||||
* @return an index to the first data codeword.
|
* @return an index to the first data codeword.
|
||||||
* @throws ReaderException
|
* @throws ReaderException
|
||||||
*/
|
*/
|
||||||
private int verifyCodewordCount(int codewords[], int numECCodewords) throws ReaderException {
|
private static int verifyCodewordCount(int[] codewords, int numECCodewords) throws ReaderException {
|
||||||
int numberOfCodewords = 0;
|
|
||||||
if (codewords.length < 4) {
|
if (codewords.length < 4) {
|
||||||
// Codeword array size should be at least 4 allowing for
|
// Codeword array size should be at least 4 allowing for
|
||||||
// Count CW, At least one Data CW, Error Correction CW, Error Correction CW
|
// Count CW, At least one Data CW, Error Correction CW, Error Correction CW
|
||||||
if (debug) System.out.println("Not enough codewords " + codewords.length);
|
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
// The first codeword, the Symbol Length Descriptor, shall always encode the total number of data
|
// The first codeword, the Symbol Length Descriptor, shall always encode the total number of data
|
||||||
// codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad
|
// codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad
|
||||||
// codewords, but excluding the number of error correction codewords.
|
// codewords, but excluding the number of error correction codewords.
|
||||||
numberOfCodewords = codewords[0];
|
int numberOfCodewords = codewords[0];
|
||||||
if (numberOfCodewords > codewords.length) {
|
if (numberOfCodewords > codewords.length) {
|
||||||
if (debug) System.out.println("Invalid number of codewords[0]=" + numberOfCodewords + " codewords.length=" + codewords.length);
|
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
if (numberOfCodewords == 0) {
|
if (numberOfCodewords == 0) {
|
||||||
// Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)
|
// Reset to the length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords)
|
||||||
if (numECCodewords < codewords.length) {
|
if (numECCodewords < codewords.length) {
|
||||||
codewords[0] = codewords.length - numECCodewords;
|
codewords[0] = codewords.length - numECCodewords;
|
||||||
if (debug) System.out.println("Codewords[0] is zero, resetting to " +(codewords[0]));
|
|
||||||
} else {
|
} else {
|
||||||
if (debug) System.out.println("Codewords[0] is zero, no data codewords");
|
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,25 +121,21 @@ public final class Decoder {
|
||||||
* <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to
|
* <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to
|
||||||
* correct the errors in-place using Reed-Solomon error correction.</p>
|
* correct the errors in-place using Reed-Solomon error correction.</p>
|
||||||
*
|
*
|
||||||
* @param codewordBytes data and error correction codewords
|
* @param codewords data and error correction codewords
|
||||||
* @param numDataCodewords number of codewords that are data bytes
|
|
||||||
* @throws ReaderException if error correction fails
|
* @throws ReaderException if error correction fails
|
||||||
*/
|
*/
|
||||||
private int correctErrors(int[] codewords, int[] erasures, int numECCodewords) throws ReaderException {
|
private static int correctErrors(int[] codewords, int[] erasures, int numECCodewords) throws ReaderException {
|
||||||
if ((erasures != null && erasures.length > numECCodewords/2 + MAX_ERRORS) ||
|
if ((erasures != null && erasures.length > numECCodewords / 2 + MAX_ERRORS) ||
|
||||||
(numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS)) {
|
(numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS)) {
|
||||||
// Too many errors or EC Codewords is corrupted
|
// Too many errors or EC Codewords is corrupted
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
// Try to correct the errors
|
// Try to correct the errors
|
||||||
int result = 0; // rsDecoder.correctErrors(codewords, numECCodewords);
|
int result = 0; // rsDecoder.correctErrors(codewords, numECCodewords);
|
||||||
if (debug) {
|
|
||||||
System.out.println("Corrected errors: " + result);
|
|
||||||
}
|
|
||||||
if (erasures != null) {
|
if (erasures != null) {
|
||||||
int numErasures = erasures.length;
|
int numErasures = erasures.length;
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
numErasures = numErasures - result;
|
numErasures -= result;
|
||||||
}
|
}
|
||||||
if (numErasures > MAX_ERRORS) {
|
if (numErasures > MAX_ERRORS) {
|
||||||
// Still too many errors
|
// Still too many errors
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2007 ZXing authors
|
* Copyright 2009 ZXing authors
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package com.google.zxing.pdf417.detector;
|
package com.google.zxing.pdf417.detector;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
|
||||||
|
|
||||||
import com.google.zxing.BlackPointEstimationMethod;
|
import com.google.zxing.BlackPointEstimationMethod;
|
||||||
import com.google.zxing.MonochromeBitmapSource;
|
import com.google.zxing.MonochromeBitmapSource;
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
|
@ -27,6 +25,8 @@ import com.google.zxing.common.BitMatrix;
|
||||||
import com.google.zxing.common.DetectorResult;
|
import com.google.zxing.common.DetectorResult;
|
||||||
import com.google.zxing.common.GridSampler;
|
import com.google.zxing.common.GridSampler;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Encapsulates logic that can detect a PDF417 Code in an image, even if the
|
* Encapsulates logic that can detect a PDF417 Code in an image, even if the
|
||||||
|
@ -36,19 +36,19 @@ import com.google.zxing.common.GridSampler;
|
||||||
* @author SITA Lab (kevin.osullivan@sita.aero)
|
* @author SITA Lab (kevin.osullivan@sita.aero)
|
||||||
*/
|
*/
|
||||||
public final class Detector {
|
public final class Detector {
|
||||||
public static final boolean debug = false;
|
|
||||||
public static final int MAX_AVG_VARIANCE = (int) ((1 << 8) * 0.42f);
|
public static final int MAX_AVG_VARIANCE = (int) ((1 << 8) * 0.42f);
|
||||||
public static final int MAX_INDIVIDUAL_VARIANCE = (int) ((1 << 8) * 0.8f);
|
public static final int MAX_INDIVIDUAL_VARIANCE = (int) ((1 << 8) * 0.8f);
|
||||||
// B S B S B S B S Bar/Space pattern
|
// B S B S B S B S Bar/Space pattern
|
||||||
private static final int[] START_PATTERN = { 8, 1, 1, 1, 1, 1, 1, 3 }; // 11111111
|
private static final int[] START_PATTERN = {8, 1, 1, 1, 1, 1, 1, 3}; // 11111111
|
||||||
// 0 1
|
// 0 1
|
||||||
// 0 1
|
// 0 1
|
||||||
// 0 1
|
// 0 1
|
||||||
// 000
|
// 000
|
||||||
|
|
||||||
// B S B S B S B S B Bar/Space pattern
|
// B S B S B S B S B Bar/Space pattern
|
||||||
private static final int[] STOP_PATTERN_REVERSE = { 1, 2, 1, 1, 1, 3, 1, 1,
|
private static final int[] STOP_PATTERN_REVERSE = {1, 2, 1, 1, 1, 3, 1, 1,
|
||||||
7 }; // 1111111 0 1 000 1 0 1 00 1
|
7}; // 1111111 0 1 000 1 0 1 00 1
|
||||||
|
|
||||||
private final MonochromeBitmapSource image;
|
private final MonochromeBitmapSource image;
|
||||||
|
|
||||||
|
@ -63,8 +63,7 @@ public final class Detector {
|
||||||
*
|
*
|
||||||
* @return {@link DetectorResult} encapsulating results of detecting a PDF417
|
* @return {@link DetectorResult} encapsulating results of detecting a PDF417
|
||||||
* Code
|
* Code
|
||||||
* @throws ReaderException
|
* @throws ReaderException if no QR Code can be found
|
||||||
* if no QR Code can be found
|
|
||||||
*/
|
*/
|
||||||
public DetectorResult detect() throws ReaderException {
|
public DetectorResult detect() throws ReaderException {
|
||||||
return detect(null);
|
return detect(null);
|
||||||
|
@ -75,27 +74,17 @@ public final class Detector {
|
||||||
* Detects a PDF417 Code in an image, simply.
|
* Detects a PDF417 Code in an image, simply.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param hints
|
* @param hints optional hints to detector
|
||||||
* optional hints to detector
|
|
||||||
* @return {@link DetectorResult} encapsulating results of detecting a PDF417
|
* @return {@link DetectorResult} encapsulating results of detecting a PDF417
|
||||||
* Code
|
* Code
|
||||||
* @throws ReaderException
|
* @throws ReaderException if no PDF417 Code can be found
|
||||||
* if no PDF417 Code can be found
|
|
||||||
*/
|
*/
|
||||||
public DetectorResult detect(Hashtable hints) throws ReaderException {
|
public DetectorResult detect(Hashtable hints) throws ReaderException {
|
||||||
if (!BlackPointEstimationMethod.TWO_D_SAMPLING.equals(image
|
if (!BlackPointEstimationMethod.TWO_D_SAMPLING.equals(image
|
||||||
.getLastEstimationMethod())) {
|
.getLastEstimationMethod())) {
|
||||||
image.estimateBlackPoint(BlackPointEstimationMethod.TWO_D_SAMPLING, 0);
|
image.estimateBlackPoint(BlackPointEstimationMethod.TWO_D_SAMPLING, 0);
|
||||||
}
|
}
|
||||||
int width = image.getWidth();
|
|
||||||
int height = image.getHeight();
|
|
||||||
if (debug)
|
|
||||||
System.out.println("Width= " + width);
|
|
||||||
if (debug)
|
|
||||||
System.out.println("Height= " + height);
|
|
||||||
|
|
||||||
long t2;
|
|
||||||
long t1 = System.currentTimeMillis();
|
|
||||||
ResultPoint[] vertices = findVertices(image);
|
ResultPoint[] vertices = findVertices(image);
|
||||||
if (vertices == null) { // Couldn't find the vertices
|
if (vertices == null) { // Couldn't find the vertices
|
||||||
// Maybe the image is rotated 180 degrees?
|
// Maybe the image is rotated 180 degrees?
|
||||||
|
@ -110,43 +99,21 @@ public final class Detector {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if (vertices != null) {
|
if (vertices != null) {
|
||||||
if (debug) {
|
|
||||||
t2 = System.currentTimeMillis();
|
|
||||||
System.out.println("Elapsed time in ms - Find Vertices "
|
|
||||||
+ (t2 - t1));
|
|
||||||
}
|
|
||||||
|
|
||||||
float moduleWidth = computeModuleWidth(vertices);
|
float moduleWidth = computeModuleWidth(vertices);
|
||||||
if (moduleWidth < 1.0f) {
|
if (moduleWidth < 1.0f) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Module Size is less than 1.0f="
|
|
||||||
+ moduleWidth);
|
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
if (debug)
|
|
||||||
System.out.println("Module Size=" + moduleWidth);
|
|
||||||
|
|
||||||
int dimension = computeDimension(vertices[4], vertices[6],
|
int dimension = computeDimension(vertices[4], vertices[6],
|
||||||
vertices[5], vertices[7], moduleWidth);
|
vertices[5], vertices[7], moduleWidth);
|
||||||
if (debug)
|
|
||||||
System.out.println("Dimension=" + dimension);
|
|
||||||
|
|
||||||
// Deskew and sample image
|
// Deskew and sample image
|
||||||
t1 = System.currentTimeMillis();
|
|
||||||
BitMatrix bits = sampleGrid(image, vertices[4], vertices[5],
|
BitMatrix bits = sampleGrid(image, vertices[4], vertices[5],
|
||||||
vertices[6], vertices[7], dimension);
|
vertices[6], vertices[7], dimension);
|
||||||
//bits.setModuleWidth(moduleWidth);
|
//bits.setModuleWidth(moduleWidth);
|
||||||
if (debug) {
|
return new DetectorResult(bits, new ResultPoint[]{vertices[4],
|
||||||
t2 = System.currentTimeMillis();
|
vertices[5], vertices[6], vertices[7]});
|
||||||
System.out
|
|
||||||
.println("Elapsed time in ms - Sampled Grid " + (t2 - t1));
|
|
||||||
}
|
|
||||||
return new DetectorResult(bits, new ResultPoint[] { vertices[4],
|
|
||||||
vertices[5], vertices[6], vertices[7] });
|
|
||||||
} else {
|
} else {
|
||||||
if (debug) {
|
|
||||||
System.out.println("Unable to locate vertices");
|
|
||||||
}
|
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,8 +122,7 @@ public final class Detector {
|
||||||
* Locate the vertices and the codewords area of a black blob using the Start
|
* Locate the vertices and the codewords area of a black blob using the Start
|
||||||
* and Stop patterns as locators.
|
* and Stop patterns as locators.
|
||||||
*
|
*
|
||||||
* @param image
|
* @param image the scanned barcode image.
|
||||||
* the scanned barcode image.
|
|
||||||
* @return the an array containing the vertices. vertices[0] x, y top left
|
* @return the an array containing the vertices. vertices[0] x, y top left
|
||||||
* barcode vertices[1] x, y bottom left barcode vertices[2] x, y top
|
* barcode vertices[1] x, y bottom left barcode vertices[2] x, y top
|
||||||
* right barcode vertices[3] x, y bottom right barcode vertices[4] x,
|
* right barcode vertices[3] x, y bottom right barcode vertices[4] x,
|
||||||
|
@ -164,7 +130,7 @@ public final class Detector {
|
||||||
* area vertices[6] x, y top right codeword area vertices[7] x, y
|
* area vertices[6] x, y top right codeword area vertices[7] x, y
|
||||||
* bottom right codeword area
|
* bottom right codeword area
|
||||||
*/
|
*/
|
||||||
private ResultPoint[] findVertices(MonochromeBitmapSource image) {
|
private static ResultPoint[] findVertices(MonochromeBitmapSource image) {
|
||||||
int height = image.getHeight();
|
int height = image.getHeight();
|
||||||
int width = image.getWidth();
|
int width = image.getWidth();
|
||||||
|
|
||||||
|
@ -178,9 +144,6 @@ public final class Detector {
|
||||||
row = image.getBlackRow(i, null, 0, width / 4);
|
row = image.getBlackRow(i, null, 0, width / 4);
|
||||||
loc = findGuardPattern(row, 0, START_PATTERN);
|
loc = findGuardPattern(row, 0, START_PATTERN);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Found START pattern at X=" + loc[0]
|
|
||||||
+ " End X=" + loc[1] + ", Y=" + i);
|
|
||||||
result[0] = new ResultPoint(loc[0], i);
|
result[0] = new ResultPoint(loc[0], i);
|
||||||
result[4] = new ResultPoint(loc[1], i);
|
result[4] = new ResultPoint(loc[1], i);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -194,9 +157,6 @@ public final class Detector {
|
||||||
row = image.getBlackRow(i, null, 0, width / 4);
|
row = image.getBlackRow(i, null, 0, width / 4);
|
||||||
loc = findGuardPattern(row, 0, START_PATTERN);
|
loc = findGuardPattern(row, 0, START_PATTERN);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Found START pattern at X=" + loc[0]
|
|
||||||
+ " End X=" + loc[1] + ", Y=" + i);
|
|
||||||
result[1] = new ResultPoint(loc[0], i);
|
result[1] = new ResultPoint(loc[0], i);
|
||||||
result[5] = new ResultPoint(loc[1], i);
|
result[5] = new ResultPoint(loc[1], i);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -212,10 +172,6 @@ public final class Detector {
|
||||||
row.reverse();
|
row.reverse();
|
||||||
loc = findGuardPattern(row, 0, STOP_PATTERN_REVERSE);
|
loc = findGuardPattern(row, 0, STOP_PATTERN_REVERSE);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Found STOP pattern at X="
|
|
||||||
+ (width - loc[0]) + " End X=" + (width - loc[1])
|
|
||||||
+ ", Y=" + i);
|
|
||||||
result[2] = new ResultPoint(width - loc[0], i);
|
result[2] = new ResultPoint(width - loc[0], i);
|
||||||
result[6] = new ResultPoint(width - loc[1], i);
|
result[6] = new ResultPoint(width - loc[1], i);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -231,10 +187,6 @@ public final class Detector {
|
||||||
row.reverse();
|
row.reverse();
|
||||||
loc = findGuardPattern(row, 0, STOP_PATTERN_REVERSE);
|
loc = findGuardPattern(row, 0, STOP_PATTERN_REVERSE);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Found STOP pattern at X="
|
|
||||||
+ (width - loc[0]) + " End X=" + (width - loc[1])
|
|
||||||
+ ", Y=" + i);
|
|
||||||
result[3] = new ResultPoint(width - loc[0], i);
|
result[3] = new ResultPoint(width - loc[0], i);
|
||||||
result[7] = new ResultPoint(width - loc[1], i);
|
result[7] = new ResultPoint(width - loc[1], i);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -242,11 +194,7 @@ public final class Detector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found) {
|
return found ? result : null;
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -255,8 +203,7 @@ public final class Detector {
|
||||||
* degrees and if it locates the start and stop patterns at it will re-map
|
* degrees and if it locates the start and stop patterns at it will re-map
|
||||||
* the vertices for a 0 degree rotation.
|
* the vertices for a 0 degree rotation.
|
||||||
*
|
*
|
||||||
* @param image
|
* @param image the scanned barcode image.
|
||||||
* the scanned barcode image.
|
|
||||||
* @return the an array containing the vertices. vertices[0] x, y top left
|
* @return the an array containing the vertices. vertices[0] x, y top left
|
||||||
* barcode vertices[1] x, y bottom left barcode vertices[2] x, y top
|
* barcode vertices[1] x, y bottom left barcode vertices[2] x, y top
|
||||||
* right barcode vertices[3] x, y bottom right barcode vertices[4] x,
|
* right barcode vertices[3] x, y bottom right barcode vertices[4] x,
|
||||||
|
@ -264,7 +211,7 @@ public final class Detector {
|
||||||
* area vertices[6] x, y top right codeword area vertices[7] x, y
|
* area vertices[6] x, y top right codeword area vertices[7] x, y
|
||||||
* bottom right codeword area
|
* bottom right codeword area
|
||||||
*/
|
*/
|
||||||
private ResultPoint[] findVertices180(MonochromeBitmapSource image) {
|
private static ResultPoint[] findVertices180(MonochromeBitmapSource image) {
|
||||||
int height = image.getHeight();
|
int height = image.getHeight();
|
||||||
int width = image.getWidth();
|
int width = image.getWidth();
|
||||||
|
|
||||||
|
@ -279,10 +226,6 @@ public final class Detector {
|
||||||
row.reverse();
|
row.reverse();
|
||||||
loc = findGuardPattern(row, 0, START_PATTERN);
|
loc = findGuardPattern(row, 0, START_PATTERN);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Found START pattern at X="
|
|
||||||
+ (width - loc[0]) + " End X=" + (width - loc[1]) + ", Y="
|
|
||||||
+ i);
|
|
||||||
result[0] = new ResultPoint(width - loc[0], i);
|
result[0] = new ResultPoint(width - loc[0], i);
|
||||||
result[4] = new ResultPoint(width - loc[1], i);
|
result[4] = new ResultPoint(width - loc[1], i);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -297,10 +240,6 @@ public final class Detector {
|
||||||
row.reverse();
|
row.reverse();
|
||||||
loc = findGuardPattern(row, 0, START_PATTERN);
|
loc = findGuardPattern(row, 0, START_PATTERN);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Found START pattern at X="
|
|
||||||
+ (width - loc[0]) + " End X=" + (width - loc[1])
|
|
||||||
+ ", Y=" + i);
|
|
||||||
result[1] = new ResultPoint(width - loc[0], i);
|
result[1] = new ResultPoint(width - loc[0], i);
|
||||||
result[5] = new ResultPoint(width - loc[1], i);
|
result[5] = new ResultPoint(width - loc[1], i);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -315,9 +254,6 @@ public final class Detector {
|
||||||
row = image.getBlackRow(i, null, (width * 3) / 4, width / 4);
|
row = image.getBlackRow(i, null, (width * 3) / 4, width / 4);
|
||||||
loc = findGuardPattern(row, 0, STOP_PATTERN_REVERSE);
|
loc = findGuardPattern(row, 0, STOP_PATTERN_REVERSE);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Found STOP pattern at X=" + loc[0]
|
|
||||||
+ " End X=" + loc[1] + ", Y=" + i);
|
|
||||||
result[2] = new ResultPoint(loc[0], i);
|
result[2] = new ResultPoint(loc[0], i);
|
||||||
result[6] = new ResultPoint(loc[1], i);
|
result[6] = new ResultPoint(loc[1], i);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -332,9 +268,6 @@ public final class Detector {
|
||||||
row = image.getBlackRow(i, null, (width * 3) / 4, width / 4);
|
row = image.getBlackRow(i, null, (width * 3) / 4, width / 4);
|
||||||
loc = findGuardPattern(row, 0, STOP_PATTERN_REVERSE);
|
loc = findGuardPattern(row, 0, STOP_PATTERN_REVERSE);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
if (debug)
|
|
||||||
System.out.println("Found STOP pattern at X=" + loc[0]
|
|
||||||
+ " End X=" + loc[1] + ", Y=" + i);
|
|
||||||
result[3] = new ResultPoint(loc[0], i);
|
result[3] = new ResultPoint(loc[0], i);
|
||||||
result[7] = new ResultPoint(loc[1], i);
|
result[7] = new ResultPoint(loc[1], i);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -352,19 +285,16 @@ public final class Detector {
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Estimates module size (pixels in a module) based on the Start and End
|
* Estimates module size (pixels in a module) based on the Start and End
|
||||||
* finder patterns -- it uses
|
* finder patterns.</p>
|
||||||
* {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)} to figure the width
|
|
||||||
* of each.
|
|
||||||
*
|
*
|
||||||
* @param vertices
|
* @param vertices [] vertices[0] x, y top left barcode vertices[1] x, y bottom
|
||||||
* [] vertices[0] x, y top left barcode vertices[1] x, y bottom
|
|
||||||
* left barcode vertices[2] x, y top right barcode vertices[3] x, y
|
* left barcode vertices[2] x, y top right barcode vertices[3] x, y
|
||||||
* bottom right barcode vertices[4] x, y top left Codeword area
|
* bottom right barcode vertices[4] x, y top left Codeword area
|
||||||
* vertices[5] x, y bottom left Codeword area vertices[6] x, y top
|
* vertices[5] x, y bottom left Codeword area vertices[6] x, y top
|
||||||
* right Codeword area vertices[7] x, y bottom right Codeword area
|
* right Codeword area vertices[7] x, y bottom right Codeword area
|
||||||
* @return the module size.
|
* @return the module size.
|
||||||
*/
|
*/
|
||||||
private float computeModuleWidth(ResultPoint[] vertices) {
|
private static float computeModuleWidth(ResultPoint[] vertices) {
|
||||||
float pixels1 = ResultPoint.distance(vertices[0], vertices[4]);
|
float pixels1 = ResultPoint.distance(vertices[0], vertices[4]);
|
||||||
float pixels2 = ResultPoint.distance(vertices[1], vertices[5]);
|
float pixels2 = ResultPoint.distance(vertices[1], vertices[5]);
|
||||||
float moduleWidth1 = (pixels1 + pixels2) / (17 * 2.0f);
|
float moduleWidth1 = (pixels1 + pixels2) / (17 * 2.0f);
|
||||||
|
@ -375,20 +305,14 @@ public final class Detector {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* Computes the dimension (number of modules in a row) of the PDF417 Code
|
* Computes the dimension (number of modules in a row) of the PDF417 Code
|
||||||
* based on vertices of the codeword area and estimated module size.
|
* based on vertices of the codeword area and estimated module size.
|
||||||
*
|
*
|
||||||
* @param topLeft
|
* @param topLeft of codeword area
|
||||||
* of codeword area
|
* @param topRight of codeword area
|
||||||
* @param topRight
|
* @param bottomLeft of codeword area
|
||||||
* of codeword area
|
* @param bottomRight of codeword are
|
||||||
* @param bottomLeft
|
* @param moduleWidth estimated module size
|
||||||
* of codeword area
|
|
||||||
* @param bottomRight
|
|
||||||
* of codeword are
|
|
||||||
* @param moduleWidth
|
|
||||||
* estimated module size
|
|
||||||
* @return the number of modules in a row.
|
* @return the number of modules in a row.
|
||||||
*/
|
*/
|
||||||
private static int computeDimension(ResultPoint topLeft,
|
private static int computeDimension(ResultPoint topLeft,
|
||||||
|
@ -401,8 +325,7 @@ public final class Detector {
|
||||||
int bottomRowDimension = round(ResultPoint.distance(bottomLeft,
|
int bottomRowDimension = round(ResultPoint.distance(bottomLeft,
|
||||||
bottomRight)
|
bottomRight)
|
||||||
/ moduleWidth);
|
/ moduleWidth);
|
||||||
int dimension = ((((topRowDimension + bottomRowDimension) >> 1) + 8) / 17) * 17;
|
return ((((topRowDimension + bottomRowDimension) >> 1) + 8) / 17) * 17;
|
||||||
return dimension;
|
|
||||||
/*
|
/*
|
||||||
* int topRowDimension = round(ResultPoint.distance(topLeft,
|
* int topRowDimension = round(ResultPoint.distance(topLeft,
|
||||||
* topRight)); //moduleWidth); int bottomRowDimension =
|
* topRight)); //moduleWidth); int bottomRowDimension =
|
||||||
|
@ -450,17 +373,14 @@ public final class Detector {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param row
|
* @param row row of black/white values to search
|
||||||
* row of black/white values to search
|
* @param rowOffset position to start search
|
||||||
* @param rowOffset
|
* @param pattern pattern of counts of number of black and white pixels that are
|
||||||
* position to start search
|
|
||||||
* @param pattern
|
|
||||||
* pattern of counts of number of black and white pixels that are
|
|
||||||
* being searched for as a pattern
|
* being searched for as a pattern
|
||||||
* @return start/end horizontal offset of guard pattern, as an array of two
|
* @return start/end horizontal offset of guard pattern, as an array of two
|
||||||
* ints.
|
* ints.
|
||||||
*/
|
*/
|
||||||
int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern) {
|
static int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern) {
|
||||||
int patternLength = pattern.length;
|
int patternLength = pattern.length;
|
||||||
int[] counters = new int[patternLength];
|
int[] counters = new int[patternLength];
|
||||||
int width = row.getSize();
|
int width = row.getSize();
|
||||||
|
@ -470,13 +390,13 @@ public final class Detector {
|
||||||
int patternStart = rowOffset;
|
int patternStart = rowOffset;
|
||||||
for (int x = rowOffset; x < width; x++) {
|
for (int x = rowOffset; x < width; x++) {
|
||||||
boolean pixel = row.get(x);
|
boolean pixel = row.get(x);
|
||||||
if ((!pixel && isWhite) || (pixel && !isWhite)) {
|
if (pixel ^ isWhite) {
|
||||||
counters[counterPosition]++;
|
counters[counterPosition]++;
|
||||||
} else {
|
} else {
|
||||||
if (counterPosition == patternLength - 1) {
|
if (counterPosition == patternLength - 1) {
|
||||||
if (patternMatchVariance(counters, pattern,
|
if (patternMatchVariance(counters, pattern,
|
||||||
MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
|
MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
|
||||||
return new int[] { patternStart, x };
|
return new int[]{patternStart, x};
|
||||||
}
|
}
|
||||||
patternStart += counters[0] + counters[1];
|
patternStart += counters[0] + counters[1];
|
||||||
for (int y = 2; y < patternLength; y++) {
|
for (int y = 2; y < patternLength; y++) {
|
||||||
|
@ -501,12 +421,9 @@ public final class Detector {
|
||||||
* the total variance from the expected pattern proportions across all
|
* the total variance from the expected pattern proportions across all
|
||||||
* pattern elements, to the length of the pattern.
|
* pattern elements, to the length of the pattern.
|
||||||
*
|
*
|
||||||
* @param counters
|
* @param counters observed counters
|
||||||
* observed counters
|
* @param pattern expected pattern
|
||||||
* @param pattern
|
* @param maxIndividualVariance The most any counter can differ before we give up
|
||||||
* expected pattern
|
|
||||||
* @param maxIndividualVariance
|
|
||||||
* The most any counter can differ before we give up
|
|
||||||
* @return ratio of total variance between counters and pattern compared to
|
* @return ratio of total variance between counters and pattern compared to
|
||||||
* total pattern size, where the ratio has been multiplied by 256.
|
* total pattern size, where the ratio has been multiplied by 256.
|
||||||
* So, 0 means no variance (perfect match); 256 means the total
|
* So, 0 means no variance (perfect match); 256 means the total
|
||||||
|
|
|
@ -37,12 +37,12 @@ public final class PDF417BlackBox1TestCase extends AbstractBlackBoxTestCase {
|
||||||
//addTest(1, 1, 270.0f);
|
//addTest(1, 1, 270.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected Hashtable<DecodeHintType, Object> getHints() {
|
protected Hashtable<DecodeHintType, Object> getHints() {
|
||||||
Hashtable<DecodeHintType, Object> table = new Hashtable<DecodeHintType, Object>();
|
Hashtable<DecodeHintType, Object> table = new Hashtable<DecodeHintType, Object>(3);
|
||||||
Vector v = new Vector();
|
Vector<BarcodeFormat> v = new Vector<BarcodeFormat>(1);
|
||||||
v.add(BarcodeFormat.PDF417);
|
v.add(BarcodeFormat.PDF417);
|
||||||
table.put(DecodeHintType.POSSIBLE_FORMATS, v);
|
table.put(DecodeHintType.POSSIBLE_FORMATS, v);
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue