在Android中如何在二维码中添加Logo

9

我看到过一些在二维码中心放置公司Logo的QR码。在安卓上有没有可能生成带有任意Logo的QR码?如果有可能,请解释一下如何实现。目前,我正在使用Zxing来生成QR码。


可能是使用Java创建设计QR码的库?的重复问题。 - rds
4个回答

8
这其实是一个技巧,如果你使用的是zxing生成QR码,它会返回一个位图值,因此你可以将你的QR码位图与你的logo位图合并,这里有一个例子:
首先,你必须有一个void函数来合并两个位图,并调整logo的大小,这样你就可以将其适配到QR码的中心。
    public Bitmap mergeBitmaps(Bitmap logo, Bitmap qrcode) {

    Bitmap combined = Bitmap.createBitmap(qrcode.getWidth(), qrcode.getHeight(), qrcode.getConfig());
    Canvas canvas = new Canvas(combined);
    int canvasWidth = canvas.getWidth();
    int canvasHeight = canvas.getHeight();
    canvas.drawBitmap(qrcode, new Matrix(), null);

    Bitmap resizeLogo = Bitmap.createScaledBitmap(logo, canvasWidth / 5, canvasHeight / 5, true);
    int centreX = (canvasWidth - resizeLogo.getWidth()) /2;
    int centreY = (canvasHeight - resizeLogo.getHeight()) / 2;
    canvas.drawBitmap(resizeLogo, centreX, centreY, null);
    return combined;
}

然后,您可以使用该void合并QR码位图和徽标位图,并将其推送到您的图像视图中。
 Bitmap yourLogo = BitmapFactory.decodeResource(getResources(), R.drawable.your_logo);
 Bitmap merge = mergeBitmaps(yourLogo, qrcode_bitmap);
 yourImageView.setImageBitmap(merge);

1
最好将 resizeLogo 的尺寸从 /5 修改为 /6。 - Shrdi
1
/5 不起作用。但是,/6 在 Shrdi 上可以工作。 - Sambhav Khandelwal

5

关于在Android上生成带有Logo的二维码,您可以参考这篇指南和提供的源代码:Generating a qr code with a logo。以下是我使用的示例Android代码,可以实现类似的效果。

我相信这段代码可以进行优化,特别是关于使用Paint类来控制图像叠加透明度,但是这段代码在这方面已经很有效了。

    /**
 * Writes the given Overlay on a new Bitmap object.
 * @param Bitmap the Bitmap to overlay.
 * @return the new {@link Bitmap}-object.
 */ 
public static Bitmap overlayBitmap(Bitmap overlay) {        
    BitMatrix matrix = null;
    QRCodeWriter writer = new QRCodeWriter();

    //Error correction

    //Sometimes your QRCode will get damaged or covered up by something – like an image overlay for instance – 
    //therefore the designers of the QRCode has added four levels; 7% (L), 15 % (M), 25% (Q), 30% (H) of error 
    //correction were a error correction of level H should result in a QRCode that are still valid even when it’s 
    //30% obscured – for more info on error correction check this       

    Map<EncodeHintType,  Object> hints; 

    hints = new HashMap<EncodeHintType, Object>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);             

    //create qr code matrix
    writer = new  QRCodeWriter();
    try {
        matrix = writer.encode(redirectUrl, 
                                 BarcodeFormat.QR_CODE,
                                 QRCODE_IMAGE_WIDTH,
                                 QRCODE_IMAGE_HEIGHT,
                                 hints);
    } catch (WriterException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 

    Bitmap image = toBitmap(matrix);
    int height = image.getHeight();
    int width = image.getWidth();

    Bitmap combined = Bitmap.createBitmap(width, height, image.getConfig());

    Canvas canvas = new Canvas(combined);
    int canvasWidth = canvas.getWidth();
    int canvasHeight = canvas.getHeight();

    canvas.drawBitmap(image, new Matrix(), null);

    int centreX = (canvasWidth  - overlay.getWidth()) /2;
    int centreY = (canvasHeight - overlay.getHeight()) /2 ; 

    //https://dev59.com/WWfWa4cB1Zd3GeqPmPlr#12235235
    //https://dev59.com/AW435IYBdhLWcg3w9FBY#5119093        
    //Paint p = new Paint();
    //p.setXfermode(new PorterDuffXfermode(Mode.DST_ATOP)); //https://dev59.com/H3TYa4cB1Zd3GeqPskIM#17553502
    //p.setAlpha(180);
    //p.setARGB(a, r, g, b);

    //canvas.drawBitmap(bitmapToBeOverlay, 0, 0, p);        

    //canvas.drawBitmap(overlay, new Matrix(), null);
    canvas.drawBitmap(overlay, centreX, centreY, null);

    return combined;
}

    /**
 * Writes the given Matrix to a new colour Bitmap object.
 * @param matrix the matrix to write.
 * @param Color the Color to be added.
 * @return the new {@link Bitmap}-object.
 */
