or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated

docs

index.md
tile.json

tessl/github-zxing-cpp--zxing-cpp

tessl install tessl/github-zxing-cpp--zxing-cpp@2.3.0

Open-source, multi-format linear/matrix barcode image processing library implemented in C++

integration.mddocs/guides/

Integration Guide

This guide covers integrating ZXing-C++ with popular frameworks and libraries.

OpenCV Integration

Basic Setup

#include <opencv2/opencv.hpp>
#include "ZXing/ReadBarcode.h"

cv::Mat mat = cv::imread("image.jpg");

// OpenCV uses BGR format by default
auto image = ZXing::ImageView(
    mat.data,
    mat.cols,
    mat.rows,
    ZXing::ImageFormat::BGR,
    mat.step  // Important: include row stride
);

auto barcode = ZXing::ReadBarcode(image);

Grayscale Conversion

cv::Mat mat = cv::imread("image.jpg");
cv::Mat gray;
cv::cvtColor(mat, gray, cv::COLOR_BGR2GRAY);

auto image = ZXing::ImageView(
    gray.data,
    gray.cols,
    gray.rows,
    ZXing::ImageFormat::Lum,
    gray.step
);

auto barcode = ZXing::ReadBarcode(image);

Drawing Results

auto barcode = ZXing::ReadBarcode(image);

if (barcode.isValid()) {
    const auto& pos = barcode.position();
    
    // Draw quadrilateral
    cv::line(mat, cv::Point(pos.topLeft().x, pos.topLeft().y),
                  cv::Point(pos.topRight().x, pos.topRight().y),
                  cv::Scalar(0, 255, 0), 2);
    cv::line(mat, cv::Point(pos.topRight().x, pos.topRight().y),
                  cv::Point(pos.bottomRight().x, pos.bottomRight().y),
                  cv::Scalar(0, 255, 0), 2);
    cv::line(mat, cv::Point(pos.bottomRight().x, pos.bottomRight().y),
                  cv::Point(pos.bottomLeft().x, pos.bottomLeft().y),
                  cv::Scalar(0, 255, 0), 2);
    cv::line(mat, cv::Point(pos.bottomLeft().x, pos.bottomLeft().y),
                  cv::Point(pos.topLeft().x, pos.topLeft().y),
                  cv::Scalar(0, 255, 0), 2);
    
    // Add text
    cv::putText(mat, barcode.text(),
                cv::Point(pos.topLeft().x, pos.topLeft().y - 10),
                cv::FONT_HERSHEY_SIMPLEX, 0.5,
                cv::Scalar(0, 255, 0), 2);
}

cv::imshow("Result", mat);
cv::waitKey(0);

Qt Integration

QImage to ImageView

#include <QImage>
#include "ZXing/ReadBarcode.h"

QImage qImage = QImage("image.png");

// Convert to RGB888 format
qImage = qImage.convertToFormat(QImage::Format_RGB888);

auto image = ZXing::ImageView(
    qImage.bits(),
    qImage.width(),
    qImage.height(),
    ZXing::ImageFormat::RGB,
    qImage.bytesPerLine()
);

auto barcode = ZXing::ReadBarcode(image);

QPixmap to ImageView

#include <QPixmap>

QPixmap pixmap("image.png");
QImage qImage = pixmap.toImage().convertToFormat(QImage::Format_RGB888);

auto image = ZXing::ImageView(
    qImage.bits(),
    qImage.width(),
    qImage.height(),
    ZXing::ImageFormat::RGB,
    qImage.bytesPerLine()
);

STB Image Integration

Loading with stb_image

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include "ZXing/ReadBarcode.h"

int width, height, channels;
unsigned char* data = stbi_load("image.png", &width, &height, &channels, 0);

ZXing::ImageFormat format;
if (channels == 1) format = ZXing::ImageFormat::Lum;
else if (channels == 3) format = ZXing::ImageFormat::RGB;
else if (channels == 4) format = ZXing::ImageFormat::RGBA;

auto image = ZXing::ImageView(data, width, height, format);
auto barcode = ZXing::ReadBarcode(image);

stbi_image_free(data);

Force Grayscale Loading

int width, height, channels;
unsigned char* data = stbi_load("image.png", &width, &height, &channels, 1);  // Force 1 channel

auto image = ZXing::ImageView(data, width, height, ZXing::ImageFormat::Lum);
auto barcode = ZXing::ReadBarcode(image);

stbi_image_free(data);

Python Bindings

Installation

pip install zxing-cpp

Basic Usage

import zxingcpp

# Read from file
results = zxingcpp.read_barcodes("image.png")
for result in results:
    print(f"Found: {result.text}")
    print(f"Format: {result.format}")

# Read from numpy array
import numpy as np
from PIL import Image

img = Image.open("image.png")
img_array = np.array(img)
results = zxingcpp.read_barcodes(img_array)

Write Barcode

import zxingcpp

# Create barcode
barcode = zxingcpp.write_barcode(
    "Hello World",
    format=zxingcpp.BarcodeFormat.QRCode,
    width=200,
    height=200
)

# Save to file
from PIL import Image
img = Image.fromarray(barcode)
img.save("qrcode.png")

WebAssembly Integration

Building for WebAssembly

emcmake cmake -B build -DZXING_EXPERIMENTAL_API=ON
emmake cmake --build build

JavaScript Usage

// Load WASM module
const ZXing = await loadZXingModule();

// Read barcode from canvas
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

const result = ZXing.readBarcode(imageData.data, 
                                  imageData.width, 
                                  imageData.height);

if (result) {
    console.log('Text:', result.text);
    console.log('Format:', result.format);
}

Android Integration

Gradle Setup

dependencies {
    implementation 'com.github.zxing-cpp:android:2.3.0'
}

Kotlin Usage

import zxingcpp.BarcodeReader
import zxingcpp.BarcodeFormat

val bitmap: Bitmap = // your bitmap
val reader = BarcodeReader()

reader.formats = setOf(BarcodeFormat.QR_CODE)
val results = reader.read(bitmap)

results.forEach { result ->
    println("Text: ${result.text}")
    println("Format: ${result.format}")
}

iOS Integration

CocoaPods Setup

pod 'ZXingCpp', '~> 2.3'

Swift Usage

import ZXingCpp

let image = UIImage(named: "barcode.png")!
let cgImage = image.cgImage!

let reader = ZXingCppReader()
reader.formats = [.qrCode, .dataMatrix]

if let result = reader.read(cgImage) {
    print("Text: \(result.text)")
    print("Format: \(result.format)")
}

.NET Integration

NuGet Package

dotnet add package ZXingCpp

C# Usage

using ZXingCpp;

var bitmap = new Bitmap("image.png");
var reader = new BarcodeReader();

reader.Formats = BarcodeFormats.QRCode | BarcodeFormats.DataMatrix;
var results = reader.Read(bitmap);

foreach (var result in results)
{
    Console.WriteLine($"Text: {result.Text}");
    Console.WriteLine($"Format: {result.Format}");
}

Camera/Video Integration

OpenCV Video Capture

#include <opencv2/opencv.hpp>
#include "ZXing/ReadBarcode.h"

cv::VideoCapture cap(0);  // Open default camera
cv::Mat frame;

while (cap.read(frame)) {
    cv::Mat gray;
    cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
    
    auto image = ZXing::ImageView(
        gray.data, gray.cols, gray.rows,
        ZXing::ImageFormat::Lum, gray.step
    );
    
    auto barcode = ZXing::ReadBarcode(image);
    
    if (barcode.isValid()) {
        std::cout << "Found: " << barcode.text() << "\n";
        // Draw on frame...
    }
    
    cv::imshow("Camera", frame);
    if (cv::waitKey(1) == 27) break;  // ESC to exit
}

Performance Optimization for Video

// Process every Nth frame
int frameCount = 0;
const int processEvery = 3;

