如何使用ZXing库从图片(而非相机)扫描二维码/条码?
使用ZXing从本地SD卡图片扫描条码的实现方法
嘿,刚好之前用ZXing做过本地图片条码扫描的需求,给你分享下具体的实现步骤,亲测好用!
一、先做好准备工作
- 确保项目已经引入ZXing核心库,如果是Android项目,在Gradle里加这句就行:
implementation 'com.google.zxing:core:3.5.2'
要是想用封装好的Android工具类,也可以加implementation 'com.journeyapps:zxing-android-embedded:4.3.0',不过核心扫描逻辑用core库就够了。 - 别忘了申请读取外部存储的权限!Android 13及以上还要申请
READ_MEDIA_IMAGES权限,动态权限申请可不能忘,不然根本读不到SD卡的图片。
二、核心扫描逻辑实现
ZXing扫描图片的核心是把图片转换成它能识别的LuminanceSource,再用MultiFormatReader解析条码内容,给你两种常用的实现方式:
方式1:通过Bitmap解析(Android端常用)
写个工具方法,传入SD卡图片的路径,就能返回扫描到的条码内容:
import com.google.zxing.*; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.client.android.RGBLuminanceSource; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; public String scanBarcodeFromImage(String imagePath) { // 1. 从SD卡路径加载Bitmap Bitmap bitmap = BitmapFactory.decodeFile(imagePath); if (bitmap == null) { return null; // 图片加载失败,直接返回 } // 2. 把Bitmap转成ZXing需要的LuminanceSource int width = bitmap.getWidth(); int height = bitmap.getHeight(); int[] pixels = new int[width * height]; bitmap.getPixels(pixels, 0, width, 0, 0, width, height); LuminanceSource source = new RGBLuminanceSource(width, height, pixels); BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source)); // 3. 配置要扫描的条码格式(按需添加,比如QR码、CODE_128这些) MultiFormatReader reader = new MultiFormatReader(); Hashtable<DecodeHintType, Object> hints = new Hashtable<>(); List<BarcodeFormat> formats = new ArrayList<>(); formats.add(BarcodeFormat.QR_CODE); formats.add(BarcodeFormat.CODE_128); formats.add(BarcodeFormat.EAN_13); hints.put(DecodeHintType.POSSIBLE_FORMATS, formats); reader.setHints(hints); // 4. 尝试解析条码 try { Result result = reader.decode(binaryBitmap); return result.getText(); // 成功拿到条码内容 } catch (NotFoundException e) { e.printStackTrace(); return null; // 没识别到条码 } catch (ChecksumException e) { e.printStackTrace(); return null; // 条码校验出错 } catch (FormatException e) { e.printStackTrace(); return null; // 条码格式不对 } finally { bitmap.recycle(); // 用完Bitmap记得释放内存,避免OOM } }
方式2:直接通过文件流解析(更省内存)
如果图片很大,用Bitmap容易内存溢出,这时候可以直接读文件流解析,适合Java环境或者处理大图片的场景:
import com.google.zxing.*; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.HybridBinarizer; import javax.imageio.ImageIO; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; public String scanBarcodeFromFile(String imagePath) { File imageFile = new File(imagePath); if (!imageFile.exists()) { return null; // 文件不存在直接返回 } try { // 直接读取文件成BufferedImage BufferedImage image = ImageIO.read(imageFile); LuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source)); // 同样配置扫描格式 MultiFormatReader reader = new MultiFormatReader(); Hashtable<DecodeHintType, Object> hints = new Hashtable<>(); List<BarcodeFormat> formats = new ArrayList<>(); formats.add(BarcodeFormat.QR_CODE); hints.put(DecodeHintType.POSSIBLE_FORMATS, formats); reader.setHints(hints); Result result = reader.decode(binaryBitmap); return result.getText(); } catch (IOException | NotFoundException | ChecksumException | FormatException e) { e.printStackTrace(); return null; } }
三、几个要注意的小细节
- 权限一定要到位:Android 6.0+必须动态申请读取外部存储的权限,不然连图片都读不了。
- 图片质量很重要:如果图片模糊、条码被遮挡,ZXing大概率识别不出来,建议提示用户选清晰的图片。
- 内存优化:加载大图片时,记得用
BitmapFactory.Options设置inSampleSize来压缩图片,避免内存溢出。 - 多格式支持:如果需要扫描多种类型的条码,记得在
POSSIBLE_FORMATS里添加对应的BarcodeFormat枚举值就行。
内容的提问来源于stack exchange,提问作者Ramadita
相关产品推荐
相关产品推荐

