tessl install tessl/github-zxing-cpp--zxing-cpp@2.3.0Open-source, multi-format linear/matrix barcode image processing library implemented in C++
The Barcode class (alias for Result) encapsulates all information about a decoded barcode, including its content, format, position, error correction level, and metadata.
class Barcode {
public:
// Construction (typically created by ReadBarcode/ReadBarcodes)
Barcode(); // Default invalid barcode
// Validity and Error Checking
bool isValid() const;
const Error& error() const;
// Format Information
BarcodeFormat format() const;
// Content Access
const ByteArray& bytes() const; // Raw bytes
ByteArray bytesECI() const; // Bytes with ECI protocol
std::string text(TextMode mode) const; // Text with specific mode
std::string text() const; // Text with default mode
std::string ecLevel() const; // Error correction level
ContentType contentType() const; // Content type hint
bool hasECI() const; // Has ECI encoding
// Position and Orientation
const Position& position() const; // Corner positions (Quadrilateral)
void setPosition(Position pos);
int orientation() const; // Orientation in degrees
bool isMirrored() const; // Is mirrored (QR/DataMatrix)
bool isInverted() const; // Has reversed reflectance
// Symbology and Metadata
std::string symbologyIdentifier() const; // Symbology identifier ("]cm")
// Structured Append (Multi-Symbol)
int sequenceSize() const; // Total symbols in sequence (-1 if not part)
int sequenceIndex() const; // 0-based index in sequence
std::string sequenceId() const; // Sequence identifier
bool isLastInSequence() const;
bool isPartOfSequence() const;
// Additional Metadata
bool readerInit() const; // Reader initialization flag
int lineCount() const; // Scan lines detected (linear codes)
std::string version() const; // Version/size (QR/DataMatrix/Aztec)
// Comparison
bool operator==(const Barcode& other) const;
// Experimental API (requires ZXING_EXPERIMENTAL_API)
#ifdef ZXING_EXPERIMENTAL_API
void symbol(BitMatrix&& bits);
ImageView symbol() const;
void zint(unique_zint_symbol&& z);
zint_symbol* zint() const;
#endif
};
// Type aliases
using Barcode = Result;
using Barcodes = std::vector<Barcode>;
using Results = std::vector<Result>;
using Position = QuadrilateralI;Always check if a barcode is valid before accessing its content:
auto barcode = ZXing::ReadBarcode(image);
if (barcode.isValid()) {
// Barcode was successfully decoded
std::cout << "Content: " << barcode.text() << "\n";
} else {
// No barcode found or decoding failed
std::cerr << "Error: " << barcode.error().msg() << "\n";
}// Get text with default text mode (from ReaderOptions)
std::string text = barcode.text();
// Get text with specific text mode
std::string plainText = barcode.text(ZXing::TextMode::Plain);
std::string eciText = barcode.text(ZXing::TextMode::ECI);
std::string hexText = barcode.text(ZXing::TextMode::Hex);
std::string escapedText = barcode.text(ZXing::TextMode::Escaped);Text modes:
<GS>)// Get raw bytes
const ZXing::ByteArray& bytes = barcode.bytes();
// Iterate bytes
for (uint8_t byte : bytes) {
std::cout << std::hex << (int)byte << " ";
}
// Get bytes with ECI encoding
ZXing::ByteArray eciBytes = barcode.bytesECI();ZXing::ContentType type = barcode.contentType();
switch (type) {
case ZXing::ContentType::Text:
std::cout << "Text content\n";
break;
case ZXing::ContentType::Binary:
std::cout << "Binary content\n";
break;
case ZXing::ContentType::GS1:
std::cout << "GS1 formatted\n";
break;
case ZXing::ContentType::ISO15434:
std::cout << "ISO 15434 formatted\n";
break;
case ZXing::ContentType::Mixed:
std::cout << "Mixed text/binary\n";
break;
case ZXing::ContentType::UnknownECI:
std::cout << "Unknown ECI\n";
break;
}// Get format
ZXing::BarcodeFormat format = barcode.format();
// Convert to string
std::string formatName = ZXing::ToString(format);
std::cout << "Format: " << formatName << "\n";
// Check specific format
if (format == ZXing::BarcodeFormat::QRCode) {
std::cout << "This is a QR code\n";
}// Get position (quadrilateral with 4 corners)
const ZXing::Position& pos = barcode.position();
// Access corners
ZXing::PointI topLeft = pos.topLeft();
ZXing::PointI topRight = pos.topRight();
ZXing::PointI bottomRight = pos.bottomRight();
ZXing::PointI bottomLeft = pos.bottomLeft();
std::cout << "Corners: "
<< "TL(" << topLeft.x << "," << topLeft.y << ") "
<< "TR(" << topRight.x << "," << topRight.y << ") "
<< "BR(" << bottomRight.x << "," << bottomRight.y << ") "
<< "BL(" << bottomLeft.x << "," << bottomLeft.y << ")\n";
// Get orientation
double orient = pos.orientation(); // Radians// Get orientation in degrees
int degrees = barcode.orientation();
std::cout << "Barcode is rotated " << degrees << " degrees\n";// Check if mirrored (horizontally flipped)
// Supported for QR Code and Data Matrix
if (barcode.isMirrored()) {
std::cout << "Barcode is mirrored\n";
}
// Check if inverted (dark background, light barcode)
if (barcode.isInverted()) {
std::cout << "Barcode is inverted\n";
}std::string ecLevel = barcode.ecLevel();
if (!ecLevel.empty()) {
std::cout << "Error correction: " << ecLevel << "\n";
}
// QR Code: "L", "M", "Q", "H"
// Aztec: Percentage (e.g., "23")
// PDF417: Level 0-8
// Empty string if not applicableThe symbology identifier follows the AIM standard ("]cm" format):
std::string symId = barcode.symbologyIdentifier();
if (!symId.empty()) {
std::cout << "Symbology ID: " << symId << "\n";
// Examples:
// "]Q1" - QR Code
// "]d2" - Data Matrix
// "]e0" - EAN-13
// "]C1" - Code 128
}Format: ]cm where:
c = symbology code characterm = modifierSome formats support structured append, where data is split across multiple barcodes:
if (barcode.isPartOfSequence()) {
int index = barcode.sequenceIndex(); // 0-based position
int size = barcode.sequenceSize(); // Total number of symbols
std::string id = barcode.sequenceId(); // Sequence identifier
std::cout << "Symbol " << (index + 1) << " of " << size
<< " (ID: " << id << ")\n";
if (barcode.isLastInSequence()) {
std::cout << "This is the last symbol\n";
}
}// Read all barcodes
auto barcodes = ZXing::ReadBarcodes(image);
// Merge all structured append sequences automatically
auto merged = ZXing::MergeStructuredAppendSequences(barcodes);
// Or merge a specific sequence manually
ZXing::Barcodes sequence = /* collect related barcodes */;
auto combined = ZXing::MergeStructuredAppendSequence(sequence);
std::cout << "Complete data: " << combined.text() << "\n";Supported formats for structured append:
if (barcode.readerInit()) {
std::cout << "Reader Initialization/Programming symbol\n";
}For linear (1D) barcodes, the number of scan lines that matched:
int lines = barcode.lineCount();
if (lines > 0) {
std::cout << "Detected on " << lines << " scan lines\n";
}For QR Code, Data Matrix, and Aztec:
std::string version = barcode.version();
if (!version.empty()) {
std::cout << "Version/Size: " << version << "\n";
}
// QR Code: "1" to "40" (or "M1"-"M4" for Micro QR)
// Data Matrix: e.g., "12x12", "16x16"
// Aztec: e.g., "1" to "32"if (!barcode.isValid()) {
const ZXing::Error& error = barcode.error();
std::cerr << "Error type: " << (int)error.type() << "\n";
std::cerr << "Error message: " << error.msg() << "\n";
switch (error.type()) {
case ZXing::Error::Type::Format:
std::cerr << "Format/decoding error\n";
break;
case ZXing::Error::Type::Checksum:
std::cerr << "Checksum validation failed\n";
break;
case ZXing::Error::Type::Unsupported:
std::cerr << "Unsupported feature\n";
break;
case ZXing::Error::Type::None:
std::cerr << "No error (barcode is valid)\n";
break;
}
}auto barcodes = ZXing::ReadBarcodes(image, options);
std::cout << "Found " << barcodes.size() << " barcodes:\n";
for (size_t i = 0; i < barcodes.size(); ++i) {
const auto& bc = barcodes[i];
std::cout << i + 1 << ". ";
if (bc.isValid()) {
std::cout << ZXing::ToString(bc.format()) << ": " << bc.text() << "\n";
// Access position
auto pos = bc.position();
std::cout << " Position: " << ZXing::ToString(pos) << "\n";
// Access metadata
if (!bc.ecLevel().empty()) {
std::cout << " EC Level: " << bc.ecLevel() << "\n";
}
} else {
std::cout << "Invalid - " << bc.error().msg() << "\n";
}
}auto barcodes = ZXing::ReadBarcodes(image);
// Filter by format
ZXing::Barcodes qrCodes;
std::copy_if(barcodes.begin(), barcodes.end(), std::back_inserter(qrCodes),
[](const ZXing::Barcode& bc) {
return bc.format() == ZXing::BarcodeFormat::QRCode;
});
// Sort by position (top to bottom)
std::sort(barcodes.begin(), barcodes.end(),
[](const ZXing::Barcode& a, const ZXing::Barcode& b) {
return a.position().topLeft().y < b.position().topLeft().y;
});
// Find barcode at specific position
auto it = std::find_if(barcodes.begin(), barcodes.end(),
[&](const ZXing::Barcode& bc) {
return ZXing::IsInside(ZXing::PointI{x, y}, bc.position());
});ZXing::Barcode bc1 = /* ... */;
ZXing::Barcode bc2 = /* ... */;
if (bc1 == bc2) {
std::cout << "Barcodes are identical\n";
}
// Compares all properties: content, format, position, metadata, etc.// Check if barcode uses ECI
if (barcode.hasECI()) {
std::cout << "Uses Extended Channel Interpretation\n";
// Get content with ECI preservation
auto eciBytes = barcode.bytesECI();
// Get text with ECI mode
std::string eciText = barcode.text(ZXing::TextMode::ECI);
}
// Content type helps determine encoding
if (barcode.contentType() == ZXing::ContentType::Text) {
// Likely UTF-8 or other text encoding
std::string text = barcode.text();
}The ByteArray class is used for raw binary content:
class ByteArray : public std::vector<uint8_t> {
public:
ByteArray(); // Default empty
ByteArray(std::initializer_list<uint8_t> list);
explicit ByteArray(int len); // Pre-allocate with zeros
explicit ByteArray(const std::string& str); // From string
void append(const ByteArray& other);
std::string_view asString(size_t pos = 0, size_t len = std::string_view::npos) const;
};
// Utility function for hex representation
std::string ToHex(const ByteArray& bytes);Usage:
auto barcode = ZXing::ReadBarcode(image);
// Get raw bytes
const ZXing::ByteArray& bytes = barcode.bytes();
// Convert to hex string for display
std::string hex = ZXing::ToHex(bytes);
std::cout << "Hex: " << hex << "\n"; // Output: "48 65 6C 6C 6F"
// Access as string view
std::string_view sv = bytes.asString();
// ByteArray is a std::vector<uint8_t>, so use standard vector operations
for (uint8_t byte : bytes) {
std::cout << static_cast<int>(byte) << " ";
}// These types are equivalent
ZXing::Barcode bc = /* ... */;
ZXing::Result res = /* ... */; // Same type
// Vectors
ZXing::Barcodes barcodes = /* ... */; // std::vector<Barcode>
ZXing::Results results = /* ... */; // std::vector<Result>
// Position
ZXing::Position pos = bc.position(); // QuadrilateralI
ZXing::QuadrilateralI quad = pos; // Same type