Zxing横竖屏二维码识别异常问题求助(Android模拟器与实体设备)
解决Zxing横竖屏二维码识别不一致问题
问题原因
你遇到的模拟器与实体设备横竖屏识别结果相反的问题,核心是未处理CameraX返回图像的旋转角度。不同设备(模拟器/实体机)的摄像头传感器方向存在差异,导致横竖屏切换时,ImageProxy返回的图像旋转角度不一致。Zxing直接识别未旋转的图像数据时,会因为图像方向错误而无法解析二维码。
解决方案
通过ImageProxy.getImageInfo().getRotationDegrees()获取图像的旋转角度,根据角度调整YUV图像数据的方向,确保Zxing识别的图像方向与实际显示方向一致。
修改后的代码
public abstract class QRCodeAnalyzer implements ImageAnalysis.Analyzer{ @Override public void analyze(@NonNull ImageProxy image) { if (image.getFormat() == ImageFormat.YUV_420_888 || image.getFormat() == ImageFormat.YUV_422_888 || image.getFormat() == ImageFormat.YUV_444_888) { ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer(); byte[] imageData = new byte[byteBuffer.capacity()]; byteBuffer.get(imageData); int rotationDegrees = image.getImageInfo().getRotationDegrees(); Log.d("QR", "图像旋转角度:" + rotationDegrees); PlanarYUVLuminanceSource source; if (rotationDegrees == 90 || rotationDegrees == 270) { // 旋转90/270度时,宽高交换,同时旋转YUV数据 byte[] rotatedData = rotateYUV(imageData, image.getWidth(), image.getHeight(), rotationDegrees); source = new PlanarYUVLuminanceSource( rotatedData, image.getHeight(), image.getWidth(), 0, 0, image.getHeight(), image.getWidth(), false ); } else { // 0/180度直接使用原始数据 source = new PlanarYUVLuminanceSource( imageData, image.getWidth(), image.getHeight(), 0, 0, image.getWidth(), image.getHeight(), false ); } BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source)); Map<DecodeHintType, Object> hints = new HashMap<>(); hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); try { Result result = new QRCodeMultiReader().decode(binaryBitmap, hints); onQRCodeFound(result); } catch (FormatException | ChecksumException | NotFoundException e) { qrCodeNotFound(); } } image.close(); } /** * 旋转YUV图像数据(仅处理Y平面,满足二维码识别的亮度需求) */ private byte[] rotateYUV(byte[] yuvData, int width, int height, int rotation) { byte[] rotatedData = new byte[yuvData.length]; boolean isClockwise = rotation == 90; int newWidth = isClockwise ? height : width; int newHeight = isClockwise ? width : height; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int newX, newY; if (isClockwise) { // 顺时针旋转90度 newX = height - y - 1; newY = x; } else { // 逆时针旋转90度(等价于顺时针270度) newX = y; newY = width - x - 1; } rotatedData[newY * newWidth + newX] = yuvData[y * width + x]; } } return rotatedData; } public abstract void qrCodeNotFound(); public abstract void onQRCodeFound(Result result); }
补充说明
- 上述代码仅处理了YUV数据的Y平面(亮度通道),因为二维码识别主要依赖亮度信息,这样可以简化逻辑并保证识别效率。如果需要处理完整的YUV色彩数据,可以扩展
rotateYUV方法处理UV平面。 - 测试时可以观察Log输出的旋转角度,确认不同设备横竖屏时的角度差异,确保旋转逻辑覆盖所有场景。
内容的提问来源于stack exchange,提问作者stud0709
相关产品推荐
相关产品推荐

