Android ZXing 二维码工具类

DevUtils Github

方法注释
createQRCodeImage生成二维码图片
decodeQRCode解析二维码图片
getResultData获取扫描结果数据
syncEncodeQRCode同步创建黑色前景色、白色背景色的二维码图片
addLogoToQRCode添加 Logo 到二维码图片上
onResult生成二维码结果回调
package dev.other;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import java.util.EnumMap;
import java.util.Map;

import dev.utils.LogPrintUtils;
import dev.utils.common.thread.DevThreadManager;

/**
 * detail: ZXing 二维码工具类
 * @author Ttt
 */
public final class ZXingQRCodeUtils {

    private ZXingQRCodeUtils() {
    }

    private static final String TAG = ZXingQRCodeUtils.class.getSimpleName();

    // ==============
    // = 生成二维码 =
    // ==============

    /**
     * detail: 生成二维码结果回调
     * @author Ttt
     */
    public interface QRResultCallBack {

        /**
         * 生成二维码结果回调
         * @param success 是否成功
         * @param bitmap  成功图片
         * @param e       异常信息
         */
        void onResult(boolean success, Bitmap bitmap, Exception e);
    }

    // =

    /**
     * 生成二维码图片
     * @param content 生成内容
     * @param size    图片宽高大小 ( 正方形 px )
     */
    public static void createQRCodeImage(final String content, final int size) {
        createQRCodeImage(content, size, null, null);
    }

    /**
     * 生成二维码图片
     * @param content          生成内容
     * @param size             图片宽高大小 ( 正方形 px )
     * @param qrResultCallBack 生成结果回调
     */
    public static void createQRCodeImage(final String content, final int size, final QRResultCallBack qrResultCallBack) {
        createQRCodeImage(content, size, null, qrResultCallBack);
    }

    /**
     * 生成二维码图片
     * @param content          生成内容
     * @param size             图片宽高大小 ( 正方形 px )
     * @param logo             中间 Logo
     * @param qrResultCallBack 生成结果回调
     */
    public static void createQRCodeImage(final String content, final int size, final Bitmap logo, final QRResultCallBack qrResultCallBack) {
        DevThreadManager.getInstance(10).execute(new Runnable() {
            @Override
            public void run() {
                try {
                    // 生成二维码图片
                    Bitmap qrCodeBitmap = syncEncodeQRCode(content, size);
                    if (logo != null) { // 中间 Logo
                        qrCodeBitmap = addLogoToQRCode(qrCodeBitmap, logo);
                    }
                    // 触发回调
                    if (qrResultCallBack != null) {
                        qrResultCallBack.onResult(true, qrCodeBitmap, null);
                    }
                } catch (Exception e) {
                    LogPrintUtils.eTag(TAG, e, "createQRCodeImage");
                    // 触发回调
                    if (qrResultCallBack != null) {
                        qrResultCallBack.onResult(false, null, e);
                    }
                }
            }
        });
    }

    // ==============
    // = 解析二维码 =
    // ==============

    // 解析配置
    private static final Map<DecodeHintType, Object> DECODE_HINTS = new EnumMap<>(DecodeHintType.class);

    /**
     * detail: 二维码扫描结果回调
     * @author Ttt
     */
    public interface QRScanCallBack {

        /**
         * 二维码扫描结果回调
         * @param success 是否成功
         * @param result  识别数据 {@link Result}
         * @param e       异常信息
         */
        void onResult(boolean success, Result result, Exception e);
    }

    // =

