You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 23:10:28