CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-google-zxing--core

Core barcode encoding/decoding library supporting 17 formats including QR Code, Data Matrix, Aztec, PDF 417, and various 1D barcodes

Pending
Overview
Eval results
Files

image-processing.mddocs/reference/

Image Processing

Image processing pipeline that converts various image formats into the binary representation required for barcode detection and decoding. The pipeline consists of luminance source adapters for RGB, YUV, and grayscale images, plus global and adaptive binarization algorithms for converting grayscale to 1-bit black/white representation.

Capabilities

LuminanceSource

Abstract base class providing grayscale luminance data from an image. Implementations convert various image formats (RGB, YUV, etc.) into 8-bit grayscale values.

/**
 * Abstract base class for providing luminance (grayscale) data from images.
 * Subclasses handle different image formats (RGB, YUV, etc.).
 * Luminance values range from 0 (black) to 255 (white).
 */
public abstract class LuminanceSource {
    /**
     * Gets a row of luminance data.
     *
     * @param y Row index (0-based from top)
     * @param row Optional pre-allocated array to reuse (may be null)
     * @return Array of luminance values for the row (0-255)
     */
    public abstract byte[] getRow(int y, byte[] row);

    /**
     * Gets the entire luminance matrix.
     *
     * @return Flattened array of all luminance values (row-major order)
     */
    public abstract byte[] getMatrix();

    /**
     * Gets the width of the luminance source.
     *
     * @return Width in pixels
     */
    public abstract int getWidth();

    /**
     * Gets the height of the luminance source.
     *
     * @return Height in pixels
     */
    public abstract int getHeight();

    /**
     * Checks if cropping is supported by this source.
     *
     * @return true if crop() can be called
     */
    public boolean isCropSupported();

    /**
     * Crops the luminance source to a rectangular region.
     *
     * @param left Left coordinate
     * @param top Top coordinate
     * @param width Width of crop region
     * @param height Height of crop region
     * @return New cropped LuminanceSource
     * @throws UnsupportedOperationException If cropping not supported
     */
    public LuminanceSource crop(int left, int top, int width, int height);

    /**
     * Checks if rotation is supported by this source.
     *
     * @return true if rotation methods can be called
     */
    public boolean isRotateSupported();

    /**
     * Rotates the luminance source 90 degrees counter-clockwise.
     *
     * @return New rotated LuminanceSource
     * @throws UnsupportedOperationException If rotation not supported
     */
    public LuminanceSource rotateCounterClockwise();

    /**
     * Rotates the luminance source 45 degrees counter-clockwise.
     *
     * @return New rotated LuminanceSource
     * @throws UnsupportedOperationException If rotation not supported
     */
    public LuminanceSource rotateCounterClockwise45();

    /**
     * Inverts the luminance values (black becomes white, white becomes black).
     *
     * @return New inverted LuminanceSource
     */
    public LuminanceSource invert();
}

RGBLuminanceSource

Luminance source for RGB pixel arrays (common in Java desktop and Android applications).

/**
 * Luminance source from RGB pixel array.
 * Converts RGB int values to grayscale luminance using standard formula:
 * Y = 0.299*R + 0.587*G + 0.114*B
 */
public final class RGBLuminanceSource extends LuminanceSource {
    /**
     * Creates luminance source from RGB pixel array.
     *
     * @param width Image width in pixels
     * @param height Image height in pixels
     * @param pixels RGB pixel array in row-major order (format: 0xAARRGGBB)
     * @throws IllegalArgumentException If dimensions don't match array size
     */
    public RGBLuminanceSource(int width, int height, int[] pixels);
}

Usage Example:

import com.google.zxing.*;
import com.google.zxing.common.*;

// From BufferedImage (Java desktop)
BufferedImage image = ...; // Load image
int width = image.getWidth();
int height = image.getHeight();
int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);

LuminanceSource source = new RGBLuminanceSource(width, height, pixels);

// From Android Bitmap
// Bitmap bitmap = ...;
// int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
// bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
// LuminanceSource source = new RGBLuminanceSource(bitmap.getWidth(), bitmap.getHeight(), pixels);

GrayscaleLuminanceSource

Luminance source for grayscale byte arrays. Used when image data is already in grayscale format, avoiding RGB conversion overhead.

/**
 * Luminance source from grayscale byte array.
 * Each byte represents a luminance value (0=black, 255=white).
 * Used for images already in grayscale format.
 */
public class GrayscaleLuminanceSource extends LuminanceSource {
    /**
     * Creates luminance source from grayscale byte array.
     *
     * @param width Image width in pixels
     * @param height Image height in pixels
     * @param pixels Grayscale byte array in row-major order (0=black, 255=white)
     * @throws IllegalArgumentException If dimensions don't match array size
     */
    public GrayscaleLuminanceSource(int width, int height, byte[] pixels);
}

Usage Example:

import com.google.zxing.GrayscaleLuminanceSource;

// From grayscale byte array
byte[] grayscalePixels = new byte[width * height];
// Fill with grayscale data (0=black, 255=white)
// ... populate grayscalePixels ...

LuminanceSource source = new GrayscaleLuminanceSource(width, height, grayscalePixels);

// Use with barcode reader
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result = reader.decode(bitmap);

PlanarYUVLuminanceSource

Luminance source for YUV image data (common in Android camera previews). Directly uses Y (luminance) channel without conversion overhead.

/**
 * Luminance source from planar YUV image data.
 * Optimized for Android camera preview frames (NV21/YV12 formats).
 * Uses Y channel directly without RGB conversion for maximum performance.
 */
public final class PlanarYUVLuminanceSource extends LuminanceSource {
    /**
     * Creates luminance source from YUV data.
     *
     * @param yuvData YUV image data (Y plane followed by UV planes)
     * @param dataWidth Full width of YUV image
     * @param dataHeight Full height of YUV image
     * @param left Left coordinate of region to extract
     * @param top Top coordinate of region to extract
     * @param width Width of region to extract
     * @param height Height of region to extract
     * @param reverseHorizontal If true, mirrors the image horizontally
     * @throws IllegalArgumentException If region is invalid
     */
    public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight,
                                   int left, int top, int width, int height,
                                   boolean reverseHorizontal);
}

Usage Example:

// From Android camera preview (NV21 format)
// @Override
// public void onPreviewFrame(byte[] data, Camera camera) {
//     Camera.Parameters parameters = camera.getParameters();
//     Camera.Size size = parameters.getPreviewSize();
//
//     LuminanceSource source = new PlanarYUVLuminanceSource(
//         data,
//         size.width, size.height,
//         0, 0,  // Extract from top-left
//         size.width, size.height,  // Full frame
//         false  // Don't reverse
//     );
// }

InvertedLuminanceSource

Wrapper that inverts luminance values of another source. Useful for decoding barcodes on dark backgrounds with light bars.

/**
 * Inverts luminance values of a delegate source.
 * Converts white to black and black to white.
 * Useful for reading inverted barcodes (light bars on dark background).
 */
public final class InvertedLuminanceSource extends LuminanceSource {
    /**
     * Creates inverted luminance source wrapping a delegate.
     *
     * @param delegate The source to invert
     */
    public InvertedLuminanceSource(LuminanceSource delegate);
}

Binarizer

Abstract base class for converting grayscale luminance to 1-bit black/white bitmap. Implementations use different algorithms for threshold determination.

/**
 * Abstract base class for binarization algorithms.
 * Converts grayscale luminance to 1-bit black/white representation
 * by determining threshold values.
 */
public abstract class Binarizer {
    /**
     * Gets a single row as black/white BitArray.
     *
     * @param y Row index
     * @param row Optional BitArray to reuse
     * @return BitArray containing binarized row
     * @throws NotFoundException If row cannot be binarized
     */
    public abstract BitArray getBlackRow(int y, BitArray row) throws NotFoundException;

    /**
     * Gets the entire image as black/white BitMatrix.
     *
     * @return BitMatrix containing binarized image
     * @throws NotFoundException If matrix cannot be binarized
     */
    public abstract BitMatrix getBlackMatrix() throws NotFoundException;

    /**
     * Checks if cropping is supported.
     *
     * @return true if luminance source supports cropping
     */
    public boolean isCropSupported();

    /**
     * Creates new binarizer with a different luminance source.
     *
     * @param source New luminance source
     * @return New Binarizer instance
     */
    public abstract Binarizer createBinarizer(LuminanceSource source);

    /**
     * Gets the width of the image.
     *
     * @return Width in pixels
     */
    public final int getWidth();

    /**
     * Gets the height of the image.
     *
     * @return Height in pixels
     */
    public final int getHeight();

    /**
     * Gets the underlying luminance source.
     *
     * @return LuminanceSource providing grayscale data
     */
    public final LuminanceSource getLuminanceSource();
}

GlobalHistogramBinarizer

Fast global histogram-based binarization. Uses single threshold for entire image based on luminance distribution. Fast but less effective for images with varying lighting.

/**
 * Fast global histogram-based binarization.
 * Computes single threshold based on luminance histogram.
 * Very fast but struggles with uneven lighting or shadows.
 *
 * Use when:
 * - Images have uniform lighting
 * - Speed is critical
 * - Simple documents or synthetic images
 */
public class GlobalHistogramBinarizer extends Binarizer {
    /**
     * Creates global histogram binarizer.
     *
     * @param source Luminance source to binarize
     */
    public GlobalHistogramBinarizer(LuminanceSource source);
}

HybridBinarizer

Local adaptive binarization with fallback to global. Divides image into blocks and computes local thresholds. Recommended for most use cases as it handles varying lighting conditions.

/**
 * Hybrid local adaptive binarization.
 * Uses local block-based thresholds for better handling of varying lighting.
 * Falls back to global method for uniform regions.
 *
 * Recommended for most use cases:
 * - Real-world photos with shadows
 * - Uneven lighting conditions
 * - Mobile device cameras
 * - General purpose barcode scanning
 */
public final class HybridBinarizer extends GlobalHistogramBinarizer {
    /**
     * Creates hybrid binarizer.
     *
     * @param source Luminance source to binarize
     */
    public HybridBinarizer(LuminanceSource source);
}

BinaryBitmap

Package: com.google.zxing.BinaryBitmap (not in common subpackage)

Binary representation of an image created from a Binarizer. This is the final form used by Reader implementations.

/**
 * Binary 1-bit bitmap representation of an image.
 * Created from a Binarizer and used by all Reader implementations.
 * Provides access to black/white data as BitArrays and BitMatrix.
 */
public final class BinaryBitmap {
    /**
     * Creates binary bitmap from binarizer.
     *
     * @param binarizer Binarizer containing image data
     */
    public BinaryBitmap(Binarizer binarizer);

    /**
     * Gets width of bitmap.
     *
     * @return Width in pixels
     */
    public int getWidth();

    /**
     * Gets height of bitmap.
     *
     * @return Height in pixels
     */
    public int getHeight();

    /**
     * Gets single row of black/white pixels.
     *
     * @param y Row index
     * @param row Optional BitArray to reuse
     * @return BitArray containing binarized row
     * @throws NotFoundException If row cannot be binarized
     */
    public BitArray getBlackRow(int y, BitArray row) throws NotFoundException;

    /**
     * Gets entire black/white matrix.
     *
     * @return BitMatrix containing binarized image
     * @throws NotFoundException If matrix cannot be binarized
     */
    public BitMatrix getBlackMatrix() throws NotFoundException;

    /**
     * Checks if cropping is supported.
     *
     * @return true if cropping supported
     */
    public boolean isCropSupported();

    /**
     * Crops to rectangular region.
     *
     * @param left Left coordinate
     * @param top Top coordinate
     * @param width Width of region
     * @param height Height of region
     * @return New cropped BinaryBitmap
     */
    public BinaryBitmap crop(int left, int top, int width, int height);

    /**
     * Checks if rotation is supported.
     *
     * @return true if rotation supported
     */
    public boolean isRotateSupported();

    /**
     * Rotates 90 degrees counter-clockwise.
     *
     * @return New rotated BinaryBitmap
     */
    public BinaryBitmap rotateCounterClockwise();

    /**
     * Rotates 45 degrees counter-clockwise.
     *
     * @return New rotated BinaryBitmap
     */
    public BinaryBitmap rotateCounterClockwise45();
}

Complete Pipeline Example

import com.google.zxing.*;
import com.google.zxing.common.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;

// Load image
BufferedImage bufferedImage = ImageIO.read(new File("barcode.png"));

// Step 1: Create luminance source from RGB pixels
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
int[] pixels = bufferedImage.getRGB(0, 0, width, height, null, 0, width);
LuminanceSource source = new RGBLuminanceSource(width, height, pixels);

// Step 2: Apply binarization
Binarizer binarizer = new HybridBinarizer(source);

// Step 3: Create binary bitmap
BinaryBitmap bitmap = new BinaryBitmap(binarizer);

// Step 4: Decode barcode
Reader reader = new MultiFormatReader();
Result result = reader.decode(bitmap);

System.out.println("Decoded: " + result.getText());

Binarization Comparison

AlgorithmSpeedQualityUse Case
GlobalHistogramBinarizerVery FastGood for uniform lightingDocuments, synthetic images
HybridBinarizerFastExcellent for varied lightingReal-world photos, mobile cameras

Best Practices

Luminance Source Selection:

  • Use RGBLuminanceSource for desktop Java (BufferedImage)
  • Use PlanarYUVLuminanceSource for Android camera (maximum performance)
  • Use InvertedLuminanceSource wrapper when detecting inverted barcodes

Binarizer Selection:

  • Use HybridBinarizer for general purpose (recommended default)
  • Use GlobalHistogramBinarizer only for uniform lighting or speed-critical applications
  • Try ALSO_INVERTED hint if barcodes may be inverted

Performance Optimization:

  • Crop source to region of interest before binarization
  • Reuse BitArray and other objects when processing multiple frames
  • Use PlanarYUVLuminanceSource directly on Android (avoids RGB conversion)
  • Process camera preview frames at reduced resolution if real-time performance needed

Troubleshooting:

  • If detection fails, try HybridBinarizer instead of GlobalHistogramBinarizer
  • For inverted barcodes (light bars on dark), use InvertedLuminanceSource or ALSO_INVERTED hint
  • For poor lighting, ensure adequate illumination or try histogram equalization before processing
  • For blurry images, image quality is likely too poor (barcode reading requires sharp images)

See Also

  • Core Reading and Writing - Using BinaryBitmap with readers
  • Bit Structures - BitMatrix and BitArray used in processing
  • Configuration Hints - PURE_BARCODE, ALSO_INVERTED hints
  • Common Utilities - String encoding and detection utilities

Install with Tessl CLI

npx tessl i tessl/maven-com-google-zxing--core

docs

index.md

tile.json