user3813234
user3813234

Reputation: 1682

scanning more than one barcode with zxing in java

I need to read pdf417 barcodes from tiffs. There is usually more than one barcode on the image-

This is my code:

InputStream in = null;
        BufferedImage bfi = null;
        File[] files = new File(DIR).listFiles();

        for (int i = 0; i < files.length; i++) {
            if (files[i].isFile()) {
                try {
                    System.out.println(files[i].getName());
                    in = new FileInputStream(files[i]);
                    bfi = ImageIO.read(in);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (in != null) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

                if (bfi != null) {
                    LuminanceSource ls = new BufferedImageLuminanceSource(bfi);
                    BinaryBitmap bmp = new BinaryBitmap(new HybridBinarizer(ls));
                    Reader reader = new MultiFormatReader();
                    Result result = null;

                    Hashtable<DecodeHintType, Object> decodeHints = new Hashtable<DecodeHintType, Object>();
                    decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);

                    try {
                        result = reader.decode(bmp, decodeHints);
                    } catch (NotFoundException e) {
                        e.printStackTrace();
                    } catch (ChecksumException e) {
                        e.printStackTrace();
                    } catch (FormatException e) {
                        e.printStackTrace();
                    }
                    System.out.println(result.getBarcodeFormat());
                    System.out.println("Text " + result.getText());
                    System.out
                            .println("-------------------------------------------------------");

                } else {
                    System.out.println("No Buffered Image for "
                            + files[i].getName());
                }
            }

        }

This works sometimes but sometimes it doesn't and the result is null.

I looked at the javadoc of zxing and found a GenericMultipleBarcodeReader. I tried to use in in my code but am doing it wrong because I get a NullPointerException:

Reader reader = new MultiFormatReader();
                    GenericMultipleBarcodeReader greader = new GenericMultipleBarcodeReader(reader);
                    Result[] result = null;

                    Hashtable<DecodeHintType, Object> decodeHints = new Hashtable<DecodeHintType, Object>();
                    decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);

                    try {
                        result = greader.decodeMultiple(bmp, decodeHints);
                    } catch (NotFoundException e) {
                        e.printStackTrace();
                    }

                    for (int j = 0; j < result.length; j++) {
                        System.out.println(result[j].getBarcodeFormat());
                        System.out.println("Text " + result[j].getText());
                    }


Exception in thread "main" java.lang.NullPointerException
    at com.google.zxing.multi.GenericMultipleBarcodeReader.translateResultPoints(GenericMultipleBarcodeReader.java:163)
    at com.google.zxing.multi.GenericMultipleBarcodeReader.doDecodeMultiple(GenericMultipleBarcodeReader.java:96)
    at com.google.zxing.multi.GenericMultipleBarcodeReader.doDecodeMultiple(GenericMultipleBarcodeReader.java:148)
    at com.google.zxing.multi.GenericMultipleBarcodeReader.decodeMultiple(GenericMultipleBarcodeReader.java:65)
    at barcode.ZXingTest.main(ZXingTest.java:77)

So the question is: Is it better to use the GenericMultipleBarcodeReader (or some other class) to scan multiple barcodes on an image and if so, how do I have to implement that?

UPDATE:

for (int i = 0; i < files.length; i++) {
            try (BufferedInputStream bfin = new BufferedInputStream(
                    new FileInputStream(files[i]))) {
                dateiname = files[i].getName();

                bfi = ImageIO.read(bfin);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (bfi != null) {
                LuminanceSource ls = new BufferedImageLuminanceSource(bfi);
                BinaryBitmap bmp = new BinaryBitmap(new HybridBinarizer(ls));

                Reader reader = new MultiFormatReader();
                GenericMultipleBarcodeReader greader = new GenericMultipleBarcodeReader(
                        new ByQuadrantReader(reader));
                Result[] result = null;

                Hashtable<DecodeHintType, Object> decodeHints = new Hashtable<DecodeHintType, Object>();
                decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);

                try {
                    result = greader.decodeMultiple(bmp, decodeHints);
                } catch (NotFoundException e) {
                    e.printStackTrace();
                    System.out.println("No result");
                    System.out.println("+++++++++++++++++++++++++++++++");
                }
                if (result != null) {
                    for (int j = 0; j < result.length; j++) {
                        System.out.println(result[j].getText());
                        System.out.println("+++++++++++++++++++++++++++++++");
                    } 
                }

            } else {
                System.out.println("No Buffered Image for "
                        + files[i].getName());
            }

        }

If I try it without the ByQuadrantReader, I get the same NullPointerException. The way I'm doing it , result.length is sometimes 1 (returning one String) and sometimes I get a NotFoundException.

I hope it's not a dumb fault in my code that I don't see...

2nd EDIT:

Exception in thread "main" java.lang.NullPointerException
    at com.google.zxing.multi.GenericMultipleBarcodeReader.doDecodeMultiple(GenericMultipleBarcodeReader.java:109)
    at com.google.zxing.multi.GenericMultipleBarcodeReader.doDecodeMultiple(GenericMultipleBarcodeReader.java:148)
    at com.google.zxing.multi.GenericMultipleBarcodeReader.decodeMultiple(GenericMultipleBarcodeReader.java:65)
    at barcode.ZXingTestMulti.main(ZXingTestMulti.java:86)

3rd EDIT:

current version of code:

public static void main(final String[] args) {

        BufferedImage bfi = null;
        File[] files = new File(DIR).listFiles();
        int counttiffs = 0;
        String filename = null;
        TreeMap<String, Exception> errormap = new TreeMap<String, Exception>();
        int onebarcode = 0;
        int twobarcodes = 0;
        int threebarcodes = 0;

        for (int i = 0; i < files.length; i++) {
            if (files[i].isFile()) {
                try (BufferedInputStream bfin = new BufferedInputStream(
                        new FileInputStream(files[i]))) {
                    filename = files[i].getName();

                    bfi = ImageIO.read(bfin);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                if (bfi != null) {
                    LuminanceSource ls = new BufferedImageLuminanceSource(bfi);
                    BinaryBitmap bmp = new BinaryBitmap(new HybridBinarizer(ls));

                    Reader reader = new MultiFormatReader();
                    GenericMultipleBarcodeReader greader = new GenericMultipleBarcodeReader(
                            reader);
                    Result[] result = null;

                    Hashtable<DecodeHintType, Object> decodeHints = new Hashtable<DecodeHintType, Object>();
                    decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);

                    try {
                        result = greader.decodeMultiple(bmp, decodeHints);
                    } catch (NotFoundException e) {
                        errormap.put(filename, e);
                    } catch (NullPointerException e) {
                        errormap.put(filename, e);
                    }
                    if (result != null) {
                        switch (result.length) {
                            case 1:
                                onebarcode++;
                                break;
                            case 3:
                                threebarcodes++;
                                break;
                            default:
                                twobarcodes++;

                        }
                        try (BufferedWriter bfwr = new BufferedWriter(
                                new FileWriter(FILE, true))) {
                            bfwr.write(filename + ": number of barcodes found = "
                                    + result.length);
                            bfwr.newLine();
                            for (int j = 0; j < result.length; j++) {
                                bfwr.write(result[j].getText());
                            }
                            bfwr.newLine();
                            bfwr.write("---------------------------------------------------------");
                            bfwr.newLine();
                            counttiffs++;
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }

                }
                else {
                    System.out.println("No Buffered Image for "
                            + files[i].getName());
                }
            }
        }

I'm using snapshots 3.1.1 of core and javase.

As you see, I need to catch a NPE:

java.lang.NullPointerException
    at com.google.zxing.multi.GenericMultipleBarcodeReader.translateResultPoints(GenericMultipleBarcodeReader.java:163)
    at com.google.zxing.multi.GenericMultipleBarcodeReader.doDecodeMultiple(GenericMultipleBarcodeReader.java:96)
    at com.google.zxing.multi.GenericMultipleBarcodeReader.doDecodeMultiple(GenericMultipleBarcodeReader.java:148)
    at com.google.zxing.multi.GenericMultipleBarcodeReader.decodeMultiple(GenericMultipleBarcodeReader.java:65)
    at zBarcodes_Test.ZXingTestMulti.main(ZXingTestMulti.java:72)

It's the same as the first one. After your first commit, I got a NPE on a different line, but now either I'm using the wrong dependency or it happened again.

And the other thing is: I scanned about 2.500 tiff-files, each with two pdf417 barcodes on them, some a little tilted and some not in perfect quality (meaning some pixles are white instead of black). I get a total of 1644 errors, either caused by a NotFoundException or NullPointer Exception. And of the 948 files scanned successfully, with 218 result.length is 1 (and it only found one barcode) and with 68, result.length is 3 (but it scanned 2 barcodes as it should).

In your experience, how sensible is zxing when barcodes are not perfetcly straight and have little errors on the edges, where pixles have not been printed perfectly?

Upvotes: 2

Views: 5192

Answers (1)

Sean Owen
Sean Owen

Reputation: 66886

This just looks like a bug, which I fixed in https://github.com/zxing/zxing/commit/e715fec42a2f8643c8f53c331f7218a1e62b0dc2 Can you try the fix perhaps by grabbing 3.1.1-SNAPSHOT?

Upvotes: 1

Related Questions