public static Bitmap toBitmapColour(BitMatrix matrix, int colour){
    int height = matrix.getHeight();
    int width = matrix.getWidth();
    Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
    for (int x = 0; x < width; x++){
        for (int y = 0; y < height; y++){
            bmp.setPixel(x, y, matrix.get(x,y) ? colour : Color.WHITE);
        }
    }
    return bmp;
}

HTH


复制粘贴图像不是一个好的选择。我尝试了您的代码,当我将图像粘贴到生成的 QR 码上方时,我的 QR 码变得混乱不堪。 - Sanjay Kumar
这不是一个好的解决方案,因为您总是需要手动检查 - 如果QR码在叠加图像后仍然有效。 - Alexander Farber
2
运行得非常好。至少在使用 Zxing 进行扫描时是这样的。记得将 ErrorCorrectionLevel 设置为 H。 - guy_m

5

QR码是一种快速响应码,您可以使用zxing制作QR码。但默认情况下,中心或其他部分没有公司标志。您可以创建一个QR码,并在其上绘制公司的标志图像


5
将它放在中央作为一个小图像,它应该可以正常工作。创建一个类似的图像,并扫描以检查是否可行。 - Girish Nair
@Stella:我试过用几个二维码扫描应用程序扫描,但似乎它不是标准的二维码,可能是一些自定义编码机制。 - Girish Nair

-1

您可以制作带有中心背景标志的QR码

首先使用以下代码创建QRCodeEncoder类:

public final class QRCodeEncoder {
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
private int dimension = Integer.MIN_VALUE;
private String contents = null;
private String displayContents = null;
private String title = null;
private BarcodeFormat format = null;
private boolean encoded = false;

public QRCodeEncoder(String data, Bundle bundle, String type,
        String format, int dimension) {
    this.dimension = dimension;
    encoded = encodeContents(data, bundle, type, format);
}

public String getContents() {
    return contents;
}

public String getDisplayContents() {
    return displayContents;
}

public String getTitle() {
    return title;
}

private boolean encodeContents(String data, Bundle bundle, String type,
        String formatString) {
    // Default to QR_CODE if no format given.
    format = null;
    if (formatString != null) {
        try {
            format = BarcodeFormat.valueOf(formatString);
        } catch (IllegalArgumentException iae) {
            // Ignore it then
        }
    }
    if (format == null || format == BarcodeFormat.QR_CODE) {
        this.format = BarcodeFormat.QR_CODE;
        encodeQRCodeContents(data, bundle, type);
    } else if (data != null && data.length() > 0) {
        contents = data;
        displayContents = data;
        title = "Text";
    }
    return contents != null && contents.length() > 0;
}

private void encodeQRCodeContents(String data, Bundle bundle, String type) {
    if (type.equals(Contents.Type.TEXT)) {
        if (data != null && data.length() > 0) {
            contents = data;
            displayContents = data;
            title = "Text";
        }
    } else if (type.equals(Contents.Type.EMAIL)) {
        data = trim(data);
        if (data != null) {
            contents = "mailto:" + data;
            displayContents = data;
            title = "E-Mail";
        }
    } else if (type.equals(Contents.Type.PHONE)) {
        data = trim(data);
        if (data != null) {
            contents = "tel:" + data;
            displayContents = PhoneNumberUtils.formatNumber(data);
            title = "Phone";
        }
    } else if (type.equals(Contents.Type.SMS)) {
        data = trim(data);
        if (data != null) {
            contents = "sms:" + data;
            displayContents = PhoneNumberUtils.formatNumber(data);
            title = "SMS";
        }
    } else if (type.equals(Contents.Type.CONTACT)) {
        if (bundle != null) {
            StringBuilder newContents = new StringBuilder(100);
            StringBuilder newDisplayContents = new StringBuilder(100);

            newContents.append("MECARD:");

            String name = trim(bundle
                    .getString(ContactsContract.Intents.Insert.NAME));
            if (name != null) {
                newContents.append("N:").append(escapeMECARD(name))
                        .append(';');
                newDisplayContents.append(name);
            }

            String address = trim(bundle
                    .getString(ContactsContract.Intents.Insert.POSTAL));
            if (address != null) {
                newContents.append("ADR:").append(escapeMECARD(address))
                        .append(';');
                newDisplayContents.append('\n').append(address);
            }

            Collection<String> uniquePhones = new HashSet<String>(
                    Contents.PHONE_KEYS.length);
            for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
                String phone = trim(bundle
                        .getString(Contents.PHONE_KEYS[x]));
                if (phone != null) {
                    uniquePhones.add(phone);
                }
            }
            for (String phone : uniquePhones) {
                newContents.append("TEL:").append(escapeMECARD(phone))
                        .append(';');
                newDisplayContents.append('\n').append(
                        PhoneNumberUtils.formatNumber(phone));
            }

            Collection<String> uniqueEmails = new HashSet<String>(
                    Contents.EMAIL_KEYS.length);
            for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
                String email = trim(bundle
                        .getString(Contents.EMAIL_KEYS[x]));
                if (email != null) {
                    uniqueEmails.add(email);
                }
            }
            for (String email : uniqueEmails) {
                newContents.append("EMAIL:").append(escapeMECARD(email))
                        .append(';');
                newDisplayContents.append('\n').append(email);
            }

            String url = trim(bundle.getString(Contents.URL_KEY));
            if (url != null) {
                // escapeMECARD(url) -> wrong escape e.g.
                // http\://zxing.google.com
                newContents.append("URL:").append(url).append(';');
                newDisplayContents.append('\n').append(url);
            }

            String note = trim(bundle.getString(Contents.NOTE_KEY));
            if (note != null) {
                newContents.append("NOTE:").append(escapeMECARD(note))
                        .append(';');
                newDisplayContents.append('\n').append(note);
            }

            // Make sure we've encoded at least one field.
            if (newDisplayContents.length() > 0) {
                newContents.append(';');
                contents = newContents.toString();
                displayContents = newDisplayContents.toString();
                title = "Contact";
            } else {
                contents = null;
                displayContents = null;
            }

        }
    } else if (type.equals(Contents.Type.LOCATION)) {
        if (bundle != null) {
            // These must use Bundle.getFloat(), not getDouble(), it's part
            // of the API.
            float latitude = bundle.getFloat("LAT", Float.MAX_VALUE);
            float longitude = bundle.getFloat("LONG", Float.MAX_VALUE);
            if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) {
                contents = "geo:" + latitude + ',' + longitude;
                displayContents = latitude + "," + longitude;
                title = "Location";
            }
        }
    }
}