    /**
     * 解析二维码图片
     * @param bitmap         待解析的二维码图片
     * @param qrScanCallBack 解析结果回调
     */
    public static void decodeQRCode(final Bitmap bitmap, final QRScanCallBack qrScanCallBack) {
        if (bitmap == null) {
            if (qrScanCallBack != null) {
                qrScanCallBack.onResult(false, null, new Exception("bitmap is null"));
            }
            return;
        }
        // 开始解析
        DevThreadManager.getInstance(5).execute(new Runnable() {
            @Override
            public void run() {
                try {
                    int width = bitmap.getWidth();
                    int height = bitmap.getHeight();
                    int[] pixels = new int[width * height];
                    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
                    RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels);
                    Result result = new MultiFormatReader().decode(new BinaryBitmap(new HybridBinarizer(source)), DECODE_HINTS);
                    // 触发回调
                    if (qrScanCallBack != null) {
                        qrScanCallBack.onResult((result != null), result, null);
                    }
                } catch (Exception e) {
                    LogPrintUtils.eTag(TAG, e, "decodeQRCode");
                    // 触发回调
                    if (qrScanCallBack != null) {
                        qrScanCallBack.onResult(false, null, e);
                    }
                }
            }
        });
    }

    // ============
    // = 获取结果 =
    // ============

    /**
     * 获取扫描结果数据
     * @param result 识别数据 {@link Result}
     * @return 扫描结果数据
     */
    public static String getResultData(final Result result) {
        return (result != null) ? result.getText() : null;
    }

    // ========
    // = 编码 =
    // ========

    // 编码类型
    private static final Map<EncodeHintType, Object> ENCODE_HINTS = new EnumMap<>(EncodeHintType.class);

    static {
        // 编码类型
        ENCODE_HINTS.put(EncodeHintType.CHARACTER_SET, "utf-8");
        // 指定纠错等级, 纠错级别 ( L 7%、M 15%、Q 25%、H 30% )
        ENCODE_HINTS.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置二维码边的空度, 非负数
        ENCODE_HINTS.put(EncodeHintType.MARGIN, 0);
    }

    /**
     * 同步创建黑色前景色、白色背景色的二维码图片
     * @param content 生成内容
     * @param size    图片宽高大小 ( 正方形 px )
     * @return 二维码图片
     */
    public static Bitmap syncEncodeQRCode(final String content, final int size) {
        return syncEncodeQRCode(content, size, Color.BLACK, Color.WHITE);
    }

    /**
     * 同步创建指定前景色、指定背景色二维码图片
     * <pre>
     *     该方法是耗时操作, 请在子线程中调用
     * </pre>
     * @param content         生成内容
     * @param size            图片宽高大小 ( 正方形 px )
     * @param foregroundColor 二维码图片的前景色
     * @param backgroundColor 二维码图片的背景色
     * @return 二维码图片
     */
    public static Bitmap syncEncodeQRCode(final String content, final int size, final int foregroundColor, final int backgroundColor) {
        try {
            BitMatrix matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, size, size, ENCODE_HINTS);
            int[] pixels = new int[size * size];
            for (int y = 0; y < size; y++) {
                for (int x = 0; x < size; x++) {
                    if (matrix.get(x, y)) {
                        pixels[y * size + x] = foregroundColor;
                    } else {
                        pixels[y * size + x] = backgroundColor;
                    }
                }
            }
            Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
            bitmap.setPixels(pixels, 0, size, 0, 0, size, size);
            return bitmap;
        } catch (Exception e) {
            LogPrintUtils.eTag(TAG, e, "syncEncodeQRCode");
            return null;
        }
    }

    /**
     * 添加 Logo 到二维码图片上
     * <pre>
     *     非最优方法, 该方式是直接把 Logo 覆盖在图片上会遮挡部分内容
     * </pre>
     * @param src  二维码图片
     * @param logo Logo
     * @return 含 Logo 二维码图片
     */
    public static Bitmap addLogoToQRCode(final Bitmap src, final Bitmap logo) {
        if (src == null || logo == null) return src;
        // 获取图片宽度高度
        int srcWidth = src.getWidth();
        int srcHeight = src.getHeight();
        int logoWidth = logo.getWidth();
        int logoHeight = logo.getHeight();
        // 缩放图片
        float scaleFactor = srcWidth * 1.0f / 4 / logoWidth; // 这里的 4 决定 Logo 在图片的比例 四分之一
        Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
        try {
            Canvas canvas = new Canvas(bitmap);
            canvas.drawBitmap(src, 0, 0, null);
            canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2);
            canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null);
            canvas.save();
            canvas.restore();
        } catch (Exception e) {
            LogPrintUtils.eTag(TAG, e, "addLogoToQRCode");
            bitmap = null;
        }
        return bitmap;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值