Android zxing生成带logo二维码

1,592 阅读3分钟

以下工具类实现了二维码的生成和添加 Logo 的功能。以下是对各部分功能的解释:

二维码生成:

通过 createQRCode() 方法来生成二维码图像。 它使用 QRCodeWriter 类来创建 BitMatrix 对象,该对象表示二维码的像素矩阵。 然后将 BitMatrix 转换为 Bitmap 对象。 zxing在生成二维码时,默认无法完全删除二维码白边,需要自定义BitMatrix,为其修改边框,该方法可以设置二维码的尺寸二维码白边边距大小

添加 Logo:

通过 addLogo() 方法在二维码图像上添加 Logo。 它使用**矩阵变换(缩放和平移)**来将 Logo 居中添加到二维码图像上。 这样可以在二维码图像上添加一个小的 Logo,使二维码的视觉效果更佳。

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.TypedValue;
import android.view.View;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 二维码工具
 *
 * @author : jerome
 */
public class QRCodeUtil {

    /**
     * 用于创建一个二维码
     *
     * @param content
     */
    public static Bitmap createQRCode(String content, Bitmap bm_logo, View view, int width, int margin) {
        try {
            int QR_WIDTH = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,width, view.getResources().getDisplayMetrics()) ; // 图像宽度
            int QR_HEIGHT = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,width, view.getResources().getDisplayMetrics()) ; // 图像高度
            //1,创建实例化对象
            QRCodeWriter writer = new QRCodeWriter();
            //2,设置字符集
            Map<EncodeHintType, Object> map = new HashMap<EncodeHintType, Object>();
            map.put(EncodeHintType.CHARACTER_SET, "UTF-8");
//            map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            //3,通过encode方法将内容写入矩阵对象
            BitMatrix matrix;
             matrix = writer.encode(content, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, map);
             //设置二维码白边
            matrix = updateBit(matrix,margin);
            //4,定义一个二维码像素点的数组,向每个像素点中填充颜色
            int[] pixels = new int[matrix.getWidth() * matrix.getHeight()];

            for (int i = 0; i < matrix.getHeight(); i++) {
                for (int j = 0; j < matrix.getWidth(); j++) {
                    // 如果矩阵此位置有值(是黑色部分)
                    if (matrix.get(j, i)) {
                        pixels[i * matrix.getWidth() + j] = 0xff000000;
                        // 如果矩阵此位置无值(是白色部分)
                    } else {
                        pixels[i * matrix.getWidth() + j] = 0xffffffff;
                    }
                }
            }

            //6,创建一个指定高度和宽度的空白bitmap对象
            Bitmap bm_QR = Bitmap.createBitmap(matrix.getWidth(), matrix.getHeight(), Bitmap.Config.ARGB_8888);
            //7,将每个像素的颜色填充到bitmap对象
            bm_QR.setPixels(pixels, 0, matrix.getWidth(), 0, 0, matrix.getWidth(), matrix.getHeight());
            //9,创建一个方法在二维码上添加一张图片
            if (null != bm_logo)
                return addLogo(bm_QR, bm_logo);
            else
                return bm_QR;
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 更新BitMatrix,为其增加边框。
     *
     * @param matrix 原始的BitMatrix对象。
     * @param margin 边框的宽度(单位:像素)。
     * @return 增加了边框的新BitMatrix对象。
     */
    private static BitMatrix updateBit(BitMatrix matrix, int margin) {
        int tempM = margin * 2;
        int[] rec = matrix.getEnclosingRectangle(); // 获取二维码图案的属性
        // rec[0]表示 left:二维码距离矩阵左边缘的距离
        // rec[1]表示 top:二维码距离矩阵上边缘的距离
        // rect[2]表示二维码的宽
        // rect[2]表示二维码的高
        int resWidth = rec[2] + tempM;
        int resHeight = rec[3] + tempM;
        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight); // 按照自定义边框生成新的BitMatrix
        resMatrix.clear();
        for (int i = margin; i < resWidth - margin; i++) { // 循环,将二维码图案绘制到新的bitMatrix中
            for (int j = margin; j < resHeight - margin; j++) {
                if (matrix.get(i - margin + rec[0], j - margin + rec[1])) {
                    resMatrix.set(i, j);
                }
            }
        }
        return resMatrix;
    }

    /**
     * 添加 Logo 到二维码图片上
     * <pre>
     *     使用矩阵变换进行平移和缩放操作,确保 Logo 居中显示
     * </pre>
     * @param src  二维码图片
     * @param logo Logo
     * @return 含 Logo 二维码图片
     */
    public static Bitmap addLogo(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();

        // 计算Logo要缩放的比例
        float scaleFactor = Math.min(srcWidth * 1.0f / 6 / logoWidth, srcHeight * 1.0f / 6 / logoHeight);

        // 创建一个新的Bitmap,用于绘制带Logo的二维码图片
        Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawBitmap(src, 0, 0, null);

        // 创建一个Matrix对象,用于进行矩阵变换操作
        Matrix matrix = new Matrix();
        matrix.postScale(scaleFactor, scaleFactor);

        // 计算Logo在二维码图片上的位置
        int logoX = (srcWidth - (int) (logoWidth * scaleFactor)) / 2;
        int logoY = (srcHeight - (int) (logoHeight * scaleFactor)) / 2;

        // 对Logo进行矩阵变换,平移到指定位置并缩放
        matrix.postTranslate(logoX, logoY);
        canvas.drawBitmap(logo, matrix, null);

        return bitmap;
    }
}

定义ImageView:

     <ImageView
                android:id="@+id/codeView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:scaleType="fitXY"
                android:layout_marginTop="3dp"
                android:layout_marginBottom="3dp"
                />

调用方式:

QRCodeUtil.createQRCode(codeContent, logoBitmap, codeView, 295,2)