com.google.zxing.client.j2se.DecodeWorker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javase Show documentation
Show all versions of javase Show documentation
Java SE-specific extensions to core ZXing library
/*
* 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.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;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.Callable;
/**
* One of a pool of threads which pulls images off the Inputs queue and decodes them in parallel.
*
* @see CommandLineRunner
*/
final class DecodeWorker implements Callable {
private static final Charset UTF8 = Charset.forName("UTF8");
private final Config config;
private final Queue inputs;
DecodeWorker(Config config, Queue inputs) {
this.config = config;
this.inputs = inputs;
}
@Override
public Integer call() throws IOException {
int successful = 0;
String input;
while ((input = inputs.poll()) != null) {
File inputFile = new File(input);
if (inputFile.exists()) {
if (config.isMulti()) {
Result[] results = decodeMulti(inputFile.toURI(), config.getHints());
if (results != null) {
successful++;
if (config.isDumpResults()) {
dumpResultMulti(inputFile, results);
}
}
} else {
Result result = decode(inputFile.toURI(), config.getHints());
if (result != null) {
successful++;
if (config.isDumpResults()) {
dumpResult(inputFile, result);
}
}
}
} else {
if (decode(URI.create(input), config.getHints()) != null) {
successful++;
}
}
}
return successful;
}
private static void dumpResult(File input, Result result) throws IOException {
String name = input.getCanonicalPath();
int pos = name.lastIndexOf('.');
if (pos > 0) {
name = name.substring(0, pos);
}
File dump = new File(name + ".txt");
writeStringToFile(result.getText(), dump);
}
private static void dumpResultMulti(File input, Result[] results) throws IOException {
String name = input.getCanonicalPath();
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 {
try (Writer out = new OutputStreamWriter(new FileOutputStream(file), UTF8)) {
out.write(value);
}
}
private static void writeResultsToFile(Result[] results, File file) throws IOException {
String newline = System.getProperty("line.separator");
try (Writer out = new OutputStreamWriter(new FileOutputStream(file), UTF8)) {
for (Result result : results) {
out.write(result.getText());
out.write(newline);
}
}
}
private Result decode(URI uri, Map hints) throws IOException {
BufferedImage image = ImageReader.readImage(uri);
try {
LuminanceSource source;
if (config.getCrop() == null) {
source = new BufferedImageLuminanceSource(image);
} else {
int[] crop = config.getCrop();
source = new BufferedImageLuminanceSource(image, crop[0], crop[1], crop[2], crop[3]);
}
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
if (config.isDumpBlackPoint()) {
dumpBlackPoint(uri, image, bitmap);
}
Result result = new MultiFormatReader().decode(bitmap, hints);
if (config.isBrief()) {
System.out.println(uri.toString() + ": Success");
} else {
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("Found " + result.getResultPoints().length + " result points.");
for (int i = 0; i < result.getResultPoints().length; i++) {
ResultPoint rp = result.getResultPoints()[i];
if (rp != null) {
System.out.println(" Point " + i + ": (" + rp.getX() + ',' + rp.getY() + ')');
}
}
}
return result;
} catch (NotFoundException ignored) {
System.out.println(uri.toString() + ": No barcode found");
return null;
}
}
private Result[] decodeMulti(URI uri, Map hints) throws IOException {
BufferedImage image = ImageReader.readImage(uri);
try {
LuminanceSource source;
if (config.getCrop() == null) {
source = new BufferedImageLuminanceSource(image);
} else {
int[] crop = config.getCrop();
source = new BufferedImageLuminanceSource(image, crop[0], crop[1], crop[2], crop[3]);
}
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
if (config.isDumpBlackPoint()) {
dumpBlackPoint(uri, image, bitmap);
}
MultiFormatReader multiFormatReader = new MultiFormatReader();
GenericMultipleBarcodeReader reader = new GenericMultipleBarcodeReader(
multiFormatReader);
Result[] results = reader.decodeMultiple(bitmap, hints);
if (config.isBrief()) {
System.out.println(uri.toString() + ": Success");
} else {
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("Found " + 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 ignored) {
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.
*/
private static void dumpBlackPoint(URI uri, BufferedImage image, BinaryBitmap bitmap) {
String inputName = uri.getPath();
if (inputName.contains(".mono.png")) {
return;
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int stride = width * 3;
int[] pixels = new int[stride * height];
// The original image
int[] argb = new int[width];
for (int y = 0; y < height; y++) {
image.getRGB(0, y, width, 1, argb, 0, width);
System.arraycopy(argb, 0, pixels, y * stride, width);
}
// Row sampling
BitArray row = new BitArray(width);
for (int y = 0; y < height; y++) {
try {
row = bitmap.getBlackRow(y, row);
} catch (NotFoundException nfe) {
// If fetching the row failed, draw a red line and keep going.
int offset = y * stride + width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = 0xffff0000;
}
continue;
}
int offset = y * stride + width;
for (int x = 0; x < width; x++) {
if (row.get(x)) {
pixels[offset + x] = 0xff000000;
} else {
pixels[offset + x] = 0xffffffff;
}
}
}
// 2D sampling
try {
for (int y = 0; y < height; y++) {
BitMatrix matrix = bitmap.getBlackMatrix();
int offset = y * stride + width * 2;
for (int x = 0; x < width; x++) {
if (matrix.get(x, y)) {
pixels[offset + x] = 0xff000000;
} else {
pixels[offset + x] = 0xffffffff;
}
}
}
} catch (NotFoundException ignored) {
// continue
}
writeResultImage(stride, height, pixels, uri, inputName, ".mono.png");
}
private static void writeResultImage(int stride,
int height,
int[] pixels,
URI uri,
String inputName,
String suffix) {
// Write the result
BufferedImage result = new BufferedImage(stride, height, BufferedImage.TYPE_INT_ARGB);
result.setRGB(0, 0, stride, height, pixels, 0, stride);
// Use the current working directory for URLs
String resultName = inputName;
if ("http".equals(uri.getScheme())) {
int pos = resultName.lastIndexOf('/');
if (pos > 0) {
resultName = '.' + resultName.substring(pos);
}
}
int pos = resultName.lastIndexOf('.');
if (pos > 0) {
resultName = resultName.substring(0, pos);
}
resultName += suffix;
try (OutputStream outStream = new FileOutputStream(resultName)) {
if (!ImageIO.write(result, "png", outStream)) {
System.err.println("Could not encode an image to " + resultName);
}
} catch (IOException ignored) {
System.err.println("Could not write to " + resultName);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy