tessl install tessl/github-zxing-cpp--zxing-cpp@2.3.0Open-source, multi-format linear/matrix barcode image processing library implemented in C++
ZXing-C++ uses the ImageView and Image classes to handle image data in various pixel formats. These classes provide a lightweight, efficient interface for passing image data to the library without requiring external dependencies.
ImageView is a non-owning view of image data. It does not copy or manage the memory, just provides access to existing data.
class ImageView {
public:
// Constructors
ImageView(); // Default null view
ImageView(const uint8_t* data, int width, int height, ImageFormat format,
int rowStride = 0, int pixStride = 0);
ImageView(const uint8_t* data, int size, int width, int height,
ImageFormat format, int rowStride = 0, int pixStride = 0); // With bounds checking
// Properties
int width() const;
int height() const;
int pixStride() const;
int rowStride() const;
ImageFormat format() const;
// Data access
const uint8_t* data() const;
const uint8_t* data(int x, int y) const;
// Transformations (return new views, no copy)
ImageView cropped(int left, int top, int width, int height) const;
ImageView rotated(int degree) const; // 0, 90, 180, 270
ImageView subsampled(int scale) const;
};Image extends ImageView and owns its memory. Use this when you need the library to manage image data.
class Image : public ImageView {
public:
Image(); // Default empty
Image(int w, int h, ImageFormat f = ImageFormat::Lum); // Allocate new image
};enum class ImageFormat : uint32_t {
None, // Invalid format
Lum, // Grayscale (luminance only)
LumA, // Grayscale + Alpha
RGB, // Red-Green-Blue
BGR, // Blue-Green-Red
RGBA, // Red-Green-Blue-Alpha
ARGB, // Alpha-Red-Green-Blue
BGRA, // Blue-Green-Red-Alpha
ABGR // Alpha-Blue-Green-Red
};| Format | Bytes/Pixel | Channel Order | Notes |
|---|---|---|---|
Lum | 1 | Grayscale | Most efficient for reading |
LumA | 2 | Gray, Alpha | Rarely used |
RGB | 3 | Red, Green, Blue | Standard RGB |
BGR | 3 | Blue, Green, Red | Common in OpenCV |
RGBA | 4 | Red, Green, Blue, Alpha | Standard RGBA |
ARGB | 4 | Alpha, Red, Green, Blue | Windows DIB format |
BGRA | 4 | Blue, Green, Red, Alpha | Common in graphics APIs |
ABGR | 4 | Alpha, Blue, Green, Red | Less common |
// From grayscale data
uint8_t* grayData = /* ... */;
int width = 640;
int height = 480;
auto imageView = ZXing::ImageView(grayData, width, height, ZXing::ImageFormat::Lum);
// Read barcode
auto barcode = ZXing::ReadBarcode(imageView);// From RGB data (e.g., from image file)
uint8_t* rgbData = /* ... */; // width * height * 3 bytes
int width = 640;
int height = 480;
auto imageView = ZXing::ImageView(rgbData, width, height, ZXing::ImageFormat::RGB);
auto barcode = ZXing::ReadBarcode(imageView);// From RGBA data (e.g., from PNG with alpha)
uint8_t* rgbaData = /* ... */; // width * height * 4 bytes
int width = 800;
int height = 600;
auto imageView = ZXing::ImageView(rgbaData, width, height, ZXing::ImageFormat::RGBA);
auto barcodes = ZXing::ReadBarcodes(imageView);OpenCV uses BGR format by default:
#include <opencv2/opencv.hpp>
cv::Mat cvImage = cv::imread("image.jpg");
auto imageView = ZXing::ImageView(
cvImage.data,
cvImage.cols,
cvImage.rows,
ZXing::ImageFormat::BGR,
cvImage.step // rowStride
);
auto barcode = ZXing::ReadBarcode(imageView);When your image has padding or non-standard layout:
// Image with row padding
uint8_t* data = /* ... */;
int width = 640;
int height = 480;
int rowStride = 672; // 640 * 3 + 32 bytes padding
int pixStride = 3; // RGB
auto imageView = ZXing::ImageView(
data, width, height,
ZXing::ImageFormat::RGB,
rowStride, pixStride
);// If you know the buffer size, use bounds-checking constructor
uint8_t* data = /* ... */;
int bufferSize = 1024 * 768 * 3;
int width = 1024;
int height = 768;
try {
auto imageView = ZXing::ImageView(
data, bufferSize, width, height,
ZXing::ImageFormat::RGB
);
} catch (const std::invalid_argument& e) {
std::cerr << "Invalid image parameters: " << e.what() << "\n";
}Extract a region of interest without copying:
auto fullImage = ZXing::ImageView(data, width, height, ZXing::ImageFormat::Lum);
// Crop to (left, top, width, height)
auto roi = fullImage.cropped(100, 100, 400, 300);
// roi is a view into the same data, no copy
auto barcode = ZXing::ReadBarcode(roi);Crop parameters are automatically clamped to valid ranges.
Create rotated views (no copy):
auto image = ZXing::ImageView(data, width, height, ZXing::ImageFormat::Lum);
// Rotate 90 degrees clockwise
auto rotated90 = image.rotated(90);
// Rotate 180 degrees
auto rotated180 = image.rotated(180);
// Rotate 270 degrees (90 counter-clockwise)
auto rotated270 = image.rotated(270);
// No rotation
auto rotated0 = image.rotated(0); // Returns copy of viewRotation is achieved by adjusting strides and starting pointer, not by copying pixels.
Subsample for faster processing:
auto image = ZXing::ImageView(data, 3200, 2400, ZXing::ImageFormat::Lum);
// Downsample by factor of 4
auto downsampled = image.subsampled(4); // Now 800x600
// This is a view with adjusted strides, skipping pixels
auto barcode = ZXing::ReadBarcode(downsampled);When you need to allocate and own image memory:
// Allocate a new grayscale image
ZXing::Image image(640, 480, ZXing::ImageFormat::Lum);
// Access mutable data
uint8_t* data = const_cast<uint8_t*>(image.data());
// Fill with pattern
for (int y = 0; y < image.height(); ++y) {
for (int x = 0; x < image.width(); ++x) {
data[y * image.width() + x] = (x + y) % 256;
}
}
// Use like ImageView
auto barcode = ZXing::ReadBarcode(image);The writing API returns an Image:
auto barcode = ZXing::CreateBarcodeFromText("Test", options);
auto image = ZXing::WriteBarcodeToImage(barcode);
// image owns its memory
int width = image.width();
int height = image.height();
// Get pixel data (grayscale)
const uint8_t* pixels = image.data();
// Save to file, display, etc.// Get pixel stride for format
constexpr int PixStride(ImageFormat format);
// Get color channel indices
constexpr int RedIndex(ImageFormat format);
constexpr int GreenIndex(ImageFormat format);
constexpr int BlueIndex(ImageFormat format);
// Convert RGB to grayscale
constexpr uint8_t RGBToLum(unsigned r, unsigned g, unsigned b);Usage:
auto format = ZXing::ImageFormat::RGB;
int stride = ZXing::PixStride(format); // 3
int rIndex = ZXing::RedIndex(format); // 0
int gIndex = ZXing::GreenIndex(format); // 1
int bIndex = ZXing::BlueIndex(format); // 2
// Manual grayscale conversion
uint8_t gray = ZXing::RGBToLum(r, g, b);For grayscale (Lum):
uint8_t pixel = data[y * width + x];For RGB:
int offset = (y * width + x) * 3;
uint8_t r = data[offset + 0];
uint8_t g = data[offset + 1];
uint8_t b = data[offset + 2];For RGBA:
int offset = (y * width + x) * 4;
uint8_t r = data[offset + 0];
uint8_t g = data[offset + 1];
uint8_t b = data[offset + 2];
uint8_t a = data[offset + 3];With custom stride:
uint8_t pixel = data[y * rowStride + x * pixStride];auto imageView = ZXing::ImageView(data, width, height, format);
// Get pointer to pixel at (x, y)
const uint8_t* pixelPtr = imageView.data(x, y);
// For RGB
uint8_t r = pixelPtr[0];
uint8_t g = pixelPtr[1];
uint8_t b = pixelPtr[2];QImage qImage = /* ... */;
// Ensure RGB32 or ARGB32 format
qImage = qImage.convertToFormat(QImage::Format_RGB888);
auto imageView = ZXing::ImageView(
qImage.bits(),
qImage.width(),
qImage.height(),
ZXing::ImageFormat::RGB,
qImage.bytesPerLine()
);
auto barcode = ZXing::ReadBarcode(imageView);cv::Mat mat = /* ... */;
// Grayscale
if (mat.channels() == 1) {
auto imageView = ZXing::ImageView(
mat.data, mat.cols, mat.rows,
ZXing::ImageFormat::Lum,
mat.step
);
}
// BGR
else if (mat.channels() == 3) {
auto imageView = ZXing::ImageView(
mat.data, mat.cols, mat.rows,
ZXing::ImageFormat::BGR,
mat.step
);
}
// BGRA
else if (mat.channels() == 4) {
auto imageView = ZXing::ImageView(
mat.data, mat.cols, mat.rows,
ZXing::ImageFormat::BGRA,
mat.step
);
}#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.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 imageView = ZXing::ImageView(data, width, height, format);
auto barcode = ZXing::ReadBarcode(imageView);
stbi_image_free(data);ImageView for zero-copy operationsubsampled() or pre-downscaletry {
// This will throw if data is nullptr
auto view = ZXing::ImageView(nullptr, 100, 100, ZXing::ImageFormat::Lum);
} catch (const std::invalid_argument& e) {
std::cerr << "Error: " << e.what() << "\n";
}
try {
// This will throw if width/height is <= 0
auto view = ZXing::ImageView(data, 0, 0, ZXing::ImageFormat::Lum);
} catch (const std::invalid_argument& e) {
std::cerr << "Error: " << e.what() << "\n";
}Use the size-parameter constructor for automatic bounds validation:
std::vector<uint8_t> buffer(640 * 480);
try {
// This validates buffer is large enough
auto view = ZXing::ImageView(
buffer.data(), buffer.size(),
640, 480, ZXing::ImageFormat::Lum
);
} catch (const std::invalid_argument& e) {
std::cerr << "Buffer too small: " << e.what() << "\n";
}