Core barcode encoding/decoding library supporting 17 formats including QR Code, Data Matrix, Aztec, PDF 417, and various 1D barcodes
—
Shared utility classes including character set handling (ECI), geometric transformations, grid sampling, string encoding detection, and barcode detection utilities. These utilities support the core barcode processing pipeline and provide essential functionality used across all format implementations.
Extended Channel Interpretation enum for character set encoding. Maps ECI values to Java Charset objects for proper text decoding.
/**
* Extended Channel Interpretation for character set encoding.
* Maps ECI values (as encoded in barcodes) to Java Charset objects.
* Supports wide range of character encodings including UTF, ISO-8859, Shift_JIS, etc.
*/
public enum CharacterSetECI {
// Common encodings
Cp437(new int[]{0, 2}),
ISO8859_1(new int[]{1, 3}),
ISO8859_2(4),
ISO8859_3(5),
ISO8859_4(6),
ISO8859_5(7),
ISO8859_6(8),
ISO8859_7(9),
ISO8859_8(10),
ISO8859_9(11),
ISO8859_10(12),
ISO8859_11(13),
ISO8859_13(15),
ISO8859_14(16),
ISO8859_15(17),
ISO8859_16(18),
Shift_JIS(20),
Cp1250(21),
Cp1251(22),
Cp1252(23),
Cp1256(24),
UnicodeBigUnmarked(25),
UTF16BE(25),
UTF8(26),
ASCII(new int[]{27, 170}),
Big5(28),
GB18030(29),
EUC_KR(30),
// And many more...
/**
* Gets the Java Charset for this ECI.
*
* @return Charset object
*/
public Charset getCharset();
/**
* Gets the ECI value (as encoded in barcodes).
*
* @return ECI value
*/
public int getValue();
/**
* Gets CharacterSetECI from ECI value.
*
* @param value ECI value from barcode
* @return CharacterSetECI enum constant
* @throws FormatException If value is invalid
*/
public static CharacterSetECI getCharacterSetECIByValue(int value) throws FormatException;
/**
* Gets CharacterSetECI from charset name.
*
* @param name Charset name (e.g., "UTF-8", "ISO-8859-1")
* @return CharacterSetECI enum constant or null if not found
*/
public static CharacterSetECI getCharacterSetECIByName(String name);
}Usage Example:
import com.google.zxing.common.CharacterSetECI;
import java.nio.charset.Charset;
// From ECI value in barcode metadata
int eciValue = 26; // UTF-8
CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByValue(eciValue);
Charset charset = eci.getCharset();
// Decode bytes with correct charset
byte[] rawBytes = result.getRawBytes();
String text = new String(rawBytes, charset);
// From charset name
CharacterSetECI utf8 = CharacterSetECI.getCharacterSetECIByName("UTF-8");
int eciValue2 = utf8.getValue(); // 26Set of CharsetEncoders for encoding strings with multiple character sets. Automatically selects the most efficient encoders for a given input string, supporting ECI switching for optimal barcode size.
/**
* Set of CharsetEncoders for encoding strings with ECI support.
* Intelligently selects character set encoders based on input string content,
* enabling efficient multi-encoding barcode generation.
*/
public final class ECIEncoderSet {
/**
* Constructs an encoder set for a string.
*
* @param stringToEncode String that needs to be encoded
* @param priorityCharset Preferred Charset or null for automatic selection
* @param fnc1 FNC1 character position or -1 for non-GS1 barcodes
*/
public ECIEncoderSet(String stringToEncode, Charset priorityCharset, int fnc1);
/**
* Gets the number of encoders in this set.
*
* @return Number of available encoders
*/
public int length();
/**
* Gets the charset name for the encoder at specified index.
*
* @param index Encoder index
* @return Charset name (e.g., "UTF-8", "ISO-8859-1")
*/
public String getCharsetName(int index);
/**
* Gets the Charset for the encoder at specified index.
*
* @param index Encoder index
* @return Charset object
*/
public Charset getCharset(int index);
/**
* Gets the ECI value for the encoder at specified index.
*
* @param index Encoder index
* @return ECI value for use in barcode
*/
public int getECIValue(int index);
/**
* Determines which encoder can encode a character.
*
* @param c Character to test
* @return Encoder index that can encode the character
*/
public int encode(char c);
/**
* Tests if a character can be encoded by the encoder at specified index.
*
* @param c Character to test
* @param encoderIndex Encoder index
* @return true if the encoder can encode the character
*/
public boolean canEncode(char c, int encoderIndex);
}Usage Example:
import com.google.zxing.common.ECIEncoderSet;
import java.nio.charset.StandardCharsets;
// Create encoder set for mixed-language text
String text = "Hello 世界"; // English + Chinese
ECIEncoderSet encoders = new ECIEncoderSet(text, StandardCharsets.UTF_8, -1);
// Iterate through string and select encoders
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
int encoderIndex = encoders.encode(c);
String charsetName = encoders.getCharsetName(encoderIndex);
int eciValue = encoders.getECIValue(encoderIndex);
// Use encoder info to build barcode with ECI switches
System.out.println("Char '" + c + "' -> " + charsetName + " (ECI " + eciValue + ")");
}Builder for decoding byte sequences with ECI character set switches. Handles mixed-encoding barcode data by switching character sets at ECI markers.
/**
* String builder that handles ECI character set switching.
* Decodes byte sequences where character encoding changes at ECI markers.
*/
public final class ECIStringBuilder {
/**
* Creates an ECIStringBuilder with default capacity.
*/
public ECIStringBuilder();
/**
* Creates an ECIStringBuilder with specified capacity.
*
* @param initialCapacity Initial capacity in bytes
*/
public ECIStringBuilder(int initialCapacity);
/**
* Appends a byte value.
*
* @param value Byte to append (as char, lowest byte used)
*/
public void append(char value);
/**
* Appends a byte value.
*
* @param value Byte to append
*/
public void append(byte value);
/**
* Appends a string as bytes.
*
* @param value String whose characters are appended as bytes
*/
public void append(String value);
/**
* Appends an integer as a string.
*
* @param value Integer to append as string representation
*/
public void append(int value);
/**
* Switches to a new character set encoding.
*
* @param value ECI value specifying new character set
* @throws FormatException If ECI value is invalid
*/
public void appendECI(int value) throws FormatException;
/**
* Builds the final decoded string.
*
* @return Decoded string with proper character encoding
*/
public String toString();
/**
* Gets the number of accumulated bytes.
*
* @return Byte count
*/
public int length();
}Usage Example:
import com.google.zxing.common.ECIStringBuilder;
// Decode barcode with ECI switches
ECIStringBuilder builder = new ECIStringBuilder();
// Read bytes in ISO-8859-1 (default)
builder.append((byte)0x48); // 'H'
builder.append((byte)0x65); // 'e'
// ECI marker switches to UTF-8 (ECI 26)
builder.appendECI(26);
// Read UTF-8 encoded bytes
builder.append((byte)0xE4); // First byte of Chinese character
builder.append((byte)0xB8);
builder.append((byte)0x96);
// Get final decoded string
String result = builder.toString(); // "He世"Interface for navigating byte sequences with ECI markers. Provides random access to bytes while tracking ECI character set switches.
/**
* Interface for navigating byte sequences with ECI markers.
* Allows random access to bytes and ECI values for encoding/decoding.
*/
public interface ECIInput {
/**
* Gets the length of the input sequence.
*
* @return Number of bytes and ECI markers
*/
int length();
/**
* Gets the byte value at specified index.
*
* @param index Position in sequence
* @return Byte value as char
* @throws IndexOutOfBoundsException If index is invalid
* @throws IllegalArgumentException If position is an ECI marker
*/
char charAt(int index);
/**
* Gets a subsequence of bytes.
*
* @param start Start index (inclusive)
* @param end End index (exclusive)
* @return CharSequence containing bytes
* @throws IndexOutOfBoundsException If indices are invalid
* @throws IllegalArgumentException If range contains ECI markers
*/
CharSequence subSequence(int start, int end);
/**
* Tests if position is an ECI marker.
*
* @param index Position to test
* @return true if position contains an ECI marker
* @throws IndexOutOfBoundsException If index is invalid
*/
boolean isECI(int index);
/**
* Gets the ECI value at specified index.
*
* @param index Position of ECI marker
* @return ECI value specifying character set
* @throws IndexOutOfBoundsException If index is invalid
* @throws IllegalArgumentException If position is not an ECI marker
*/
int getECIValue(int index);
/**
* Tests if N characters are available from position.
*
* @param index Starting position
* @param n Number of characters needed
* @return true if N consecutive non-ECI characters available
*/
boolean haveNCharacters(int index, int n);
}Geometric transformation for image rectification. Converts quadrilateral regions to squares and vice versa, essential for decoding skewed or perspective-distorted barcodes.
/**
* Perspective transformation matrix for converting between
* quadrilaterals and squares. Used for image rectification when
* decoding skewed or perspective-distorted barcodes.
*/
public final class PerspectiveTransform {
/**
* Creates transformation from arbitrary quadrilateral to another quadrilateral.
*
* @param x0, y0 First corner of source quadrilateral
* @param x1, y1 Second corner of source quadrilateral
* @param x2, y2 Third corner of source quadrilateral
* @param x3, y3 Fourth corner of source quadrilateral
* @param x0p, y0p First corner of destination quadrilateral
* @param x1p, y1p Second corner of destination quadrilateral
* @param x2p, y2p Third corner of destination quadrilateral
* @param x3p, y3p Fourth corner of destination quadrilateral
* @return PerspectiveTransform object
*/
public static PerspectiveTransform quadrilateralToQuadrilateral(
float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3,
float x0p, float y0p, float x1p, float y1p, float x2p, float y2p, float x3p, float y3p);
/**
* Creates transformation from unit square to arbitrary quadrilateral.
*
* @param x0, y0 First corner of quadrilateral
* @param x1, y1 Second corner of quadrilateral
* @param x2, y2 Third corner of quadrilateral
* @param x3, y3 Fourth corner of quadrilateral
* @return PerspectiveTransform object
*/
public static PerspectiveTransform squareToQuadrilateral(
float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
/**
* Creates transformation from arbitrary quadrilateral to unit square.
*
* @param x0, y0 First corner of quadrilateral
* @param x1, y1 Second corner of quadrilateral
* @param x2, y2 Third corner of quadrilateral
* @param x3, y3 Fourth corner of quadrilateral
* @return PerspectiveTransform object
*/
public static PerspectiveTransform quadrilateralToSquare(
float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
/**
* Transforms array of points using this transformation.
* Array is modified in-place. Format: [x0, y0, x1, y1, x2, y2, ...]
*
* @param points Array of x,y coordinate pairs
*/
public void transformPoints(float[] points);
/**
* Transforms separate x and y arrays.
* Arrays are modified in-place.
*
* @param xValues Array of x coordinates
* @param yValues Array of y coordinates
*/
public void transformPoints(float[] xValues, float[] yValues);
/**
* Builds composite transformation (this followed by other).
*
* @param other Second transformation to apply
* @return Composite PerspectiveTransform
*/
public PerspectiveTransform times(PerspectiveTransform other);
}Usage Example:
import com.google.zxing.common.PerspectiveTransform;
// Transform skewed barcode corners to square
float[] corners = {100, 100, 200, 110, 190, 200, 105, 195}; // Skewed quad
PerspectiveTransform transform = PerspectiveTransform.quadrilateralToSquare(
corners[0], corners[1], corners[2], corners[3],
corners[4], corners[5], corners[6], corners[7]
);
// Transform sample points
float[] points = {150, 150}; // Point to transform
transform.transformPoints(points);
// points now contains transformed coordinatesAbstract base class for sampling regular grids from images. Used by 2D barcode decoders to extract module values from detected patterns.
/**
* Base class for sampling grids from images.
* Converts arbitrary quadrilaterals (detected barcodes) to
* regular square grids (module matrices).
*/
public abstract class GridSampler {
/**
* Gets the singleton GridSampler instance.
*
* @return Current GridSampler (DefaultGridSampler by default)
*/
public static GridSampler getInstance();
/**
* Sets custom GridSampler implementation.
* Platform-specific code can provide optimized implementations
* (e.g., using native code or GPU acceleration).
*
* @param newGridSampler Custom sampler to use
*/
public static void setGridSampler(GridSampler newGridSampler);
/**
* Samples a grid from image using perspective transform.
*
* @param image Source image as BitMatrix
* @param dimensionX Grid width in modules
* @param dimensionY Grid height in modules
* @param p1ToX, p1ToY Transformation parameters (8 points)
* @param p2ToX, p2ToY Transformation parameters
* @param p3ToX, p3ToY Transformation parameters
* @param p4ToX, p4ToY Transformation parameters
* @return Sampled BitMatrix (regular grid)
* @throws NotFoundException If sampling fails
*/
public abstract BitMatrix sampleGrid(BitMatrix image,
int dimensionX, int dimensionY,
float p1ToX, float p1ToY, float p2ToX, float p2ToY,
float p3ToX, float p3ToY, float p4ToX, float p4ToY)
throws NotFoundException;
/**
* Samples a grid using PerspectiveTransform.
*
* @param image Source image
* @param dimensionX Grid width
* @param dimensionY Grid height
* @param transform Perspective transformation
* @return Sampled grid
* @throws NotFoundException If sampling fails
*/
public abstract BitMatrix sampleGrid(BitMatrix image,
int dimensionX, int dimensionY,
PerspectiveTransform transform)
throws NotFoundException;
/**
* Checks if quadrilateral is reasonable (not too skewed).
*
* @param p1ToX, p1ToY Corner coordinates (4 corners)
* @param p2ToX, p2ToY Corner coordinates
* @param p3ToX, p3ToY Corner coordinates
* @param p4ToX, p4ToY Corner coordinates
* @throws NotFoundException If quadrilateral is invalid
*/
protected static void checkAndNudgePoints(BitMatrix image, float[] points)
throws NotFoundException;
}Default grid sampler implementation using bilinear interpolation.
/**
* Default grid sampler using bilinear interpolation.
* Samples black/white values from arbitrary quadrilaterals.
*/
public final class DefaultGridSampler extends GridSampler {
/**
* Samples grid from image.
* See GridSampler for method signatures.
*/
@Override
public BitMatrix sampleGrid(BitMatrix image,
int dimensionX, int dimensionY,
float p1ToX, float p1ToY, float p2ToX, float p2ToY,
float p3ToX, float p3ToY, float p4ToX, float p4ToY)
throws NotFoundException;
@Override
public BitMatrix sampleGrid(BitMatrix image,
int dimensionX, int dimensionY,
PerspectiveTransform transform)
throws NotFoundException;
}Usage Example:
import com.google.zxing.common.GridSampler;
import com.google.zxing.common.DefaultGridSampler;
// Use default implementation
GridSampler sampler = GridSampler.getInstance();
// For platform-specific optimization, provide custom implementation
// Example: Native implementation for Android
public class NativeGridSampler extends GridSampler {
@Override
public BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY,
float p1ToX, float p1ToY, float p2ToX, float p2ToY,
float p3ToX, float p3ToY, float p4ToX, float p4ToY) {
// Native JNI implementation for faster grid sampling
return nativeSampleGrid(image, dimensionX, dimensionY,
p1ToX, p1ToY, p2ToX, p2ToY,
p3ToX, p3ToY, p4ToX, p4ToY);
}
// Additional native methods...
}
// Set custom implementation at app initialization
GridSampler.setGridSampler(new NativeGridSampler());String encoding detection and utility functions.
/**
* String encoding utilities.
* Detects character encoding from byte arrays and provides
* encoding hints for proper text decoding.
*/
public final class StringUtils {
/**
* Attempts to guess character encoding from byte array.
* Uses byte order marks, encoding hints, and heuristics.
*
* @param bytes Raw bytes to analyze
* @param hints Decode hints (may contain CHARACTER_SET)
* @return Charset name (e.g., "UTF-8", "ISO-8859-1")
*/
public static String guessEncoding(byte[] bytes, Map<DecodeHintType,?> hints);
/**
* Deprecated version of guessEncoding.
*
* @param bytes Raw bytes
* @param hints Decode hints
* @return Charset name
*/
@Deprecated
public static String guessCharset(byte[] bytes, Map<DecodeHintType,?> hints);
}Usage Example:
import com.google.zxing.common.StringUtils;
import java.nio.charset.Charset;
// Guess encoding from barcode data
byte[] rawBytes = result.getRawBytes();
String encoding = StringUtils.guessEncoding(rawBytes, hints);
Charset charset = Charset.forName(encoding);
// Decode with detected encoding
String text = new String(rawBytes, charset);
System.out.println("Detected encoding: " + encoding);
System.out.println("Text: " + text);Container for detector output (bits and corner points).
/**
* Result of detecting a barcode in an image.
* Contains the extracted bit matrix and corner/finder pattern locations.
*/
public class DetectorResult {
/**
* Creates a detector result.
*
* @param bits Extracted BitMatrix of barcode modules
* @param points Result points (corners, finder patterns, etc.)
*/
public DetectorResult(BitMatrix bits, ResultPoint[] points);
/**
* Gets the extracted bit matrix.
*
* @return BitMatrix containing barcode modules
*/
public final BitMatrix getBits();
/**
* Gets the result points.
*
* @return Array of corner/finder pattern points
*/
public final ResultPoint[] getPoints();
}Container for decoder output (text, raw bytes, metadata).
/**
* Result of decoding bits into text and metadata.
* Contains decoded text, raw bytes, error correction info, etc.
*/
public class DecoderResult {
/**
* Creates a decoder result.
*
* @param rawBytes Raw decoded bytes
* @param text Decoded text string
* @param byteSegments List of byte segments (optional)
* @param ecLevel Error correction level string (optional)
*/
public DecoderResult(byte[] rawBytes, String text, List<byte[]> byteSegments, String ecLevel);
/**
* Gets raw decoded bytes.
*
* @return Raw bytes
*/
public byte[] getRawBytes();
/**
* Gets number of valid bits in raw bytes.
*
* @return Number of bits
*/
public int getNumBits();
/**
* Sets number of valid bits.
*
* @param numBits Number of bits
*/
public void setNumBits(int numBits);
/**
* Gets decoded text.
*
* @return Text string
*/
public String getText();
/**
* Gets byte segments (if present).
*
* @return List of byte arrays or null
*/
public List<byte[]> getByteSegments();
/**
* Gets error correction level.
*
* @return EC level string or null
*/
public String getECLevel();
/**
* Gets number of errors corrected during decoding.
*
* @return Error count or null
*/
public Integer getErrorsCorrected();
/**
* Sets number of errors corrected.
*
* @param errorsCorrected Error count
*/
public void setErrorsCorrected(Integer errorsCorrected);
/**
* Gets number of erasures corrected.
*
* @return Erasure count or null
*/
public Integer getErasures();
/**
* Sets number of erasures corrected.
*
* @param erasures Erasure count
*/
public void setErasures(Integer erasures);
/**
* Gets other format-specific data.
*
* @return Format-specific object or null
*/
public Object getOther();
/**
* Sets other format-specific data.
*
* @param other Format-specific object
*/
public void setOther(Object other);
/**
* Checks if structured append is present.
*
* @return true if part of structured append sequence
*/
public boolean hasStructuredAppend();
/**
* Gets structured append parity.
*
* @return Parity value
*/
public int getStructuredAppendParity();
/**
* Gets structured append sequence number.
*
* @return Sequence number (0-based)
*/
public int getStructuredAppendSequenceNumber();
/**
* Gets symbology modifier.
*
* @return Modifier for symbology identifier
*/
public int getSymbologyModifier();
}Package: com.google.zxing.common.detector.MathUtils
Mathematical utility functions.
/**
* Mathematical utility functions for barcode processing.
*/
public final class MathUtils {
/**
* Rounds float to nearest integer.
*
* @param d Float value
* @return Rounded integer
*/
public static int round(float d);
/**
* Calculates Euclidean distance between two points.
*
* @param aX, aY First point coordinates
* @param bX, bY Second point coordinates
* @return Distance in pixels
*/
public static float distance(float aX, float aY, float bX, float bY);
/**
* Calculates distance between integer points.
*
* @param aX, aY First point
* @param bX, bY Second point
* @return Distance
*/
public static float distance(int aX, int aY, int bX, int bY);
/**
* Sums array of integers.
*
* @param array Integer array
* @return Sum of all elements
*/
public static int sum(int[] array);
}Detects rectangular regions of black/white.
/**
* Detects rectangular regions in monochrome images.
* Used by some 2D barcode detectors.
*/
public final class MonochromeRectangleDetector {
/**
* Creates detector for image.
*
* @param image BitMatrix to analyze
*/
public MonochromeRectangleDetector(BitMatrix image);
/**
* Attempts to detect a rectangle.
*
* @return Array of 4 ResultPoints (corners) or null
* @throws NotFoundException If no rectangle found
*/
public ResultPoint[] detect() throws NotFoundException;
}Detects white rectangular regions (used for Data Matrix detection).
/**
* Detects white rectangular regions in images.
* Used primarily by Data Matrix detector.
*/
public final class WhiteRectangleDetector {
/**
* Creates detector with default parameters.
*
* @param image BitMatrix to analyze
* @throws NotFoundException If image too small
*/
public WhiteRectangleDetector(BitMatrix image) throws NotFoundException;
/**
* Creates detector with custom parameters.
*
* @param image BitMatrix to analyze
* @param initSize Initial search size
* @param x, y Center coordinates for search
* @throws NotFoundException If parameters invalid
*/
public WhiteRectangleDetector(BitMatrix image, int initSize, int x, int y)
throws NotFoundException;
/**
* Detects white rectangle.
*
* @return Array of 4 ResultPoints (corners)
* @throws NotFoundException If no rectangle found
*/
public ResultPoint[] detect() throws NotFoundException;
}Character Set Handling:
Geometric Transformations:
Utility Classes:
Performance: