tessl install tessl/github-zxing-cpp--zxing-cpp@2.3.0Open-source, multi-format linear/matrix barcode image processing library implemented in C++
The ZXing-C++ reading API provides functions to detect and decode barcodes from images. The library supports reading single or multiple barcodes from an image with extensive configuration options.
namespace ZXing {
/**
* Read a single barcode from an image.
* Stops after finding the first valid barcode.
*
* @param image ImageView of the image data
* @param options Optional ReaderOptions for configuration (default: empty options)
* @return Barcode result (check isValid() to see if barcode was found)
*/
Barcode ReadBarcode(const ImageView& image, const ReaderOptions& options = {});
/**
* Read multiple barcodes from an image.
* Searches for all barcodes up to maxNumberOfSymbols limit.
*
* @param image ImageView of the image data
* @param options Optional ReaderOptions for configuration (default: empty options)
* @return Vector of Barcode results (may be empty if no barcodes found)
*/
Barcodes ReadBarcodes(const ImageView& image, const ReaderOptions& options = {});
}#include "ZXing/ReadBarcode.h"
// Assuming you have image data loaded
uint8_t* imageData = ...; // Your image data
int width = ...;
int height = ...;
// Create ImageView (for grayscale image)
auto image = ZXing::ImageView(imageData, width, height, ZXing::ImageFormat::Lum);
// Read barcode with default options
auto barcode = ZXing::ReadBarcode(image);
if (barcode.isValid()) {
std::cout << "Found: " << barcode.text() << "\n";
std::cout << "Format: " << ZXing::ToString(barcode.format()) << "\n";
} else {
std::cerr << "No barcode found\n";
}#include "ZXing/ReadBarcode.h"
auto image = ZXing::ImageView(data, width, height, ZXing::ImageFormat::RGB);
// Configure to find up to 10 barcodes
auto options = ZXing::ReaderOptions()
.setMaxNumberOfSymbols(10)
.setFormats(ZXing::BarcodeFormat::Any);
auto barcodes = ZXing::ReadBarcodes(image, options);
std::cout << "Found " << barcodes.size() << " barcodes:\n";
for (const auto& bc : barcodes) {
if (bc.isValid()) {
std::cout << " " << ZXing::ToString(bc.format())
<< ": " << bc.text() << "\n";
}
}// Only look for QR codes
auto options = ZXing::ReaderOptions()
.setFormats(ZXing::BarcodeFormat::QRCode);
auto barcode = ZXing::ReadBarcode(image, options);// Look for QR codes, Data Matrix, or PDF417
auto formats = ZXing::BarcodeFormat::QRCode
| ZXing::BarcodeFormat::DataMatrix
| ZXing::BarcodeFormat::PDF417;
auto options = ZXing::ReaderOptions().setFormats(formats);
auto barcodes = ZXing::ReadBarcodes(image, options);// Use more aggressive scanning strategies
auto options = ZXing::ReaderOptions()
.setFormats(ZXing::BarcodeFormat::Any)
.setTryHarder(true) // Spend more time looking
.setTryRotate(true) // Try 90/180/270 degree rotations
.setTryInvert(true) // Try inverted colors
.setTryDownscale(true); // Try downscaled images
auto barcodes = ZXing::ReadBarcodes(image, options);// Grayscale image
auto imageLum = ZXing::ImageView(data, width, height, ZXing::ImageFormat::Lum);
// RGB image
auto imageRGB = ZXing::ImageView(data, width, height, ZXing::ImageFormat::RGB);
// RGBA image (with alpha channel)
auto imageRGBA = ZXing::ImageView(data, width, height, ZXing::ImageFormat::RGBA);
// BGR image (common in OpenCV)
auto imageBGR = ZXing::ImageView(data, width, height, ZXing::ImageFormat::BGR);
// All work the same way
auto barcode = ZXing::ReadBarcode(imageLum);// If your image data has padding or custom layout
int rowStride = width * 3 + 16; // 16 bytes padding per row
int pixStride = 3; // 3 bytes per pixel (RGB)
auto image = ZXing::ImageView(data, width, height,
ZXing::ImageFormat::RGB,
rowStride, pixStride);
auto barcode = ZXing::ReadBarcode(image);// Read from a specific region of interest
auto fullImage = ZXing::ImageView(data, width, height, ZXing::ImageFormat::Lum);
// Crop to region (left, top, width, height)
auto roi = fullImage.cropped(100, 100, 400, 300);
auto barcode = ZXing::ReadBarcode(roi);auto options = ZXing::ReaderOptions()
.setReturnErrors(true); // Return barcodes even if they have errors
auto barcodes = ZXing::ReadBarcodes(image, options);
for (const auto& bc : barcodes) {
if (bc.isValid()) {
std::cout << "Valid: " << bc.text() << "\n";
} else {
std::cerr << "Error: " << bc.error().msg()
<< " (type: " << static_cast<int>(bc.error().type()) << ")\n";
}
}When tryHarder is enabled, the library spends more time analyzing the image to find difficult-to-detect barcodes:
auto options = ZXing::ReaderOptions().setTryHarder(true);This is useful for:
Enable rotation detection to find barcodes at any angle:
auto options = ZXing::ReaderOptions().setTryRotate(true);The library will try 0°, 90°, 180°, and 270° orientations.
Some barcode formats support inverted colors (dark background, light barcode):
auto options = ZXing::ReaderOptions().setTryInvert(true);For very large images, downscaling can improve performance:
auto options = ZXing::ReaderOptions()
.setTryDownscale(true)
.setDownscaleThreshold(500) // Downscale if min(width,height) > 500
.setDownscaleFactor(3); // Scale factor (2, 3, or 4)If you know the image contains only a single, perfectly aligned barcode (e.g., a generated image):
auto options = ZXing::ReaderOptions().setIsPure(true);This enables fast-path processing with no rotation or perspective correction.
The library converts grayscale images to binary (black/white) using different algorithms:
enum class Binarizer {
LocalAverage, // Average of neighboring pixels (default for matrix codes)
GlobalHistogram, // Valley between peaks in histogram (default for linear codes)
FixedThreshold, // Fixed threshold at 127
BoolCast // Threshold at 0 (fastest, for already-binary images)
};Usage:
auto options = ZXing::ReaderOptions()
.setBinarizer(ZXing::Binarizer::GlobalHistogram);For linear barcodes, require multiple scan lines to agree:
auto options = ZXing::ReaderOptions()
.setMinLineCount(3); // Default is 2Higher values increase accuracy but may miss valid barcodes.
Enable full ASCII support for Code 39:
auto options = ZXing::ReaderOptions()
.setTryCode39ExtendedMode(true);Control how EAN-2 and EAN-5 add-on symbols are handled:
enum class EanAddOnSymbol {
Ignore, // Ignore add-on symbols (default)
Read, // Read add-on if present
Require // Require add-on to be present
};Usage:
auto options = ZXing::ReaderOptions()
.setEanAddOnSymbol(ZXing::EanAddOnSymbol::Read);
auto barcode = ZXing::ReadBarcode(image, options);
if (barcode.isValid()) {
// Main barcode data
std::cout << "Main: " << barcode.text() << "\n";
// Add-on data (if present)
auto addOn = ZXing::GTIN::EanAddOn(barcode);
if (!addOn.empty()) {
std::cout << "Add-on: " << addOn << "\n";
}
}These 2D codes support:
For maximum speed when barcode format and quality are known:
auto options = ZXing::ReaderOptions()
.setFormats(ZXing::BarcodeFormat::QRCode) // Specific format
.setTryHarder(false)
.setTryRotate(false)
.setTryInvert(false)
.setTryDownscale(false)
.setBinarizer(ZXing::Binarizer::BoolCast); // If image is pre-binarizedFor maximum detection rate when speed is not critical:
auto options = ZXing::ReaderOptions()
.setFormats(ZXing::BarcodeFormat::Any)
.setTryHarder(true)
.setTryRotate(true)
.setTryInvert(true)
.setTryDownscale(true)
.setMaxNumberOfSymbols(20); // Look for many barcodesAll reading functions are thread-safe. You can call ReadBarcode or ReadBarcodes from multiple threads simultaneously on different images.
// Safe to use from multiple threads
#pragma omp parallel for
for (int i = 0; i < numImages; ++i) {
auto barcode = ZXing::ReadBarcode(images[i], options);
results[i] = barcode;
}