tessl install tessl/github-zxing-cpp--zxing-cpp@2.3.0Open-source, multi-format linear/matrix barcode image processing library implemented in C++
This guide covers integrating ZXing-C++ with popular frameworks and libraries.
#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);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);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);#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);#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()
);#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);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);pip install zxing-cppimport 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)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")emcmake cmake -B build -DZXING_EXPERIMENTAL_API=ON
emmake cmake --build build// 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);
}dependencies {
implementation 'com.github.zxing-cpp:android:2.3.0'
}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}")
}pod 'ZXingCpp', '~> 2.3'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)")
}dotnet add package ZXingCppusing 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}");
}#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
}// 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...
}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_minimum_required(VERSION 3.16)
project(MyApp)
find_package(ZXing REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp ZXing::ZXing)find_package(ZXing REQUIRED)
find_package(OpenCV REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp
ZXing::ZXing
${OpenCV_LIBS}
)find_package(ZXing REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp ZXing::ZXing)
target_compile_definitions(myapp PRIVATE ZXING_EXPERIMENTAL_API)// 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...
}// 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);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();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);Problem: Application crashes when reading Solution: Ensure QImage format is compatible
// ✅ Correct: Convert to RGB888 first
qImage = qImage.convertToFormat(QImage::Format_RGB888);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