Core barcode encoding/decoding library supporting 17 formats including QR Code, Data Matrix, Aztec, PDF 417, and various 1D barcodes
—
Complete QR Code encoding and decoding support with configurable error correction levels (L, M, Q, H), encoding modes (numeric, alphanumeric, byte, kanji), and versions 1-40. QR Codes are the most widely used 2D barcode format, supporting up to 7,089 numeric characters with excellent error correction capabilities.
Reader implementation for detecting and decoding QR Codes from binary bitmap images. Supports both standard detection with finder patterns and fast pure barcode extraction for clean images.
/**
* Reader implementation for QR Code 2D barcodes.
* Locates and decodes QR codes in images using finder pattern detection
* or pure barcode extraction for clean images.
*/
public class QRCodeReader implements Reader {
/**
* Creates a new QR Code reader.
*/
public QRCodeReader();
/**
* Locates and decodes a QR code in an image.
*
* @param image Binary bitmap representation of the image
* @return Result containing decoded text and metadata
* @throws NotFoundException If a QR code cannot be found in the image
* @throws ChecksumException If error correction fails
* @throws FormatException If a QR code cannot be decoded
*/
@Override
public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException;
/**
* Locates and decodes a QR code in an image with configuration hints.
*
* @param image Binary bitmap representation of the image
* @param hints Map of DecodeHintType to configuration values
* - PURE_BARCODE (Boolean): Use fast pure barcode extraction
* - CHARACTER_SET (String): Expected character encoding
* - TRY_HARDER (Boolean): Spend more time for better accuracy
* @return Result containing decoded text and metadata
* @throws NotFoundException If a QR code cannot be found in the image
* @throws ChecksumException If error correction fails
* @throws FormatException If a QR code cannot be decoded
*/
@Override
public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)
throws NotFoundException, ChecksumException, FormatException;
/**
* Resets any internal state. Should be called between decoding attempts.
*/
@Override
public void reset();
}Usage Example:
import com.google.zxing.*;
import com.google.zxing.common.*;
import com.google.zxing.qrcode.*;
import java.util.*;
// Create luminance source from image pixels
int[] pixels = ...; // RGB int array
LuminanceSource source = new RGBLuminanceSource(width, height, pixels);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
// Decode QR code
Reader reader = new QRCodeReader();
Result result = reader.decode(bitmap);
// Access decoded data
String text = result.getText();
byte[] rawBytes = result.getRawBytes();
ResultPoint[] corners = result.getResultPoints();
// Decode with hints for pure barcode
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result result2 = reader.decode(bitmap, hints);Writer implementation for encoding QR Codes. Generates a BitMatrix representation that can be rendered to an image with configurable error correction and quiet zone margins.
/**
* Writer implementation for QR Code 2D barcodes.
* Encodes text into QR Code BitMatrix with configurable error correction
* and margin settings.
*/
public final class QRCodeWriter implements Writer {
/**
* Creates a new QR Code writer.
*/
public QRCodeWriter();
/**
* Encodes contents into a QR Code BitMatrix with default settings.
* Uses error correction level L and 4-module quiet zone.
*
* @param contents String content to encode
* @param format Must be BarcodeFormat.QR_CODE
* @param width Preferred width in pixels
* @param height Preferred height in pixels
* @return BitMatrix representation of the QR code
* @throws WriterException If encoding fails
* @throws IllegalArgumentException If contents is empty or format is not QR_CODE
*/
@Override
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
throws WriterException;
/**
* Encodes contents into a QR Code BitMatrix with configuration hints.
*
* @param contents String content to encode (cannot be empty)
* @param format Must be BarcodeFormat.QR_CODE
* @param width Preferred width in pixels (must be non-negative)
* @param height Preferred height in pixels (must be non-negative)
* @param hints Map of EncodeHintType to configuration values
* - ERROR_CORRECTION (ErrorCorrectionLevel): L, M, Q, or H (default: L)
* - MARGIN (Integer): Quiet zone size in modules (default: 4)
* - CHARACTER_SET (String): Character encoding (e.g., "UTF-8")
* - QR_VERSION (Integer): Exact QR version 1-40 (auto-selected if not set)
* - QR_MASK_PATTERN (Integer): Mask pattern 0-7 (auto-selected if not set)
* @return BitMatrix representation of the QR code
* @throws WriterException If encoding fails
* @throws IllegalArgumentException If parameters are invalid
*/
@Override
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
Map<EncodeHintType,?> hints) throws WriterException;
/**
* Renders a QRCode object as a BitMatrix with scaling.
* Static utility method for advanced use cases.
*
* @param code QRCode object to render (must have a matrix)
* @param width Desired width in pixels
* @param height Desired height in pixels
* @param quietZone Quiet zone size in modules
* @return BitMatrix representation scaled to requested dimensions
* @throws IllegalStateException If code does not have a matrix
* @throws NullPointerException If code is null
*/
public static BitMatrix renderResult(QRCode code, int width, int height, int quietZone);
}Usage Example:
import com.google.zxing.*;
import com.google.zxing.common.*;
import com.google.zxing.qrcode.*;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.util.*;
// Encode with default settings
Writer writer = new QRCodeWriter();
BitMatrix matrix = writer.encode(
"https://example.com",
BarcodeFormat.QR_CODE,
300,
300
);
// Encode with high error correction and custom margin
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 1); // 1 module quiet zone instead of default 4
BitMatrix matrix2 = writer.encode(
"Hello, QR Code!",
BarcodeFormat.QR_CODE,
400,
400,
hints
);
// Convert BitMatrix to image pixels
int width = matrix2.getWidth();
int height = matrix2.getHeight();
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
pixels[y * width + x] = matrix2.get(x, y) ? 0xFF000000 : 0xFFFFFFFF;
}
}QR Code error correction levels defining the amount of redundancy for error recovery. Higher levels allow more damage to the barcode while still being readable, but reduce data capacity.
/**
* QR Code error correction levels as defined by ISO 18004:2006, 6.5.1.
* Each level provides different data recovery capabilities at the cost
* of reduced data capacity.
*/
public enum ErrorCorrectionLevel {
/**
* Error correction level L: ~7% of codewords can be restored.
* Lowest error correction, highest data capacity.
*/
L,
/**
* Error correction level M: ~15% of codewords can be restored.
* Medium-low error correction (default for most use cases).
*/
M,
/**
* Error correction level Q: ~25% of codewords can be restored.
* Medium-high error correction.
*/
Q,
/**
* Error correction level H: ~30% of codewords can be restored.
* Highest error correction, lowest data capacity.
*/
H;
/**
* Gets the 2-bit encoding value for this error correction level.
*
* @return Integer bits value used in QR code format information
*/
public int getBits();
/**
* Decodes error correction level from format information bits.
*
* @param bits Integer containing the two bits encoding the level
* @return ErrorCorrectionLevel corresponding to the bits
* @throws IllegalArgumentException If bits are invalid
*/
public static ErrorCorrectionLevel forBits(int bits);
}Usage Example:
import com.google.zxing.*;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.util.*;
// Use highest error correction for damaged or small QR codes
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
BitMatrix matrix = writer.encode("Important data", BarcodeFormat.QR_CODE,
300, 300, hints);
// Use low error correction for maximum data capacity
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
BitMatrix matrix2 = writer.encode("Long text...", BarcodeFormat.QR_CODE,
400, 400, hints);QR Code encoding modes defining how data is encoded into the barcode. Different modes optimize for different character sets, providing better compression for specific data types.
/**
* QR Code data encoding modes as defined by ISO 18004:2006, 6.4.1.
* Each mode encodes different character sets with varying efficiency.
*/
public enum Mode {
/**
* End of message terminator (not a real encoding mode).
*/
TERMINATOR,
/**
* Numeric mode: encodes decimal digits 0-9.
* Most efficient for numeric-only data (3.3 bits per digit).
*/
NUMERIC,
/**
* Alphanumeric mode: encodes digits, uppercase A-Z, space, and symbols $ % * + - . / :
* Efficient for uppercase alphanumeric data (5.5 bits per character).
*/
ALPHANUMERIC,
/**
* Structured append mode: combines multiple QR codes into a sequence.
* Not commonly used in most applications.
*/
STRUCTURED_APPEND,
/**
* Byte mode: encodes raw 8-bit bytes.
* Used for binary data, lowercase letters, and Unicode (8 bits per byte).
*/
BYTE,
/**
* Extended Channel Interpretation mode: specifies character set.
* Used to indicate non-default character encodings.
*/
ECI,
/**
* Kanji mode: encodes Japanese Kanji characters.
* Efficient for Shift JIS Japanese text (13 bits per character).
*/
KANJI,
/**
* FNC1 first position: GS1 standard indicator.
* Marks barcode as containing GS1 Application Identifier data.
*/
FNC1_FIRST_POSITION,
/**
* FNC1 second position: Application-specific indicator.
* Marks barcode as containing application-specific data.
*/
FNC1_SECOND_POSITION,
/**
* Hanzi mode: encodes GB18030 Chinese characters.
* Efficient for simplified Chinese text (13 bits per character).
*/
HANZI;
/**
* Gets the 4-bit encoding value for this mode.
*
* @return Integer bits value used in QR code mode indicator
*/
public int getBits();
/**
* Decodes mode from mode indicator bits.
*
* @param bits Four bits encoding a QR Code data mode
* @return Mode corresponding to the bits
* @throws IllegalArgumentException If bits do not correspond to a known mode
*/
public static Mode forBits(int bits);
/**
* Gets the number of bits used to encode character count for this mode.
*
* @param version QR Code version (1-40)
* @return Number of bits used for character count field
*/
public int getCharacterCountBits(Version version);
}Usage Example:
// Modes are typically selected automatically by the encoder
// based on input data characteristics
// Numeric data: "12345" -> NUMERIC mode (most efficient)
BitMatrix numericQR = writer.encode("12345", BarcodeFormat.QR_CODE, 300, 300);
// Alphanumeric data: "ABC-123" -> ALPHANUMERIC mode
BitMatrix alphaQR = writer.encode("ABC-123", BarcodeFormat.QR_CODE, 300, 300);
// Mixed case or Unicode: "Hello, World!" -> BYTE mode
BitMatrix byteQR = writer.encode("Hello, World!", BarcodeFormat.QR_CODE, 300, 300);
// The encoder automatically selects the most efficient mode(s)
// and can switch between modes within a single QR codeQR Code version information representing the size and capacity of the barcode. Versions range from 1 (21x21 modules) to 40 (177x177 modules), with each version supporting different data capacities based on error correction level.
/**
* QR Code version information as defined by ISO 18004:2006 Annex D.
* Versions 1-40 define the size and capacity of QR codes.
* Version N is (17 + 4*N) x (17 + 4*N) modules.
*/
public final class Version {
/**
* Gets the QR Code version number (1-40).
*
* @return Version number
*/
public int getVersionNumber();
/**
* Gets alignment pattern center coordinates for this version.
*
* @return Array of alignment pattern center positions in modules
*/
public int[] getAlignmentPatternCenters();
/**
* Gets the total number of data codewords in this version.
*
* @return Total codewords across all blocks
*/
public int getTotalCodewords();
/**
* Gets the dimension (width and height) for this version.
*
* @return Dimension in modules (17 + 4 * versionNumber)
*/
public int getDimensionForVersion();
/**
* Gets error correction block configuration for the specified level.
*
* @param ecLevel Error correction level (L, M, Q, or H)
* @return ECBlocks containing block structure for this version and level
*/
public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel);
/**
* Gets the Version for a specific version number.
*
* @param versionNumber Version number (1-40)
* @return Version object for the specified number
* @throws IllegalArgumentException If version number is outside 1-40 range
*/
public static Version getVersionForNumber(int versionNumber);
/**
* Deduces version information from QR Code dimensions.
*
* @param dimension Dimension in modules
* @return Version for a QR Code of that dimension
* @throws FormatException If dimension is invalid (not 1 mod 4)
*/
public static Version getProvisionalVersionForDimension(int dimension) throws FormatException;
/**
* Decodes version information from version bits.
* Used for versions 7 and higher which encode version in the barcode.
*
* @param versionBits Integer containing version information bits
* @return Version object, or null if decoding fails
*/
static Version decodeVersionInformation(int versionBits);
/**
* Nested class: Error correction block configuration.
* Encapsulates EC block structure for a version/level combination.
*/
public static final class ECBlocks {
/**
* Gets the number of error correction codewords per block.
*
* @return EC codewords per block
*/
public int getECCodewordsPerBlock();
/**
* Gets the total number of error correction blocks.
*
* @return Total number of blocks
*/
public int getNumBlocks();
/**
* Gets the total number of error correction codewords.
*
* @return Total EC codewords across all blocks
*/
public int getTotalECCodewords();
/**
* Gets the array of error correction block structures.
*
* @return Array of ECB objects defining block structure
*/
public ECB[] getECBlocks();
}
/**
* Nested class: Individual error correction block parameters.
* Defines count and data codewords for a block group.
*/
public static final class ECB {
/**
* Gets the number of blocks with this structure.
*
* @return Block count
*/
public int getCount();
/**
* Gets the number of data codewords per block.
*
* @return Data codewords per block
*/
public int getDataCodewords();
}
}Usage Example:
import com.google.zxing.*;
import com.google.zxing.qrcode.decoder.*;
import java.util.*;
// Explicitly specify QR Code version (1-40)
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.QR_VERSION, 5); // Force version 5 (37x37 modules)
BitMatrix matrix = writer.encode("Data", BarcodeFormat.QR_CODE, 200, 200, hints);
// Query version information
Version version = Version.getVersionForNumber(10);
int dimension = version.getDimensionForVersion(); // 57 modules (17 + 4*10)
int[] alignmentCenters = version.getAlignmentPatternCenters();
int totalCodewords = version.getTotalCodewords();
// Get error correction block structure
Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ErrorCorrectionLevel.M);
int ecCodewords = ecBlocks.getECCodewordsPerBlock();
int numBlocks = ecBlocks.getNumBlocks();
// Usually version is auto-selected by the encoder
// based on data size and error correction level
BitMatrix autoMatrix = writer.encode("Long text content...",
BarcodeFormat.QR_CODE, 400, 400);Data capacity varies by version and error correction level:
Version 1 (21x21 modules):
Version 10 (57x57 modules):
Version 40 (177x177 modules):
QR Codes support splitting data across multiple barcodes:
// Decoded result will contain structured append metadata
Result result = reader.decode(bitmap);
Map<ResultMetadataType, Object> metadata = result.getResultMetadata();
if (metadata.containsKey(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) {
int sequence = (Integer) metadata.get(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE);
int parity = (Integer) metadata.get(ResultMetadataType.STRUCTURED_APPEND_PARITY);
// Handle multi-QR sequence
}Decoded QR Codes include error correction information:
Result result = reader.decode(bitmap);
Map<ResultMetadataType, Object> metadata = result.getResultMetadata();
String ecLevel = (String) metadata.get(ResultMetadataType.ERROR_CORRECTION_LEVEL);
Integer errorsCorrected = (Integer) metadata.get(ResultMetadataType.ERRORS_CORRECTED);
System.out.println("Error correction level: " + ecLevel);
System.out.println("Errors corrected: " + errorsCorrected);Advanced QR Code encoder providing direct access to encoding operations without using the Writer interface. Useful for custom encoding workflows and accessing intermediate encoding results.
/**
* QR Code encoder with static methods for direct encoding.
* Provides fine-grained control over the encoding process.
*/
public final class Encoder {
/**
* Encodes content into a QRCode object with specified error correction.
*
* @param content String content to encode
* @param ecLevel Error correction level (L, M, Q, or H)
* @return QRCode object containing encoded matrix and metadata
* @throws WriterException If encoding fails
*/
public static QRCode encode(String content, ErrorCorrectionLevel ecLevel)
throws WriterException;
/**
* Encodes content into a QRCode object with configuration hints.
*
* @param content String content to encode
* @param ecLevel Error correction level
* @param hints Map of EncodeHintType to configuration values
* - CHARACTER_SET (String): Character encoding
* - QR_VERSION (Integer): Specific version (1-40)
* - QR_MASK_PATTERN (Integer): Specific mask pattern (0-7)
* - QR_COMPACT (Boolean): Enable compact mode
* - GS1_FORMAT (Boolean): Use GS1 encoding
* @return QRCode object containing encoded matrix and metadata
* @throws WriterException If encoding fails
*/
public static QRCode encode(String content, ErrorCorrectionLevel ecLevel,
Map<EncodeHintType,?> hints)
throws WriterException;
/**
* Chooses the optimal encoding mode for the given content.
*
* @param content String content to analyze
* @return Mode that provides best compression for the content
*/
public static Mode chooseMode(String content);
}Usage Example:
import com.google.zxing.*;
import com.google.zxing.qrcode.decoder.*;
import com.google.zxing.qrcode.encoder.*;
import java.util.*;
// Direct encoding with Encoder class
QRCode qrCode = Encoder.encode("Hello, World!", ErrorCorrectionLevel.M);
// Access encoded structure
ByteMatrix matrix = qrCode.getMatrix();
Version version = qrCode.getVersion();
int maskPattern = qrCode.getMaskPattern();
Mode mode = qrCode.getMode();
System.out.println("QR Code Version: " + version.getVersionNumber());
System.out.println("Mask Pattern: " + maskPattern);
System.out.println("Encoding Mode: " + mode);
System.out.println("Dimensions: " + matrix.getWidth() + "x" + matrix.getHeight());
// Encode with specific hints
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.QR_VERSION, 5);
hints.put(EncodeHintType.QR_MASK_PATTERN, 3);
QRCode customQR = Encoder.encode("Custom data", ErrorCorrectionLevel.H, hints);
// Analyze optimal mode for content
Mode numericMode = Encoder.chooseMode("12345"); // Returns NUMERIC
Mode alphaMode = Encoder.chooseMode("ABC-123"); // Returns ALPHANUMERIC
Mode byteMode = Encoder.chooseMode("Hello, World!"); // Returns BYTERepresents an encoded QR Code with access to the matrix and encoding parameters. Used as the output of the Encoder class, providing programmatic access to the encoded structure.
/**
* Represents an encoded QR Code structure with matrix and metadata.
* Provides access to encoding parameters and the encoded bit matrix.
*/
public final class QRCode {
/**
* Number of available mask patterns (0-7).
*/
public static final int NUM_MASK_PATTERNS = 8;
/**
* Creates a new QRCode instance.
*/
public QRCode();
/**
* Gets the encoding mode used.
*
* @return Mode used for encoding (NUMERIC, ALPHANUMERIC, BYTE, etc.)
*/
public Mode getMode();
/**
* Sets the encoding mode.
*
* @param value Mode to set
*/
public void setMode(Mode value);
/**
* Gets the error correction level.
*
* @return ErrorCorrectionLevel (L, M, Q, or H)
*/
public ErrorCorrectionLevel getECLevel();
/**
* Sets the error correction level.
*
* @param value Error correction level to set
*/
public void setECLevel(ErrorCorrectionLevel value);
/**
* Gets the QR Code version.
*
* @return Version object (versions 1-40)
*/
public Version getVersion();
/**
* Sets the QR Code version.
*
* @param version Version to set
*/
public void setVersion(Version version);
/**
* Gets the mask pattern used (0-7).
*
* @return Mask pattern number
*/
public int getMaskPattern();
/**
* Sets the mask pattern.
*
* @param value Mask pattern number (0-7)
*/
public void setMaskPattern(int value);
/**
* Gets the encoded matrix.
*
* @return ByteMatrix containing the encoded QR Code
*/
public ByteMatrix getMatrix();
/**
* Sets the encoded matrix.
*
* @param value ByteMatrix to set
*/
public void setMatrix(ByteMatrix value);
}Usage Example:
import com.google.zxing.qrcode.encoder.*;
import com.google.zxing.qrcode.decoder.*;
// Create and configure QRCode manually
QRCode qrCode = new QRCode();
qrCode.setMode(Mode.BYTE);
qrCode.setECLevel(ErrorCorrectionLevel.M);
qrCode.setVersion(Version.getVersionForNumber(5));
qrCode.setMaskPattern(3);
// Or get from Encoder
QRCode encoded = Encoder.encode("Data", ErrorCorrectionLevel.H);
// Inspect encoding details
System.out.println("Mode: " + encoded.getMode());
System.out.println("EC Level: " + encoded.getECLevel());
System.out.println("Version: " + encoded.getVersion().getVersionNumber());
System.out.println("Mask: " + encoded.getMaskPattern());
ByteMatrix matrix = encoded.getMatrix();
System.out.println("Size: " + matrix.getWidth() + "x" + matrix.getHeight());
// Access individual modules
for (int y = 0; y < matrix.getHeight(); y++) {
for (int x = 0; x < matrix.getWidth(); x++) {
byte value = matrix.get(x, y);
// Process module value (0 = white, 1 = black)
}
}Represents a 2D matrix of bytes for QR Code encoding. Used internally by the encoder to represent the QR Code before conversion to BitMatrix.
/**
* 2D matrix of bytes representing QR Code modules.
* Similar to BitMatrix but using bytes for intermediate encoding.
*/
public final class ByteMatrix {
/**
* Creates a ByteMatrix with specified dimensions.
*
* @param width Matrix width in modules
* @param height Matrix height in modules
*/
public ByteMatrix(int width, int height);
/**
* Gets the width of the matrix.
*
* @return Width in modules
*/
public int getWidth();
/**
* Gets the height of the matrix.
*
* @return Height in modules
*/
public int getHeight();
/**
* Gets the value at a specific position.
*
* @param x X coordinate
* @param y Y coordinate
* @return Byte value at position
*/
public byte get(int x, int y);
/**
* Gets the underlying 2D byte array.
*
* @return 2D byte array [height][width]
*/
public byte[][] getArray();
/**
* Sets the value at a specific position.
*
* @param x X coordinate
* @param y Y coordinate
* @param value Byte value to set
*/
public void set(int x, int y, byte value);
/**
* Sets the value at a specific position using int.
*
* @param x X coordinate
* @param y Y coordinate
* @param value Integer value to set (cast to byte)
*/
public void set(int x, int y, int value);
/**
* Clears the matrix, setting all values to the specified byte.
*
* @param value Byte value to fill matrix with
*/
public void clear(byte value);
}Error Correction Selection:
Version Selection:
Encoding Optimization:
Advanced Encoding:
Encoder class for direct access to encoding resultsQRCode class to inspect encoding parameters