or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated

docs

examples

edge-cases.mdreal-world-scenarios.md
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++

real-world-scenarios.mddocs/examples/

Real-World Scenarios

This document provides practical examples for common ZXing-C++ use cases.

Retail Point of Sale

Scanning Product Barcodes

#include "ZXing/ReadBarcode.h"

class POSScanner {
    ZXing::ReaderOptions options;
    
public:
    POSScanner() {
        // Configure for retail formats
        options.setFormats(
            ZXing::BarcodeFormat::EAN13 |
            ZXing::BarcodeFormat::EAN8 |
            ZXing::BarcodeFormat::UPCA |
            ZXing::BarcodeFormat::UPCE
        );
        options.setTryHarder(true);
        options.setTryRotate(false);  // Products usually upright
    }
    
    std::optional<std::string> scanProduct(const ZXing::ImageView& image) {
        auto barcode = ZXing::ReadBarcode(image, options);
        
        if (!barcode.isValid()) {
            return std::nullopt;
        }
        
        // Validate check digit
        if (!ZXing::GTIN::IsCheckDigitValid(barcode.text())) {
            logWarning("Invalid check digit");
            return std::nullopt;
        }
        
        return barcode.text();
    }
};

Handling Add-On Symbols

auto options = ZXing::ReaderOptions()
    .setFormats(ZXing::BarcodeFormat::EAN13)
    .setEanAddOnSymbol(ZXing::EanAddOnSymbol::Read);

auto barcode = ZXing::ReadBarcode(image, options);

if (barcode.isValid()) {
    std::string mainCode = barcode.text();
    std::string addOn = ZXing::GTIN::EanAddOn(barcode);
    
    if (!addOn.empty()) {
        if (addOn.length() == 2) {
            // Magazine issue number
            std::string issue = ZXing::GTIN::IssueNr(addOn);
            std::cout << "Issue: " << issue << "\n";
        } else if (addOn.length() == 5) {
            // Book price
            std::string price = ZXing::GTIN::Price(addOn);
            std::cout << "Price: " << price << "\n";
        }
    }
}

Warehouse Management

Batch Scanning

#include <vector>
#include <string>

class WarehouseScanner {
public:
    struct ScanResult {
        std::string code;
        ZXing::BarcodeFormat format;
        ZXing::Position position;
        std::chrono::system_clock::time_point timestamp;
    };
    
    std::vector<ScanResult> scanPallet(const ZXing::ImageView& image) {
        auto options = ZXing::ReaderOptions()
            .setFormats(ZXing::BarcodeFormat::Code128 |
                       ZXing::BarcodeFormat::DataMatrix)
            .setMaxNumberOfSymbols(20)
            .setTryHarder(true);
        
        auto barcodes = ZXing::ReadBarcodes(image, options);
        
        std::vector<ScanResult> results;
        for (const auto& bc : barcodes) {
            if (bc.isValid()) {
                results.push_back({
                    bc.text(),
                    bc.format(),
                    bc.position(),
                    std::chrono::system_clock::now()
                });
            }
        }
        
        return results;
    }
};

Tracking Package Movement

class PackageTracker {
    std::map<std::string, std::vector<std::string>> packageHistory;
    
public:
    void scanPackage(const ZXing::ImageView& image, 
                     const std::string& location) {
        auto options = ZXing::ReaderOptions()
            .setFormats(ZXing::BarcodeFormat::Code128);
        
        auto barcode = ZXing::ReadBarcode(image, options);
        
        if (barcode.isValid()) {
            std::string trackingNumber = barcode.text();
            packageHistory[trackingNumber].push_back(location);
            
            // Log to database
            logPackageMovement(trackingNumber, location);
        }
    }
    
    std::vector<std::string> getPackageHistory(const std::string& trackingNumber) {
        return packageHistory[trackingNumber];
    }
};

Document Processing

Scanning Driver's License (PDF417)

struct DriverLicense {
    std::string name;
    std::string licenseNumber;
    std::string dateOfBirth;
    std::string expirationDate;
    std::string address;
};

std::optional<DriverLicense> scanDriverLicense(const ZXing::ImageView& image) {
    auto options = ZXing::ReaderOptions()
        .setFormats(ZXing::BarcodeFormat::PDF417)
        .setTryHarder(true);
    
    auto barcode = ZXing::ReadBarcode(image, options);
    
    if (!barcode.isValid()) {
        return std::nullopt;
    }
    
    // Parse AAMVA format
    std::string data = barcode.text();
    DriverLicense license;
    
    // Parse fields (simplified example)
    size_t pos = 0;
    while ((pos = data.find("DAA", pos)) != std::string::npos) {
        license.name = data.substr(pos + 3, data.find('\n', pos) - pos - 3);
        break;
    }
    
    // Parse other fields...
    
    return license;
}

Multi-Page Document Scanning

class DocumentScanner {
    std::map<std::string, std::vector<ZXing::Barcode>> documents;
    
public:
    void scanPage(const ZXing::ImageView& image, int pageNumber) {
        auto options = ZXing::ReaderOptions()
            .setFormats(ZXing::BarcodeFormat::QRCode |
                       ZXing::BarcodeFormat::DataMatrix)
            .setMaxNumberOfSymbols(10);
        
        auto barcodes = ZXing::ReadBarcodes(image, options);
        
        for (const auto& bc : barcodes) {
            if (bc.isValid() && bc.isPartOfSequence()) {
                std::string docId = bc.sequenceId();
                documents[docId].push_back(bc);
                
                // Check if document is complete
                if (isDocumentComplete(docId)) {
                    processCompleteDocument(docId);
                }
            }
        }
    }
    
private:
    bool isDocumentComplete(const std::string& docId) {
        const auto& pages = documents[docId];
        if (pages.empty()) return false;
        
        int expectedPages = pages[0].sequenceSize();
        return pages.size() == expectedPages;
    }
    
    void processCompleteDocument(const std::string& docId) {
        auto merged = ZXing::MergeStructuredAppendSequence(documents[docId]);
        if (merged.isValid()) {
            std::cout << "Document complete: " << merged.text() << "\n";
            documents.erase(docId);
        }
    }
};

Mobile Applications

QR Code Business Card

struct BusinessCard {
    std::string name;
    std::string company;
    std::string email;
    std::string phone;
    std::string website;
};

std::optional<BusinessCard> scanBusinessCard(const ZXing::ImageView& image) {
    auto options = ZXing::ReaderOptions()
        .setFormats(ZXing::BarcodeFormat::QRCode);
    
    auto barcode = ZXing::ReadBarcode(image, options);
    
    if (!barcode.isValid()) {
        return std::nullopt;
    }
    
    std::string vcard = barcode.text();
    
    // Parse vCard format
    BusinessCard card;
    
    auto extractField = [&](const std::string& field) -> std::string {
        size_t pos = vcard.find(field);
        if (pos == std::string::npos) return "";
        
        size_t start = vcard.find(':', pos) + 1;
        size_t end = vcard.find('\n', start);
        return vcard.substr(start, end - start);
    };
    
    card.name = extractField("FN:");
    card.company = extractField("ORG:");
    card.email = extractField("EMAIL:");
    card.phone = extractField("TEL:");
    card.website = extractField("URL:");
    
    return card;
}

WiFi QR Code

struct WiFiCredentials {
    std::string ssid;
    std::string password;
    std::string encryption;  // WPA, WEP, nopass
};

std::optional<WiFiCredentials> scanWiFiQR(const ZXing::ImageView& image) {
    auto barcode = ZXing::ReadBarcode(image);
    
    if (!barcode.isValid()) {
        return std::nullopt;
    }
    
    std::string text = barcode.text();
    
    // WiFi QR format: WIFI:T:WPA;S:SSID;P:password;;
    if (text.substr(0, 5) != "WIFI:") {
        return std::nullopt;
    }
    
    WiFiCredentials creds;
    
    auto extractParam = [&](const std::string& param) -> std::string {
        size_t pos = text.find(param + ":");
        if (pos == std::string::npos) return "";
        
        size_t start = pos + param.length() + 1;
        size_t end = text.find(';', start);
        return text.substr(start, end - start);
    };
    
    creds.encryption = extractParam("T");
    creds.ssid = extractParam("S");
    creds.password = extractParam("P");
    
    return creds;
}

Manufacturing

Part Tracking with Data Matrix

class PartTracker {
public:
    struct PartInfo {
        std::string partNumber;
        std::string serialNumber;
        std::string lotNumber;
        std::string manufactureDate;
    };
    
    std::optional<PartInfo> scanPart(const ZXing::ImageView& image) {
        auto options = ZXing::ReaderOptions()
            .setFormats(ZXing::BarcodeFormat::DataMatrix)
            .setTryHarder(true)
            .setTryInvert(true);  // Parts may have inverted codes
        
        auto barcode = ZXing::ReadBarcode(image, options);
        
        if (!barcode.isValid()) {
            return std::nullopt;
        }
        
        // Parse GS1 format
        if (barcode.contentType() == ZXing::ContentType::GS1) {
            return parseGS1Data(barcode.text());
        }
        
        return std::nullopt;
    }
    
private:
    std::optional<PartInfo> parseGS1Data(const std::string& data) {
        PartInfo info;
        
        // Parse GS1 Application Identifiers
        // (01) = GTIN, (10) = Batch/Lot, (17) = Expiry, (21) = Serial
        
        size_t pos = 0;
        while (pos < data.length()) {
            if (data.substr(pos, 3) == "(01)") {
                info.partNumber = extractGS1Field(data, pos + 3, 14);
            } else if (data.substr(pos, 3) == "(10)") {
                info.lotNumber = extractGS1Field(data, pos + 3);
            } else if (data.substr(pos, 3) == "(17)") {
                info.manufactureDate = extractGS1Field(data, pos + 3, 6);
            } else if (data.substr(pos, 3) == "(21)") {
                info.serialNumber = extractGS1Field(data, pos + 3);
            }
            
            pos = data.find('(', pos + 1);
            if (pos == std::string::npos) break;
        }
        
        return info;
    }
    
    std::string extractGS1Field(const std::string& data, size_t start, 
                                 int fixedLength = -1) {
        if (fixedLength > 0) {
            return data.substr(start, fixedLength);
        }
        
        size_t end = data.find('(', start);
        if (end == std::string::npos) end = data.length();
        return data.substr(start, end - start);
    }
};

Healthcare

Medication Verification

class MedicationScanner {
public:
    struct MedicationInfo {
        std::string ndc;  // National Drug Code
        std::string lotNumber;
        std::string expirationDate;
        std::string serialNumber;
    };
    
    std::optional<MedicationInfo> scanMedication(const ZXing::ImageView& image) {
        auto options = ZXing::ReaderOptions()
            .setFormats(ZXing::BarcodeFormat::DataMatrix |
                       ZXing::BarcodeFormat::QRCode)
            .setTryHarder(true);
        
        auto barcode = ZXing::ReadBarcode(image, options);
        
        if (!barcode.isValid()) {
            return std::nullopt;
        }
        
        // Parse GS1 DataBar or 2D barcode
        return parseGS1Healthcare(barcode.text());
    }
    
    bool verifyMedication(const MedicationInfo& info) {
        // Check expiration
        if (isExpired(info.expirationDate)) {
            return false;
        }
        
        // Verify against database
        return checkDatabase(info.ndc, info.serialNumber);
    }
    
private:
    std::optional<MedicationInfo> parseGS1Healthcare(const std::string& data) {
        MedicationInfo info;
        
        // Parse GS1 format
        // (01) = GTIN/NDC, (10) = Lot, (17) = Expiry, (21) = Serial
        
        // Implementation similar to part tracking example
        
        return info;
    }
    
    bool isExpired(const std::string& expiryDate) {
        // Parse YYMMDD format and compare with current date
        // Implementation details...
        return false;
    }
    
    bool checkDatabase(const std::string& ndc, const std::string& serial) {
        // Verify against pharmaceutical database
        // Implementation details...
        return true;
    }
};

Event Management

Ticket Validation

class TicketValidator {
    std::set<std::string> usedTickets;
    
public:
    enum class ValidationResult {
        Valid,
        AlreadyUsed,
        Invalid,
        Expired
    };
    
    ValidationResult validateTicket(const ZXing::ImageView& image) {
        auto options = ZXing::ReaderOptions()
            .setFormats(ZXing::BarcodeFormat::QRCode |
                       ZXing::BarcodeFormat::Aztec)
            .setTryHarder(true);
        
        auto barcode = ZXing::ReadBarcode(image, options);
        
        if (!barcode.isValid()) {
            return ValidationResult::Invalid;
        }
        
        std::string ticketId = barcode.text();
        
        // Check if already used
        if (usedTickets.count(ticketId)) {
            return ValidationResult::AlreadyUsed;
        }
        
        // Verify ticket validity (check signature, expiration, etc.)
        if (!verifyTicketSignature(ticketId)) {
            return ValidationResult::Invalid;
        }
        
        if (isTicketExpired(ticketId)) {
            return ValidationResult::Expired;
        }
        
        // Mark as used
        usedTickets.insert(ticketId);
        
        return ValidationResult::Valid;
    }
    
private:
    bool verifyTicketSignature(const std::string& ticketId) {
        // Verify cryptographic signature
        // Implementation details...
        return true;
    }
    
    bool isTicketExpired(const std::string& ticketId) {
        // Check ticket expiration
        // Implementation details...
        return false;
    }
};

Inventory Management

Stock Taking

class InventoryScanner {
public:
    struct InventoryItem {
        std::string sku;
        int quantity;
        std::string location;
        std::chrono::system_clock::time_point scannedAt;
    };
    
    std::vector<InventoryItem> scanShelf(const ZXing::ImageView& image,
                                          const std::string& location) {
        auto options = ZXing::ReaderOptions()
            .setFormats(ZXing::BarcodeFormat::Any)
            .setMaxNumberOfSymbols(50)
            .setTryHarder(true);
        
        auto barcodes = ZXing::ReadBarcodes(image, options);
        
        std::map<std::string, int> itemCounts;
        
        for (const auto& bc : barcodes) {
            if (bc.isValid()) {
                itemCounts[bc.text()]++;
            }
        }
        
        std::vector<InventoryItem> items;
        auto now = std::chrono::system_clock::now();
        
        for (const auto& [sku, count] : itemCounts) {
            items.push_back({sku, count, location, now});
        }
        
        return items;
    }
    
    void exportToCSV(const std::vector<InventoryItem>& items,
                     const std::string& filename) {
        std::ofstream file(filename);
        file << "SKU,Quantity,Location,Timestamp\n";
        
        for (const auto& item : items) {
            auto time_t = std::chrono::system_clock::to_time_t(item.scannedAt);
            file << item.sku << ","
                 << item.quantity << ","
                 << item.location << ","
                 << std::ctime(&time_t);
        }
    }
};

Best Practices from Real-World Use

1. Always Validate Results

auto barcode = ZXing::ReadBarcode(image);

if (barcode.isValid()) {
    // Additional validation
    if (barcode.format() == ZXing::BarcodeFormat::EAN13) {
        if (!ZXing::GTIN::IsCheckDigitValid(barcode.text())) {
            // Reject invalid check digit
            return;
        }
    }
    
    // Process valid barcode
    processBarcode(barcode.text());
}

2. Log Scan Attempts

struct ScanLog {
    std::chrono::system_clock::time_point timestamp;
    bool success;
    std::string errorMessage;
    ZXing::BarcodeFormat format;
    std::string content;
};

std::vector<ScanLog> scanHistory;

void logScan(const ZXing::Barcode& barcode) {
    ScanLog log;
    log.timestamp = std::chrono::system_clock::now();
    log.success = barcode.isValid();
    
    if (barcode.isValid()) {
        log.format = barcode.format();
        log.content = barcode.text();
    } else {
        log.errorMessage = barcode.error().msg();
    }
    
    scanHistory.push_back(log);
}

3. Handle Network Failures

class RobustScanner {
    std::queue<std::string> offlineQueue;
    
public:
    void scanAndUpload(const ZXing::ImageView& image) {
        auto barcode = ZXing::ReadBarcode(image);
        
        if (barcode.isValid()) {
            if (isOnline()) {
                uploadToServer(barcode.text());
            } else {
                // Queue for later
                offlineQueue.push(barcode.text());
                saveToLocalStorage(barcode.text());
            }
        }
    }
    
    void syncOfflineScans() {
        while (!offlineQueue.empty() && isOnline()) {
            uploadToServer(offlineQueue.front());
            offlineQueue.pop();
        }
    }
};

Next Steps

  • Edge Cases - Advanced scenarios and troubleshooting
  • Quick Start Guide - Basic usage
  • API Reference - Detailed documentation