mirror of
https://github.com/zxing/zxing.git
synced 2024-11-09 20:44:03 -08:00
Use JCommander for CommandLineRunner args
This commit is contained in:
parent
106fd2fc0e
commit
8fe986a9aa
6
NOTICE
6
NOTICE
|
@ -9,3 +9,9 @@ Copyright 2005-2006 Dietmar Bürkle
|
||||||
Portions of this software were contributed under section 5 of the
|
Portions of this software were contributed under section 5 of the
|
||||||
Apache License. Contributors are listed under:
|
Apache License. Contributors are listed under:
|
||||||
http://barcode4j.sourceforge.net/contributors.html
|
http://barcode4j.sourceforge.net/contributors.html
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
NOTICES FOR JCOMMANDER
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright 2010 Cedric Beust cedric@beust.com
|
||||||
|
|
|
@ -26,6 +26,11 @@
|
||||||
<groupId>com.google.zxing</groupId>
|
<groupId>com.google.zxing</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.beust</groupId>
|
||||||
|
<artifactId>jcommander</artifactId>
|
||||||
|
<version>1.48</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
|
|
|
@ -16,25 +16,22 @@
|
||||||
|
|
||||||
package com.google.zxing.client.j2se;
|
package com.google.zxing.client.j2se;
|
||||||
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.beust.jcommander.JCommander;
|
||||||
import com.google.zxing.DecodeHintType;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.nio.file.DirectoryStream;
|
import java.nio.file.DirectoryStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.EnumMap;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This simple command line utility decodes files, directories of files, or URIs which are passed
|
* This simple command line utility decodes files, directories of files, or URIs which are passed
|
||||||
|
@ -47,188 +44,109 @@ import java.util.regex.Pattern;
|
||||||
*/
|
*/
|
||||||
public final class CommandLineRunner {
|
public final class CommandLineRunner {
|
||||||
|
|
||||||
private static final Pattern COMMA = Pattern.compile(",");
|
|
||||||
|
|
||||||
private CommandLineRunner() {
|
private CommandLineRunner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
if (args.length == 0) {
|
DecoderConfig config = new DecoderConfig();
|
||||||
printUsage();
|
JCommander jCommander = new JCommander(config, args);
|
||||||
|
jCommander.setProgramName(CommandLineRunner.class.getSimpleName());
|
||||||
|
if (config.help) {
|
||||||
|
jCommander.usage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config config = new Config();
|
List<URI> inputs = config.inputPaths;
|
||||||
Queue<URI> inputs = new ConcurrentLinkedQueue<>();
|
do {
|
||||||
|
inputs = retainValid(expand(inputs), config.recursive);
|
||||||
for (String arg : args) {
|
} while (config.recursive && isExpandable(inputs));
|
||||||
String[] argValue = arg.split("=");
|
|
||||||
switch (argValue[0]) {
|
|
||||||
case "--try_harder":
|
|
||||||
config.setTryHarder(true);
|
|
||||||
break;
|
|
||||||
case "--pure_barcode":
|
|
||||||
config.setPureBarcode(true);
|
|
||||||
break;
|
|
||||||
case "--products_only":
|
|
||||||
config.setProductsOnly(true);
|
|
||||||
break;
|
|
||||||
case "--dump_results":
|
|
||||||
config.setDumpResults(true);
|
|
||||||
break;
|
|
||||||
case "--dump_black_point":
|
|
||||||
config.setDumpBlackPoint(true);
|
|
||||||
break;
|
|
||||||
case "--multi":
|
|
||||||
config.setMulti(true);
|
|
||||||
break;
|
|
||||||
case "--brief":
|
|
||||||
config.setBrief(true);
|
|
||||||
break;
|
|
||||||
case "--recursive":
|
|
||||||
config.setRecursive(true);
|
|
||||||
break;
|
|
||||||
case "--crop":
|
|
||||||
int[] crop = new int[4];
|
|
||||||
String[] tokens = COMMA.split(argValue[1]);
|
|
||||||
for (int i = 0; i < crop.length; i++) {
|
|
||||||
crop[i] = Integer.parseInt(tokens[i]);
|
|
||||||
}
|
|
||||||
config.setCrop(crop);
|
|
||||||
break;
|
|
||||||
case "--possibleFormats":
|
|
||||||
config.setPossibleFormats(COMMA.split(argValue[1]));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (arg.startsWith("-")) {
|
|
||||||
System.err.println("Unknown command line option " + arg);
|
|
||||||
printUsage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
URI argURI = URI.create(arg);
|
|
||||||
if (argURI.getScheme() == null) {
|
|
||||||
argURI = new URI("file", argURI.getSchemeSpecificPart(), argURI.getFragment());
|
|
||||||
}
|
|
||||||
addArgumentToInputs(argURI, config, inputs);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int numInputs = inputs.size();
|
int numInputs = inputs.size();
|
||||||
if (numInputs == 0) {
|
if (numInputs == 0) {
|
||||||
System.err.println("No inputs specified");
|
jCommander.usage();
|
||||||
printUsage();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
config.setHints(buildHints(config));
|
Queue<URI> syncInputs = new ConcurrentLinkedQueue<>(inputs);
|
||||||
|
|
||||||
int numThreads = Math.min(numInputs, Runtime.getRuntime().availableProcessors());
|
int numThreads = Math.min(numInputs, Runtime.getRuntime().availableProcessors());
|
||||||
int successful = 0;
|
int successful = 0;
|
||||||
if (numThreads > 1) {
|
if (numThreads > 1) {
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
||||||
Collection<Future<Integer>> futures = new ArrayList<>(numThreads);
|
Collection<Future<Integer>> futures = new ArrayList<>(numThreads);
|
||||||
for (int x = 0; x < numThreads; x++) {
|
for (int x = 0; x < numThreads; x++) {
|
||||||
futures.add(executor.submit(new DecodeWorker(config, inputs)));
|
futures.add(executor.submit(new DecodeWorker(config, syncInputs)));
|
||||||
}
|
}
|
||||||
executor.shutdown();
|
executor.shutdown();
|
||||||
for (Future<Integer> future : futures) {
|
for (Future<Integer> future : futures) {
|
||||||
successful += future.get();
|
successful += future.get();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
successful += new DecodeWorker(config, inputs).call();
|
successful += new DecodeWorker(config, syncInputs).call();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numInputs > 1) {
|
if (!config.brief && numInputs > 1) {
|
||||||
System.out.println("\nDecoded " + successful + " files out of " + numInputs +
|
System.out.println("\nDecoded " + successful + " files out of " + numInputs +
|
||||||
" successfully (" + (successful * 100 / numInputs) + "%)\n");
|
" successfully (" + (successful * 100 / numInputs) + "%)\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static List<URI> expand(List<URI> inputs) throws IOException, URISyntaxException {
|
||||||
* Build all the inputs up front into a single flat list, so the threads can atomically pull
|
List<URI> expanded = new ArrayList<>();
|
||||||
* paths/URLs off the queue.
|
for (URI input : inputs) {
|
||||||
*/
|
if (isFileOrDir(input)) {
|
||||||
private static void addArgumentToInputs(URI input, Config config, Queue<URI> inputs) throws IOException {
|
Path inputPath = Paths.get(input);
|
||||||
// Special case: a local directory
|
if (Files.isDirectory(inputPath)) {
|
||||||
if ("file".equals(input.getScheme()) && Files.isDirectory(Paths.get(input))) {
|
try (DirectoryStream<Path> childPaths = Files.newDirectoryStream(inputPath)) {
|
||||||
try (DirectoryStream<Path> childPaths = Files.newDirectoryStream(Paths.get(input))) {
|
|
||||||
for (Path childPath : childPaths) {
|
for (Path childPath : childPaths) {
|
||||||
Path realChildPath = childPath.toRealPath();
|
expanded.add(childPath.toUri());
|
||||||
// Skip hidden files and directories (e.g. svn stuff).
|
|
||||||
if (!realChildPath.getFileName().toString().startsWith(".")) {
|
|
||||||
// Recur on nested directories if requested, otherwise skip them.
|
|
||||||
if (config.isRecursive() && Files.isDirectory(realChildPath)) {
|
|
||||||
addArgumentToInputs(realChildPath.toUri(), config, inputs);
|
|
||||||
} else {
|
|
||||||
inputs.add(realChildPath.toUri());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inputs.add(input);
|
expanded.add(input);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<DecodeHintType,?> buildHints(Config config) {
|
|
||||||
Collection<BarcodeFormat> possibleFormats = new ArrayList<>();
|
|
||||||
String[] possibleFormatsNames = config.getPossibleFormats();
|
|
||||||
if (possibleFormatsNames != null && possibleFormatsNames.length > 0) {
|
|
||||||
for (String format : possibleFormatsNames) {
|
|
||||||
possibleFormats.add(BarcodeFormat.valueOf(format));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
possibleFormats.add(BarcodeFormat.UPC_A);
|
expanded.add(input);
|
||||||
possibleFormats.add(BarcodeFormat.UPC_E);
|
|
||||||
possibleFormats.add(BarcodeFormat.EAN_13);
|
|
||||||
possibleFormats.add(BarcodeFormat.EAN_8);
|
|
||||||
possibleFormats.add(BarcodeFormat.RSS_14);
|
|
||||||
possibleFormats.add(BarcodeFormat.RSS_EXPANDED);
|
|
||||||
if (!config.isProductsOnly()) {
|
|
||||||
possibleFormats.add(BarcodeFormat.CODE_39);
|
|
||||||
possibleFormats.add(BarcodeFormat.CODE_93);
|
|
||||||
possibleFormats.add(BarcodeFormat.CODE_128);
|
|
||||||
possibleFormats.add(BarcodeFormat.ITF);
|
|
||||||
possibleFormats.add(BarcodeFormat.QR_CODE);
|
|
||||||
possibleFormats.add(BarcodeFormat.DATA_MATRIX);
|
|
||||||
possibleFormats.add(BarcodeFormat.AZTEC);
|
|
||||||
possibleFormats.add(BarcodeFormat.PDF_417);
|
|
||||||
possibleFormats.add(BarcodeFormat.CODABAR);
|
|
||||||
possibleFormats.add(BarcodeFormat.MAXICODE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
|
for (int i = 0; i < expanded.size(); i++) {
|
||||||
hints.put(DecodeHintType.POSSIBLE_FORMATS, possibleFormats);
|
URI input = expanded.get(i);
|
||||||
if (config.isTryHarder()) {
|
if (input.getScheme() == null) {
|
||||||
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
|
expanded.set(i, new URI("file", input.getSchemeSpecificPart(), input.getFragment()));
|
||||||
}
|
}
|
||||||
if (config.isPureBarcode()) {
|
|
||||||
hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
|
|
||||||
}
|
}
|
||||||
return hints;
|
return expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printUsage() {
|
private static List<URI> retainValid(List<URI> inputs, boolean recursive) {
|
||||||
System.err.println("Decode barcode images using the ZXing library");
|
List<URI> retained = new ArrayList<>();
|
||||||
System.err.println();
|
for (URI input : inputs) {
|
||||||
System.err.println("usage: CommandLineRunner { file | dir | url } [ options ]");
|
boolean retain;
|
||||||
System.err.println(" --try_harder: Use the TRY_HARDER hint, default is normal (mobile) mode");
|
if (isFileOrDir(input)) {
|
||||||
System.err.println(" --pure_barcode: Input image is a pure monochrome barcode image, not a photo");
|
Path inputPath = Paths.get(input);
|
||||||
System.err.println(" --products_only: Only decode the UPC and EAN families of barcodes");
|
retain =
|
||||||
System.err.println(" --dump_results: Write the decoded contents to input.txt");
|
!inputPath.getFileName().toString().startsWith(".") &&
|
||||||
System.err.println(" --dump_black_point: Compare black point algorithms as input.mono.png");
|
(recursive || !Files.isDirectory(inputPath));
|
||||||
System.err.println(" --multi: Scans image for multiple barcodes");
|
} else {
|
||||||
System.err.println(" --brief: Only output one line per file, omitting the contents");
|
retain = true;
|
||||||
System.err.println(" --recursive: Descend into subdirectories");
|
|
||||||
System.err.println(" --crop=left,top,width,height: Only examine cropped region of input image(s)");
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append(" --possibleFormats=barcodeFormat[,barcodeFormat2...] where barcodeFormat is any of: ");
|
|
||||||
for (BarcodeFormat format : BarcodeFormat.values()) {
|
|
||||||
builder.append(format).append(',');
|
|
||||||
}
|
}
|
||||||
builder.setLength(builder.length() - 1);
|
if (retain) {
|
||||||
System.err.println(builder);
|
retained.add(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retained;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isExpandable(List<URI> inputs) {
|
||||||
|
for (URI input : inputs) {
|
||||||
|
if (isFileOrDir(input) && Files.isDirectory(Paths.get(input))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isFileOrDir(URI uri) {
|
||||||
|
return "file".equals(uri.getScheme());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2011 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.client.j2se;
|
|
||||||
|
|
||||||
import com.google.zxing.DecodeHintType;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
final class Config {
|
|
||||||
|
|
||||||
private Map<DecodeHintType,?> hints;
|
|
||||||
private boolean tryHarder;
|
|
||||||
private boolean pureBarcode;
|
|
||||||
private boolean productsOnly;
|
|
||||||
private boolean dumpResults;
|
|
||||||
private boolean dumpBlackPoint;
|
|
||||||
private boolean multi;
|
|
||||||
private boolean brief;
|
|
||||||
private boolean recursive;
|
|
||||||
private int[] crop;
|
|
||||||
private String[] possibleFormats;
|
|
||||||
|
|
||||||
Map<DecodeHintType,?> getHints() {
|
|
||||||
return hints;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHints(Map<DecodeHintType,?> hints) {
|
|
||||||
this.hints = hints;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isTryHarder() {
|
|
||||||
return tryHarder;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTryHarder(boolean tryHarder) {
|
|
||||||
this.tryHarder = tryHarder;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isPureBarcode() {
|
|
||||||
return pureBarcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPureBarcode(boolean pureBarcode) {
|
|
||||||
this.pureBarcode = pureBarcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isProductsOnly() {
|
|
||||||
return productsOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setProductsOnly(boolean productsOnly) {
|
|
||||||
this.productsOnly = productsOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isDumpResults() {
|
|
||||||
return dumpResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDumpResults(boolean dumpResults) {
|
|
||||||
this.dumpResults = dumpResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isDumpBlackPoint() {
|
|
||||||
return dumpBlackPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDumpBlackPoint(boolean dumpBlackPoint) {
|
|
||||||
this.dumpBlackPoint = dumpBlackPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isMulti() {
|
|
||||||
return multi;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMulti(boolean multi) {
|
|
||||||
this.multi = multi;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isBrief() {
|
|
||||||
return brief;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBrief(boolean brief) {
|
|
||||||
this.brief = brief;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isRecursive() {
|
|
||||||
return recursive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRecursive(boolean recursive) {
|
|
||||||
this.recursive = recursive;
|
|
||||||
}
|
|
||||||
|
|
||||||
int[] getCrop() {
|
|
||||||
return crop;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCrop(int[] crop) {
|
|
||||||
this.crop = crop;
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] getPossibleFormats() {
|
|
||||||
return possibleFormats;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPossibleFormats(String[] possibleFormats) {
|
|
||||||
this.possibleFormats = possibleFormats;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -42,6 +42,7 @@ import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
@ -57,22 +58,24 @@ final class DecodeWorker implements Callable<Integer> {
|
||||||
private static final int BLACK = 0xFF000000;
|
private static final int BLACK = 0xFF000000;
|
||||||
private static final int WHITE = 0xFFFFFFFF;
|
private static final int WHITE = 0xFFFFFFFF;
|
||||||
|
|
||||||
private final Config config;
|
private final DecoderConfig config;
|
||||||
private final Queue<URI> inputs;
|
private final Queue<URI> inputs;
|
||||||
|
private final Map<DecodeHintType,?> hints;
|
||||||
|
|
||||||
DecodeWorker(Config config, Queue<URI> inputs) {
|
DecodeWorker(DecoderConfig config, Queue<URI> inputs) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.inputs = inputs;
|
this.inputs = inputs;
|
||||||
|
hints = config.buildHints();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer call() throws IOException {
|
public Integer call() throws IOException {
|
||||||
int successful = 0;
|
int successful = 0;
|
||||||
for (URI input; (input = inputs.poll()) != null;) {
|
for (URI input; (input = inputs.poll()) != null;) {
|
||||||
Result[] results = decode(input, config.getHints());
|
Result[] results = decode(input, hints);
|
||||||
if (results != null) {
|
if (results != null) {
|
||||||
successful++;
|
successful++;
|
||||||
if (config.isDumpResults()) {
|
if (config.dumpResults) {
|
||||||
dumpResult(input, results);
|
dumpResult(input, results);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,22 +119,23 @@ final class DecodeWorker implements Callable<Integer> {
|
||||||
BufferedImage image = ImageReader.readImage(uri);
|
BufferedImage image = ImageReader.readImage(uri);
|
||||||
|
|
||||||
LuminanceSource source;
|
LuminanceSource source;
|
||||||
if (config.getCrop() == null) {
|
if (config.crop == null) {
|
||||||
source = new BufferedImageLuminanceSource(image);
|
source = new BufferedImageLuminanceSource(image);
|
||||||
} else {
|
} else {
|
||||||
int[] crop = config.getCrop();
|
List<Integer> crop = config.crop;
|
||||||
source = new BufferedImageLuminanceSource(image, crop[0], crop[1], crop[2], crop[3]);
|
source = new BufferedImageLuminanceSource(
|
||||||
|
image, crop.get(0), crop.get(1), crop.get(2), crop.get(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
if (config.isDumpBlackPoint()) {
|
if (config.dumpBlackPoint) {
|
||||||
dumpBlackPoint(uri, image, bitmap);
|
dumpBlackPoint(uri, image, bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiFormatReader multiFormatReader = new MultiFormatReader();
|
MultiFormatReader multiFormatReader = new MultiFormatReader();
|
||||||
Result[] results;
|
Result[] results;
|
||||||
try {
|
try {
|
||||||
if (config.isMulti()) {
|
if (config.multi) {
|
||||||
MultipleBarcodeReader reader = new GenericMultipleBarcodeReader(multiFormatReader);
|
MultipleBarcodeReader reader = new GenericMultipleBarcodeReader(multiFormatReader);
|
||||||
results = reader.decodeMultiple(bitmap, hints);
|
results = reader.decodeMultiple(bitmap, hints);
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,7 +146,7 @@ final class DecodeWorker implements Callable<Integer> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.isBrief()) {
|
if (config.brief) {
|
||||||
System.out.println(uri + ": Success");
|
System.out.println(uri + ": Success");
|
||||||
} else {
|
} else {
|
||||||
for (Result result : results) {
|
for (Result result : results) {
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2011 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.client.j2se;
|
||||||
|
|
||||||
|
import com.beust.jcommander.Parameter;
|
||||||
|
import com.beust.jcommander.validators.PositiveInteger;
|
||||||
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
import com.google.zxing.DecodeHintType;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
final class DecoderConfig {
|
||||||
|
|
||||||
|
@Parameter(names = "--try_harder",
|
||||||
|
description = "Use the TRY_HARDER hint, default is normal mode")
|
||||||
|
boolean tryHarder;
|
||||||
|
|
||||||
|
@Parameter(names="--pure_barcode",
|
||||||
|
description="Input image is a pure monochrome barcode image, not a photo")
|
||||||
|
boolean pureBarcode;
|
||||||
|
|
||||||
|
@Parameter(names = "--products_only",
|
||||||
|
description = "Only decode the UPC and EAN families of barcodes")
|
||||||
|
boolean productsOnly;
|
||||||
|
|
||||||
|
@Parameter(names = "--dump_results",
|
||||||
|
description = "Write the decoded contents to input.txt")
|
||||||
|
boolean dumpResults;
|
||||||
|
|
||||||
|
@Parameter(names = "--dump_black_point",
|
||||||
|
description = "Compare black point algorithms with dump as input.mono.png")
|
||||||
|
boolean dumpBlackPoint;
|
||||||
|
|
||||||
|
@Parameter(names = "--multi",
|
||||||
|
description = "Scans image for multiple barcodes")
|
||||||
|
boolean multi;
|
||||||
|
|
||||||
|
@Parameter(names = "--brief",
|
||||||
|
description = "Only output one line per file, omitting the contents")
|
||||||
|
boolean brief;
|
||||||
|
|
||||||
|
@Parameter(names = "--recursive",
|
||||||
|
description = "Descend into subdirectories")
|
||||||
|
boolean recursive;
|
||||||
|
|
||||||
|
@Parameter(names = "--crop",
|
||||||
|
description = " Only examine cropped region of input image(s)",
|
||||||
|
arity = 4,
|
||||||
|
validateWith = PositiveInteger.class)
|
||||||
|
List<Integer> crop;
|
||||||
|
|
||||||
|
@Parameter(names = "--possible_formats",
|
||||||
|
description = "Formats to decode, where format is any value in BarcodeFormat",
|
||||||
|
variableArity = true)
|
||||||
|
List<BarcodeFormat> possibleFormats;
|
||||||
|
|
||||||
|
@Parameter(names = "--help",
|
||||||
|
description = "Prints this help message",
|
||||||
|
help = true)
|
||||||
|
boolean help;
|
||||||
|
|
||||||
|
@Parameter(description = "(URIs to decode)", required = true, variableArity = true)
|
||||||
|
List<URI> inputPaths;
|
||||||
|
|
||||||
|
Map<DecodeHintType,?> buildHints() {
|
||||||
|
List<BarcodeFormat> finalPossibleFormats = possibleFormats;
|
||||||
|
if (finalPossibleFormats == null || finalPossibleFormats.isEmpty()) {
|
||||||
|
finalPossibleFormats = new ArrayList<>();
|
||||||
|
finalPossibleFormats.addAll(Arrays.asList(
|
||||||
|
BarcodeFormat.UPC_A,
|
||||||
|
BarcodeFormat.UPC_E,
|
||||||
|
BarcodeFormat.EAN_13,
|
||||||
|
BarcodeFormat.EAN_8,
|
||||||
|
BarcodeFormat.RSS_14,
|
||||||
|
BarcodeFormat.RSS_EXPANDED
|
||||||
|
));
|
||||||
|
if (!productsOnly) {
|
||||||
|
finalPossibleFormats.addAll(Arrays.asList(
|
||||||
|
BarcodeFormat.CODE_39,
|
||||||
|
BarcodeFormat.CODE_93,
|
||||||
|
BarcodeFormat.CODE_128,
|
||||||
|
BarcodeFormat.ITF,
|
||||||
|
BarcodeFormat.QR_CODE,
|
||||||
|
BarcodeFormat.DATA_MATRIX,
|
||||||
|
BarcodeFormat.AZTEC,
|
||||||
|
BarcodeFormat.PDF_417,
|
||||||
|
BarcodeFormat.CODABAR,
|
||||||
|
BarcodeFormat.MAXICODE
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
|
||||||
|
hints.put(DecodeHintType.POSSIBLE_FORMATS, finalPossibleFormats);
|
||||||
|
if (tryHarder) {
|
||||||
|
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
if (pureBarcode) {
|
||||||
|
hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap(hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue