使用Java中的Zxing读取QRCode

17

关于使用Zxing的一些问题...

我写了以下代码来从图像中读取条形码:

public class BarCodeDecode 
{
    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        try
        {
            String tmpImgFile = "D:\\FormCode128.TIF";

            Map<DecodeHintType,Object> tmpHintsMap = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
            tmpHintsMap.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            tmpHintsMap.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
            tmpHintsMap.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE);

            File tmpFile = new File(tmpImgFile);
            String tmpRetString = BarCodeUtil.decode(tmpFile, tmpHintsMap);
            //String tmpRetString = BarCodeUtil.decode(tmpFile, null);
            System.out.println(tmpRetString);
        }
        catch (Exception tmpExpt)
        {
            System.out.println("main: " + "Excpt err! (" + tmpExpt.getMessage() + ")");
        }
        System.out.println("main: " + "Program end.");
    }

}

public class BarCodeUtil 
{
    private static BarcodeFormat DEFAULT_BARCODE_FORMAT = BarcodeFormat.CODE_128;

    /**
      * Decode method used to read image or barcode itself, and recognize the barcode,
      * get the encoded contents and returns it.
      * @param whatFile image that need to be read.
      * @param config configuration used when reading the barcode.
      * @return decoded results from barcode.
      */
     public static String decode(File whatFile, Map<DecodeHintType, Object> whatHints) throws Exception 
     {
         // check the required parameters
         if (whatFile == null || whatFile.getName().trim().isEmpty())
             throw new IllegalArgumentException("File not found, or invalid file name.");
         BufferedImage tmpBfrImage;
         try 
         {
             tmpBfrImage = ImageIO.read(whatFile);
         } 
         catch (IOException tmpIoe) 
         {
             throw new Exception(tmpIoe.getMessage());
         }
         if (tmpBfrImage == null)
             throw new IllegalArgumentException("Could not decode image.");
         LuminanceSource tmpSource = new BufferedImageLuminanceSource(tmpBfrImage);
         BinaryBitmap tmpBitmap = new BinaryBitmap(new HybridBinarizer(tmpSource));
         MultiFormatReader tmpBarcodeReader = new MultiFormatReader();
         Result tmpResult;
         String tmpFinalResult;
         try 
         {
             if (whatHints != null && ! whatHints.isEmpty())
                 tmpResult = tmpBarcodeReader.decode(tmpBitmap, whatHints);
             else
                 tmpResult = tmpBarcodeReader.decode(tmpBitmap);
             // setting results.
             tmpFinalResult = String.valueOf(tmpResult.getText());
         } 
         catch (Exception tmpExcpt) 
         {
             throw new Exception("BarCodeUtil.decode Excpt err - " + tmpExcpt.toString() + " - " + tmpExcpt.getMessage());
         }
         return tmpFinalResult;
    }
}

我尝试阅读下面包含Code128和QRCode的两张图片。

enter image description here enter image description here

它可以识别Code128,但无法识别QRCode。 有人知道为什么吗...


1
为了解决这个问题,我最终在程序中剪切了条形码和QR码所在的区域。然后它们得到了识别。 - Johnny
你是如何剪切/指定区域的?我也遇到了类似的情况。 - Don Cheadle
1
亲爱的mmcrae,我首先将整个图像读入缓冲区----> BufferedImage tmpBfrImage = ImageIO.read(whatFile); 然后使用getSubimage方法---->BufferedImage tmpBarCodeBfrImage = tmpBfrImage.getSubimage(whatBarCodeArea.x, whatBarCodeArea.y, whatBarCodeArea.width, whatBarCodeArea.height); - Johnny
你的代码对我有效。 - michaeln peterson
3个回答

10

请通过链接查看完整的教程。这个代码的作者是Joe。我没有开发这个代码,所以我只是复制粘贴以确保在链接失效的情况下可用。

作者正在使用ZXing(Zebra Crossing Library),您可以从此处下载该库,用于本教程。

Java中的QR码编写和读取程序:

package com.javapapers.java;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class QRCode {

  public static void main(String[] args) throws WriterException, IOException,
      NotFoundException {
    String qrCodeData = "Hello World!";
    String filePath = "QRCode.png";
    String charset = "UTF-8"; // or "ISO-8859-1"
    Map<EncodeHintType, ErrorCorrectionLevel> hintMap = new HashMap<EncodeHintType, ErrorCorrectionLevel>();
    hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);

    createQRCode(qrCodeData, filePath, charset, hintMap, 200, 200);
    System.out.println("QR Code image created successfully!");

    System.out.println("Data read from QR Code: "
        + readQRCode(filePath, charset, hintMap));

  }

  public static void createQRCode(String qrCodeData, String filePath,
      String charset, Map hintMap, int qrCodeheight, int qrCodewidth)
      throws WriterException, IOException {
    BitMatrix matrix = new MultiFormatWriter().encode(
        new String(qrCodeData.getBytes(charset), charset),
        BarcodeFormat.QR_CODE, qrCodewidth, qrCodeheight, hintMap);
    MatrixToImageWriter.writeToFile(matrix, filePath.substring(filePath
        .lastIndexOf('.') + 1), new File(filePath));
  }

  public static String readQRCode(String filePath, String charset, Map hintMap)
      throws FileNotFoundException, IOException, NotFoundException {
    BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(
        new BufferedImageLuminanceSource(
            ImageIO.read(new FileInputStream(filePath)))));
    Result qrCodeResult = new MultiFormatReader().decode(binaryBitmap,
        hintMap);
    return qrCodeResult.getText();
  }
}

ZXing QR Code库的Maven依赖:

<dependency>
  <groupId>com.google.zxing</groupId>
  <artifactId>core</artifactId>
  <version>2.2</version>
</dependency>

<dependency>
  <groupId>com.google.zxing</groupId>
  <artifactId>javase</artifactId>
  <version>2.2</version>
</dependency>

我原本以为QR码阅读器不是为UTF-8设计的,但有时它们能够正确猜测。我相信要使用的标准是ISO-8859-1。 - Don Cheadle

8

奇怪的是,您的代码对我有效,但我不得不删除以下提示。

tmpHintsMap.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE);

当我的图像不是纯条形码时,这个提示破坏了我的结果。

谢谢!


2
正确,您不想将其设置为任何值。如果它具有任何值,则为“true”。嗯,也许这不是最好的选择。 - Sean Owen
很奇怪,这似乎会防止它找到非条形码,但这似乎是预期的行为。 - Don Cheadle

0

这段代码对我有效。

public static List<string> ScanForBarcodes(string path)
{
  return ScanForBarcodes(new Bitmap(path));
}

public static List<string> ScanForBarcodes(Bitmap bitmap)
{
  // initialize a new Barcode reader.
  BarcodeReader reader = new BarcodeReader
  {
    TryHarder = true, // TryHarder is slower but recognizes more Barcodes
    PossibleFormats = new List<BarcodeFormat> // in the ZXing There is an Enum where all supported barcodeFormats were contained
    {
      BarcodeFormat.CODE_128, 
      BarcodeFormat.QR_CODE,
      //BarcodeFormat. ... ;
    }
  };
  return reader.DecodeMultiple(bitmap).Select(result => result.Text).ToList(); // return only the barcode string.
                                                                               // If you want the full Result use: return reader.DecodeMultiple(bitmap);
}

你使用过this(ZXing.Net)库吗?

我正在使用它的Java库。 - Johnny
ZXing.net出了问题吗?它对我完全不起作用。Decode方法总是返回null。 - Zack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接