diff --git a/AUTHORS b/AUTHORS
index 99e5207b9..3ac399a3a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -19,6 +19,7 @@ David Phillip Oster (Google)
David Albert (Bug Labs)
David Olivier
Diego Pierotto
+drejc83
Eduardo Castillejo (University of Deusto)
Eric Kobrin (Velocitude)
Erik Barbara
diff --git a/javase/src/com/google/zxing/client/j2se/CommandLineRunner.java b/javase/src/com/google/zxing/client/j2se/CommandLineRunner.java
index 55d373962..e47f5d3f1 100644
--- a/javase/src/com/google/zxing/client/j2se/CommandLineRunner.java
+++ b/javase/src/com/google/zxing/client/j2se/CommandLineRunner.java
@@ -16,20 +16,7 @@
package com.google.zxing.client.j2se;
-import com.google.zxing.BarcodeFormat;
-import com.google.zxing.BinaryBitmap;
-import com.google.zxing.DecodeHintType;
-import com.google.zxing.LuminanceSource;
-import com.google.zxing.MultiFormatReader;
-import com.google.zxing.NotFoundException;
-import com.google.zxing.Result;
-import com.google.zxing.client.result.ParsedResult;
-import com.google.zxing.client.result.ResultParser;
-import com.google.zxing.common.BitArray;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.common.HybridBinarizer;
-import com.google.zxing.ResultPoint;
-
+import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
@@ -44,13 +31,25 @@ import java.nio.charset.Charset;
import java.util.Hashtable;
import java.util.Vector;
-import javax.imageio.ImageIO;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.LuminanceSource;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.NotFoundException;
+import com.google.zxing.Result;
+import com.google.zxing.ResultPoint;
+import com.google.zxing.client.result.ParsedResult;
+import com.google.zxing.client.result.ResultParser;
+import com.google.zxing.common.BitArray;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.multi.GenericMultipleBarcodeReader;
/**
- *
This simple command line utility decodes files, directories of files, or URIs which are passed
- * as arguments. By default it uses the normal decoding algorithms, but you can pass --try_harder to
- * request that hint. The raw text of each barcode is printed, and when running against directories,
- * summary statistics are also displayed.
+ * This simple command line utility decodes files, directories of files, or URIs which are passed as arguments. By
+ * default it uses the normal decoding algorithms, but you can pass --try_harder to request that hint. The raw text of
+ * each barcode is printed, and when running against directories, summary statistics are also displayed.
*
* @author Sean Owen
* @author dswitkin@google.com (Daniel Switkin)
@@ -71,6 +70,7 @@ public final class CommandLineRunner {
boolean productsOnly = false;
boolean dumpResults = false;
boolean dumpBlackPoint = false;
+ boolean multi = false;
int[] crop = null;
for (String arg : args) {
if ("--try_harder".equals(arg)) {
@@ -83,6 +83,8 @@ public final class CommandLineRunner {
dumpResults = true;
} else if ("--dump_black_point".equals(arg)) {
dumpBlackPoint = true;
+ } else if ("--multi".equals(arg)) {
+ multi = true;
} else if (arg.startsWith("--crop")) {
crop = new int[4];
String[] tokens = arg.substring(7).split(",");
@@ -99,7 +101,7 @@ public final class CommandLineRunner {
Hashtable hints = buildHints(tryHarder, pureBarcode, productsOnly);
for (String arg : args) {
if (!arg.startsWith("--")) {
- decodeOneArgument(arg, hints, dumpResults, dumpBlackPoint, crop);
+ decodeOneArgument(arg, hints, dumpResults, dumpBlackPoint, crop, multi);
}
}
}
@@ -145,14 +147,15 @@ public final class CommandLineRunner {
System.err.println(" --dump_results: Write the decoded contents to input.txt");
System.err.println(" --dump_black_point: Compare black point algorithms as input.mono.png");
System.err.println(" --crop=left,top,width,height: Only examine cropped region of input image(s)");
+ System.err.println(" --multi: Scans image for multiple barcodes");
}
private static void decodeOneArgument(String argument,
Hashtable hints,
boolean dumpResults,
boolean dumpBlackPoint,
- int[] crop) throws IOException,
- URISyntaxException {
+ int[] crop,
+ boolean multi) throws IOException, URISyntaxException {
File inputFile = new File(argument);
if (inputFile.exists()) {
@@ -169,21 +172,38 @@ public final class CommandLineRunner {
if (filename.contains(".mono.png")) {
continue;
}
- Result result = decode(input.toURI(), hints, dumpBlackPoint, crop);
- if (result != null) {
- successful++;
- if (dumpResults) {
- dumpResult(input, result);
+ if (multi) {
+ Result[] results = decodeMulti(input.toURI(), hints, dumpBlackPoint, crop);
+ if (results != null) {
+ successful++;
+ if (dumpResults) {
+ dumpResultMulti(input, results);
+ }
+ }
+ } else {
+ Result result = decode(input.toURI(), hints, dumpBlackPoint, crop);
+ if (result != null) {
+ successful++;
+ if (dumpResults) {
+ dumpResult(input, result);
+ }
}
}
total++;
}
System.out.println("\nDecoded " + successful + " files out of " + total +
- " successfully (" + (successful * 100 / total) + "%)\n");
+ " successfully (" + (successful * 100 / total) + "%)\n");
} else {
- Result result = decode(inputFile.toURI(), hints, dumpBlackPoint, crop);
- if (dumpResults) {
- dumpResult(inputFile, result);
+ if (multi) {
+ Result[] results = decodeMulti(inputFile.toURI(), hints, dumpBlackPoint, crop);
+ if (dumpResults) {
+ dumpResultMulti(inputFile, results);
+ }
+ } else {
+ Result result = decode(inputFile.toURI(), hints, dumpBlackPoint, crop);
+ if (dumpResults) {
+ dumpResult(inputFile, result);
+ }
}
}
} else {
@@ -201,6 +221,16 @@ public final class CommandLineRunner {
writeStringToFile(result.getText(), dump);
}
+ private static void dumpResultMulti(File input, Result[] results) throws IOException {
+ String name = input.getAbsolutePath();
+ int pos = name.lastIndexOf('.');
+ if (pos > 0) {
+ name = name.substring(0, pos);
+ }
+ File dump = new File(name + ".txt");
+ writeResultsToFile(results, dump);
+ }
+
private static void writeStringToFile(String value, File file) throws IOException {
Writer out = new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF8"));
try {
@@ -210,6 +240,19 @@ public final class CommandLineRunner {
}
}
+ private static void writeResultsToFile(Result[] results, File file) throws IOException {
+ String newline = System.getProperty("line.separator");
+ Writer out = new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF8"));
+ try {
+ for (Result result : results) {
+ out.write(result.getText());
+ out.write(newline);
+ }
+ } finally {
+ out.close();
+ }
+ }
+
private static Result decode(URI uri,
Hashtable hints,
boolean dumpBlackPoint,
@@ -238,26 +281,78 @@ public final class CommandLineRunner {
Result result = new MultiFormatReader().decode(bitmap, hints);
ParsedResult parsedResult = ResultParser.parseResult(result);
System.out.println(uri.toString() + " (format: " + result.getBarcodeFormat() +
- ", type: " + parsedResult.getType() + "):\nRaw result:\n" + result.getText() +
- "\nParsed result:\n" + parsedResult.getDisplayResult());
+ ", type: " + parsedResult.getType() + "):\nRaw result:\n" + result.getText() +
+ "\nParsed result:\n" + parsedResult.getDisplayResult());
System.out.println("Also, there were " + result.getResultPoints().length + " result points.");
for (int i = 0; i < result.getResultPoints().length; i++) {
ResultPoint rp = result.getResultPoints()[i];
- System.out.println(" Point " + i + ": (" + rp.getX() + "," + rp.getY() + ")");
+ System.out.println(" Point " + i + ": (" + rp.getX() + ',' + rp.getY() + ')');
}
return result;
} catch (NotFoundException nfe) {
System.out.println(uri.toString() + ": No barcode found");
return null;
- // } finally {
+ // } finally {
// Uncomment these lines when turning on exception tracking in ReaderException.
//System.out.println("Threw " + ReaderException.getExceptionCountAndReset() + " exceptions");
//System.out.println("Throwers:\n" + ReaderException.getThrowersAndReset());
}
}
+ private static Result[] decodeMulti(URI uri,
+ Hashtable hints,
+ boolean dumpBlackPoint,
+ int[] crop) throws IOException {
+ BufferedImage image;
+ try {
+ image = ImageIO.read(uri.toURL());
+ } catch (IllegalArgumentException iae) {
+ throw new FileNotFoundException("Resource not found: " + uri);
+ }
+ if (image == null) {
+ System.err.println(uri.toString() + ": Could not load image");
+ return null;
+ }
+ try {
+ LuminanceSource source;
+ if (crop == null) {
+ source = new BufferedImageLuminanceSource(image);
+ } else {
+ source = new BufferedImageLuminanceSource(image, crop[0],
+ crop[1], crop[2], crop[3]);
+ }
+ BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+ if (dumpBlackPoint) {
+ dumpBlackPoint(uri, image, bitmap);
+ }
+
+ MultiFormatReader multiFormatReader = new MultiFormatReader();
+ GenericMultipleBarcodeReader reader = new GenericMultipleBarcodeReader(
+ multiFormatReader);
+ Result[] results = reader.decodeMultiple(bitmap, hints);
+
+ for (Result result : results) {
+ ParsedResult parsedResult = ResultParser.parseResult(result);
+ System.out.println(uri.toString() + " (format: "
+ + result.getBarcodeFormat() + ", type: "
+ + parsedResult.getType() + "):\nRaw result:\n"
+ + result.getText() + "\nParsed result:\n"
+ + parsedResult.getDisplayResult());
+ System.out.println("Also, there were " + result.getResultPoints().length + " result points.");
+ for (int i = 0; i < result.getResultPoints().length; i++) {
+ ResultPoint rp = result.getResultPoints()[i];
+ System.out.println(" Point " + i + ": (" + rp.getX() + ',' + rp.getY() + ')');
+ }
+ }
+ return results;
+ } catch (NotFoundException nfe) {
+ System.out.println(uri.toString() + ": No barcode found");
+ return null;
+ }
+ }
+
// Writes out a single PNG which is three times the width of the input image, containing from left
// to right: the original image, the row sampling monochrome version, and the 2D sampling
// monochrome version.