while (cap.read(frame)) {
    if (++frameCount % processEvery != 0) continue;
    
    // Downscale for faster processing
    cv::Mat small;
    cv::resize(frame, small, cv::Size(), 0.5, 0.5);
    
    cv::Mat gray;
    cv::cvtColor(small, gray, cv::COLOR_BGR2GRAY);
    
    auto image = ZXing::ImageView(
        gray.data, gray.cols, gray.rows,
        ZXing::ImageFormat::Lum, gray.step
    );
    
    auto options = ZXing::ReaderOptions()
        .setFormats(ZXing::BarcodeFormat::QRCode)
        .setTryRotate(false)  // Assume upright
        .setTryInvert(false);
    
    auto barcode = ZXing::ReadBarcode(image, options);
    // Process result...
}

Thread Safety

All ZXing-C++ functions are thread-safe. You can process multiple images in parallel:

#include <thread>
#include <vector>

std::vector<std::thread> threads;
std::vector<ZXing::Barcode> results(images.size());

for (size_t i = 0; i < images.size(); ++i) {
    threads.emplace_back([&, i]() {
        results[i] = ZXing::ReadBarcode(images[i]);
    });
}

for (auto& thread : threads) {
    thread.join();
}

CMake Integration Examples

Simple Integration

cmake_minimum_required(VERSION 3.16)
project(MyApp)

find_package(ZXing REQUIRED)

add_executable(myapp main.cpp)
target_link_libraries(myapp ZXing::ZXing)

With OpenCV

find_package(ZXing REQUIRED)
find_package(OpenCV REQUIRED)

add_executable(myapp main.cpp)
target_link_libraries(myapp 
    ZXing::ZXing
    ${OpenCV_LIBS}
)

Enable Experimental API

find_package(ZXing REQUIRED)

add_executable(myapp main.cpp)
target_link_libraries(myapp ZXing::ZXing)
target_compile_definitions(myapp PRIVATE ZXING_EXPERIMENTAL_API)

Best Practices

1. Reuse Options Objects

// Create once, reuse many times
auto options = ZXing::ReaderOptions()
    .setFormats(ZXing::BarcodeFormat::QRCode)
    .setTryHarder(true);

for (const auto& image : images) {
    auto barcode = ZXing::ReadBarcode(image, options);
    // Process...
}

2. Convert to Grayscale Early

// Convert once at capture/load time
cv::Mat gray;
cv::cvtColor(colorImage, gray, cv::COLOR_BGR2GRAY);

// Use grayscale for all processing
auto image = ZXing::ImageView(gray.data, gray.cols, gray.rows,
                               ZXing::ImageFormat::Lum, gray.step);

3. Handle Errors Gracefully

auto barcode = ZXing::ReadBarcode(image);

if (!barcode.isValid()) {
    // Log error but continue processing
    logError("Barcode read failed: " + barcode.error().msg());
    return std::nullopt;
}

return barcode.text();

Troubleshooting

OpenCV: Wrong Colors

Problem: Colors appear wrong in results Solution: OpenCV uses BGR, not RGB

// ✅ Correct
auto image = ZXing::ImageView(mat.data, mat.cols, mat.rows,
                               ZXing::ImageFormat::BGR, mat.step);

Qt: Crash on Read

Problem: Application crashes when reading Solution: Ensure QImage format is compatible

// ✅ Correct: Convert to RGB888 first
qImage = qImage.convertToFormat(QImage::Format_RGB888);

Performance: Slow Detection

Problem: Detection is too slow for real-time Solution: Optimize settings

auto options = ZXing::ReaderOptions()
    .setFormats(ZXing::BarcodeFormat::QRCode)  // Specific format
    .setTryRotate(false)  // Disable if not needed
    .setTryInvert(false)  // Disable if not needed
    .setTryDownscale(true);  // Enable for large images

Next Steps

  • Quick Start Guide - Basic usage
  • Real-World Scenarios - Common patterns
  • API Reference - Detailed documentation