How to Generate QR Code with Logo Inside on Android Using ZXing: A Complete Guide
QR codes have become an integral part of modern digital interaction, used for everything from sharing URLs and contact information to making payments. While standard QR codes are functional, adding a logo (e.g., a brand logo) can enhance brand recognition and make the QR code more visually appealing.
In this guide, we’ll walk you through generating a custom QR code with a logo using ZXing (Zebra Crossing), the most popular open-source library for barcode and QR code processing. We’ll cover everything from setting up dependencies to advanced customizations, ensuring even beginners can follow along.
Table of Contents#
- Prerequisites
- What is ZXing?
- Step 1: Add ZXing Dependencies
- Step 2: Generate a Basic QR Code
- Step 3: Add a Logo to the QR Code
- Troubleshooting Common Issues
- Advanced Customizations
- Conclusion
- References
Prerequisites#
Before starting, ensure you have:
- Android Studio (version 4.0+ recommended)
- Basic knowledge of Android development (Java or Kotlin)
- An Android device/emulator for testing
- A logo image (PNG/JPG, preferably with a transparent background for better results)
What is ZXing?#
ZXing (“Zebra Crossing”) is an open-source, multi-format 1D/2D barcode image processing library written in Java. It supports QR codes, UPC-A, EAN-13, and many other formats. For Android, ZXing provides core encoding/decoding logic, and community-maintained wrappers (like zxing-android-embedded) simplify integration.
Step 1: Add ZXing Dependencies#
To use ZXing in your Android project, add the following dependencies to your app/build.gradle file. We’ll use the official ZXing Core library for QR code generation and zxing-android-embedded for helper utilities (optional but recommended for easier integration).
For Gradle (Groovy)#
dependencies {
// ZXing Core (required for QR code encoding)
implementation 'com.google.zxing:core:3.5.1'
// Optional: ZXing Android Embedded (simplifies barcode scanning/encoding)
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
}For Gradle (Kotlin DSL)#
dependencies {
implementation("com.google.zxing:core:3.5.1")
implementation("com.journeyapps:zxing-android-embedded:4.3.0")
}Sync your project after adding dependencies.
Step 2: Generate a Basic QR Code (Without Logo)#
Before adding a logo, let’s first generate a standard QR code. We’ll use ZXing’s MultiFormatWriter to encode data into a QR code matrix, then convert that matrix into a Bitmap.
Step 2.1: Define QR Code Parameters#
First, define the content (e.g., a URL), size (in pixels), and error correction level (critical for logo integration later).
| Parameter | Description |
|---|---|
content | The data to encode (e.g., "https://example.com"). |
size | QR code dimensions (e.g., 500x500 pixels). |
errorCorrectionLevel | Resilience to damage (use H for logos, as it recovers 30% of data loss). |
Step 2.2: Encode Data into a QR Code Matrix#
Use MultiFormatWriter to convert the content into a BitMatrix (a 2D array representing QR code modules).
Kotlin Example:#
import com.google.zxing.BarcodeFormat
import com.google.zxing.WriterException
import com.google.zxing.common.BitMatrix
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
fun generateQrCodeMatrix(
content: String,
size: Int,
errorCorrectionLevel: ErrorCorrectionLevel = ErrorCorrectionLevel.H
): BitMatrix? {
return try {
val writer = QRCodeWriter()
writer.encode(
content,
BarcodeFormat.QR_CODE,
size,
size,
mapOf(
com.google.zxing.EncodeHintType.ERROR_CORRECTION to errorCorrectionLevel
)
)
} catch (e: WriterException) {
e.printStackTrace()
null
}
}Java Example:#
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 com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.util.HashMap;
import java.util.Map;
public BitMatrix generateQrCodeMatrix(String content, int size, ErrorCorrectionLevel errorCorrectionLevel) {
try {
QRCodeWriter writer = new QRCodeWriter();
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.ERROR_CORRECTION, errorCorrectionLevel);
return writer.encode(content, BarcodeFormat.QR_CODE, size, size, hints);
} catch (WriterException e) {
e.printStackTrace();
return null;
}
}Step 2.3: Convert BitMatrix to Bitmap#
The BitMatrix contains 0s (white modules) and 1s (black modules). Convert it to a Bitmap using a loop to draw pixels.
Kotlin Example:#
import android.graphics.Bitmap
import android.graphics.Color
import com.google.zxing.common.BitMatrix
fun convertMatrixToBitmap(matrix: BitMatrix): Bitmap {
val width = matrix.width
val height = matrix.height
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
for (x in 0 until width) {
for (y in 0 until height) {
bitmap.setPixel(x, y, if (matrix.get(x, y)) Color.BLACK else Color.WHITE)
}
}
return bitmap
}Java Example:#
import android.graphics.Bitmap;
import android.graphics.Color;
import com.google.zxing.common.BitMatrix;
public Bitmap convertMatrixToBitmap(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
bitmap.setPixel(x, y, matrix.get(x, y) ? Color.BLACK : Color.WHITE);
}
}
return bitmap;
}Step 2.4: Combine Steps to Generate a Basic QR Code#
Call the above functions to generate a Bitmap and display it in an ImageView.
Kotlin Example:#
val qrContent = "https://example.com"
val qrSize = 500 // pixels
val errorCorrectionLevel = ErrorCorrectionLevel.H
// Generate matrix
val matrix = generateQrCodeMatrix(qrContent, qrSize, errorCorrectionLevel)
// Convert to bitmap
val basicQrBitmap = matrix?.let { convertMatrixToBitmap(it) }
// Display in ImageView
imageView.setImageBitmap(basicQrBitmap)You now have a basic black-and-white QR code!
Step 3: Add a Logo to the QR Code#
To add a logo, overlay a smaller bitmap (your logo) onto the center of the QR code. Key considerations:
- Logo Size: Keep it ≤20% of the QR code size (e.g., 100x100px for a 500x500px QR code). Larger logos may break scannability.
- White Border: Add a small white border around the logo to separate it from QR modules (improves readability).
Step 3.1: Prepare the Logo Bitmap#
First, load your logo (from drawable or assets) and resize it to the desired size.
Kotlin Example (Resize Logo):#
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
fun resizeLogo(context: Context, logoResId: Int, targetSize: Int): Bitmap {
val originalLogo = BitmapFactory.decodeResource(context.resources, logoResId)
val matrix = Matrix()
val scaleFactor = targetSize.toFloat() / originalLogo.width.coerceAtMost(originalLogo.height)
matrix.postScale(scaleFactor, scaleFactor)
return Bitmap.createBitmap(originalLogo, 0, 0, originalLogo.width, originalLogo.height, matrix, false)
}Java Example (Resize Logo):#
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
public Bitmap resizeLogo(Context context, int logoResId, int targetSize) {
Bitmap originalLogo = BitmapFactory.decodeResource(context.getResources(), logoResId);
Matrix matrix = new Matrix();
float scaleFactor = (float) targetSize / Math.min(originalLogo.getWidth(), originalLogo.getHeight());
matrix.postScale(scaleFactor, scaleFactor);
return Bitmap.createBitmap(originalLogo, 0, 0, originalLogo.getWidth(), originalLogo.getHeight(), matrix, false);
}Step 3.2: Overlay Logo on QR Code#
Use a Canvas to draw the QR code bitmap, then overlay the resized logo in the center. Add a white border to the logo for contrast.
Kotlin Example (Overlay Logo):#
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
fun addLogoToQrCode(qrBitmap: Bitmap, logoBitmap: Bitmap, borderSize: Int = 5): Bitmap {
val qrWidth = qrBitmap.width
val qrHeight = qrBitmap.height
val logoWidth = logoBitmap.width
val logoHeight = logoBitmap.height
// Create a new bitmap to draw QR + logo
val combinedBitmap = Bitmap.createBitmap(qrWidth, qrHeight, qrBitmap.config)
val canvas = Canvas(combinedBitmap)
// Draw the original QR code
canvas.drawBitmap(qrBitmap, 0f, 0f, null)
// Calculate logo position (center)
val logoX = (qrWidth - logoWidth) / 2f
val logoY = (qrHeight - logoHeight) / 2f
// Draw white border around logo (optional but recommended)
val borderPaint = Paint()
borderPaint.color = android.graphics.Color.WHITE
canvas.drawRect(
logoX - borderSize,
logoY - borderSize,
logoX + logoWidth + borderSize,
logoY + logoHeight + borderSize,
borderPaint
)
// Draw the logo on top
canvas.drawBitmap(logoBitmap, logoX, logoY, null)
return combinedBitmap
}Java Example (Overlay Logo):#
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
public Bitmap addLogoToQrCode(Bitmap qrBitmap, Bitmap logoBitmap, int borderSize) {
int qrWidth = qrBitmap.getWidth();
int qrHeight = qrBitmap.getHeight();
int logoWidth = logoBitmap.getWidth();
int logoHeight = logoBitmap.getHeight();
Bitmap combinedBitmap = Bitmap.createBitmap(qrWidth, qrHeight, qrBitmap.getConfig());
Canvas canvas = new Canvas(combinedBitmap);
// Draw QR code
canvas.drawBitmap(qrBitmap, 0f, 0f, null);
// Calculate logo position (center)
float logoX = (qrWidth - logoWidth) / 2f;
float logoY = (qrHeight - logoHeight) / 2f;
// Draw white border
Paint borderPaint = new Paint();
borderPaint.setColor(android.graphics.Color.WHITE);
canvas.drawRect(
logoX - borderSize,
logoY - borderSize,
logoX + logoWidth + borderSize,
logoY + logoHeight + borderSize,
borderPaint
);
// Draw logo
canvas.drawBitmap(logoBitmap, logoX, logoY, null);
return combinedBitmap;
}Step 3.3: Combine All Steps#
Put it all together to generate a QR code with a logo:
Kotlin Example (Full Workflow):#
// 1. Generate basic QR code matrix
val qrContent = "https://example.com"
val qrSize = 500 // 500x500 pixels
val matrix = generateQrCodeMatrix(qrContent, qrSize, ErrorCorrectionLevel.H) ?: return
// 2. Convert matrix to bitmap
val basicQrBitmap = convertMatrixToBitmap(matrix)
// 3. Resize logo (20% of QR size: 500 * 0.2 = 100)
val logoSize = (qrSize * 0.2).toInt() // 100 pixels
val resizedLogo = resizeLogo(context, R.drawable.your_logo, logoSize)
// 4. Overlay logo with border
val finalQrBitmap = addLogoToQrCode(basicQrBitmap, resizedLogo, borderSize = 5)
// 5. Display in ImageView
imageView.setImageBitmap(finalQrBitmap)Troubleshooting Common Issues#
1. QR Code Not Scanning#
- Cause: Logo too large, low error correction level, or poor contrast.
- Fix: Use
ErrorCorrectionLevel.H, reduce logo size to ≤20% of QR size, or add a white border.
2. Logo Appears Distorted#
- Cause: Incorrect resizing logic (e.g., stretching instead of scaling proportionally).
- Fix: Use
Matrix.postScale()with equal x/y scaling factors (as in Step 3.1).
3. Dependency Conflicts#
- Cause: Outdated ZXing versions or conflicting libraries.
- Fix: Use the latest ZXing Core (
3.5.1+) andzxing-android-embedded(4.3.0+).
Advanced Customizations#
Change QR Code Colors#
Customize foreground (QR modules) and background colors by modifying the convertMatrixToBitmap function:
// Kotlin example: Red foreground, white background
fun convertMatrixToBitmap(matrix: BitMatrix, fgColor: Int = Color.RED, bgColor: Int = Color.WHITE): Bitmap {
val width = matrix.width
val height = matrix.height
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
for (x in 0 until width) {
for (y in 0 until height) {
bitmap.setPixel(x, y, if (matrix.get(x, y)) fgColor else bgColor)
}
}
return bitmap
}Rounded QR Code Corners#
Use a Paint with setCornerRadius to round module corners (requires more advanced bitmap manipulation or libraries like QRCodeGenerator).
Add Text Below the QR Code#
Draw text using Canvas.drawText() after rendering the QR code and logo:
val textPaint = Paint().apply {
color = Color.BLACK
textSize = 40f // Adjust size
textAlign = Paint.Align.CENTER
}
canvas.drawText("Scan to Visit Example.com", qrWidth/2f, qrHeight + 50f, textPaint)Conclusion#
Generating a QR code with a logo on Android using ZXing involves three core steps:
- Encode content into a QR matrix with high error correction.
- Convert the matrix to a bitmap.
- Overlay a resized logo (with optional border) onto the QR code.
With ZXing’s flexibility, you can further customize colors, add text, or experiment with advanced styles. Always test your QR code with multiple scanners (e.g., Google Lens, QR Code Reader) to ensure scannability!