public Bitmap encodeAsBitmap() throws WriterException {
    if (!encoded)
        return null;

    Hashtable hints = null;
    String encoding = guessAppropriateEncoding(contents);
    if (encoding != null) {
        hints = new Hashtable();
        hints.put(EncodeHintType.CHARACTER_SET, encoding);
    }
    MultiFormatWriter writer = new MultiFormatWriter();
    ByteMatrix result = writer.encode(contents, format, dimension,dimension, hints);
    int width = result.getWidth();
    int height = result.getHeight();
    int[] pixels = new int[width * height];
    // All are 0, or black, by default
    for (int y = 0; y < height; y++) {
        int offset = y * width;
        for (int x = 0; x < width; x++) {

            if (result.get(x, y) == 0) {
                pixels[offset + x] = BLACK;
            }       
        }
    }

    Bitmap bitmap = Bitmap.createBitmap(width, height,
            Bitmap.Config.ARGB_8888);
    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
    return bitmap;
}

private static String guessAppropriateEncoding(CharSequence contents) {
    // Very crude at the moment
    for (int i = 0; i < contents.length(); i++) {
        if (contents.charAt(i) > 0xFF) {
            return "UTF-8";
        }
    }
    return null;
}

private static String trim(String s) {
    if (s == null) {
        return null;
    }
    String result = s.trim();
    return result.length() == 0 ? null : result;
}

private static String escapeMECARD(String input) {
    if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) {
        return input;
    }
    int length = input.length();
    StringBuilder result = new StringBuilder(length);
    for (int i = 0; i < length; i++) {
        char c = input.charAt(i);
        if (c == ':' || c == ';') {
            result.append('\\');
        }
        result.append(c);
    }
    return result.toString();
}

}

然后在您想要使用图像生成QR码的活动中使用以下代码:

 private Bitmap generateQRCode(String encryptData) {
// here encryptData data will be your data
    WindowManager manager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
    Display display = manager.getDefaultDisplay();
    Point point = new Point();
    display.getSize(point);
    int width = point.x;
    int height = point.y;
    int smallerDimension = width < height ? width : height;
    smallerDimension = smallerDimension * 3 / 4;

    // Encode with a QR Code image
    QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(encryptData, null, Contents.Type.TEXT, BarcodeFormat.QR_CODE.toString(), smallerDimension);
    Bitmap bitmap = null;
    Bitmap bitMerged = null;
    try {
        bitmap = qrCodeEncoder.encodeAsBitmap();
        Bitmap myLogo = BitmapFactory.decodeResource(getResources(), R.drawable.pay365logo);
        bitMerged = mergeBitmaps(bitmap,myLogo);
    } catch (WriterException e) {
        e.printStackTrace();
    }

    return bitMerged;

}

public static Bitmap mergeBitmaps(Bitmap qrCode, Bitmap myLogo) {
    Bitmap bmOverlay = Bitmap.createBitmap(qrCode.getWidth(), qrCode.getHeight(), qrCode.getConfig());
    Canvas canvas = new Canvas(bmOverlay);
    canvas.drawBitmap(myLogo, (qrCode.getWidth() - myLogo.getWidth()) / 2, (qrCode.getHeight() - myLogo.getHeight()) / 2, null);
    canvas.drawBitmap(qrCode, new Matrix(), null);
    return bmOverlay;
}

它将会像这样: 它将会像这样


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接