tessl install tessl/github-zxing-cpp--zxing-cpp@2.3.0Open-source, multi-format linear/matrix barcode image processing library implemented in C++
The ZXing::GTIN namespace provides utilities for working with Global Trade Item Numbers (GTIN) and GS1 standards. These functions are useful for processing retail barcodes like UPC and EAN.
All GTIN utilities are in the ZXing::GTIN namespace:
namespace ZXing::GTIN {
// Check digit computation
template <typename T>
T ComputeCheckDigit(const std::basic_string<T>& digits,
bool skipTail = false);
// Check digit validation
template <typename T>
bool IsCheckDigitValid(const std::basic_string<T>& s);
// Country/origin lookup
std::string LookupCountryIdentifier(const std::string& GTIN,
const BarcodeFormat format = BarcodeFormat::None);
// EAN add-on support
std::string EanAddOn(const Barcode& barcode);
std::string IssueNr(const std::string& ean2AddOn);
std::string Price(const std::string& ean5AddOn);
}GTIN check digits use modulo-10 algorithm:
#include "ZXing/GTIN.h"
// Compute check digit for EAN-13 (12 digits + check)
std::string ean12 = "400638133393";
char checkDigit = ZXing::GTIN::ComputeCheckDigit(ean12);
std::cout << "Check digit: " << checkDigit << "\n"; // "1"
std::string fullEan13 = ean12 + checkDigit;
std::cout << "Full EAN-13: " << fullEan13 << "\n"; // "4006381333931"Works with different string types:
// char strings
std::string digits = "12345678901";
char check = ZXing::GTIN::ComputeCheckDigit(digits);
// Wide character strings
std::wstring wdigits = L"12345678901";
wchar_t wcheck = ZXing::GTIN::ComputeCheckDigit(wdigits);When computing for partial numbers:
// Skip last digit during computation (useful for in-place calculation)
std::string partialEan = "40063813339X";
char check = ZXing::GTIN::ComputeCheckDigit(partialEan, true);#include "ZXing/GTIN.h"
// Validate EAN-13
std::string ean13 = "4006381333931";
if (ZXing::GTIN::IsCheckDigitValid(ean13)) {
std::cout << "Valid EAN-13\n";
} else {
std::cout << "Invalid check digit\n";
}
// Validate UPC-A
std::string upca = "012345678905";
if (ZXing::GTIN::IsCheckDigitValid(upca)) {
std::cout << "Valid UPC-A\n";
}auto barcode = ZXing::ReadBarcode(image);
if (barcode.format() == ZXing::BarcodeFormat::EAN13) {
std::string code = barcode.text();
if (ZXing::GTIN::IsCheckDigitValid(code)) {
std::cout << "Valid GTIN\n";
} else {
std::cerr << "Check digit validation failed\n";
// May indicate scanning error or damaged barcode
}
}#include "ZXing/GTIN.h"
auto barcode = ZXing::ReadBarcode(image);
if (barcode.isValid()) {
std::string country = ZXing::GTIN::LookupCountryIdentifier(
barcode.text(), barcode.format());
if (!country.empty()) {
std::cout << "Country/Origin: " << country << "\n";
} else {
std::cout << "Country unknown or not applicable\n";
}
}Common GS1 prefixes:
// "000" - "019" : USA and Canada
// "020" - "029" : Restricted distribution (coupons, etc.)
// "030" - "039" : USA
// "040" - "049" : Restricted distribution
// "050" - "059" : Coupons
// "060" - "099" : USA and Canada
// "100" - "139" : USA
// "200" - "299" : Restricted distribution
// "300" - "379" : France and Monaco
// "380" : Bulgaria
// "383" : Slovenia
// "385" : Croatia
// "400" - "440" : Germany
// "450" - "459" : Japan
// "460" - "469" : Russia
// "470" : Kyrgyzstan
// "471" : Taiwan
// "474" : Estonia
// "475" : Latvia
// "476" : Azerbaijan
// "477" : Lithuania
// "478" : Uzbekistan
// "479" : Sri Lanka
// "480" : Philippines
// "481" : Belarus
// "482" : Ukraine
// "484" : Moldova
// "485" : Armenia
// "486" : Georgia
// "487" : Kazakhstan
// "488" : Tajikistan
// "489" : Hong Kong
// "490" - "499" : Japan
// "500" - "509" : UK
// "520" - "521" : Greece
// "528" : Lebanon
// "529" : Cyprus
// "530" : Albania
// "531" : Macedonia
// "535" : Malta
// "539" : Ireland
// "540" - "549" : Belgium and Luxembourg
// "560" : Portugal
// "569" : Iceland
// "570" - "579" : Denmark
// "590" : Poland
// "594" : Romania
// "599" : Hungary
// "600" - "601" : South Africa
// "603" : Ghana
// "604" : Senegal
// "608" : Bahrain
// "609" : Mauritius
// "611" : Morocco
// "613" : Algeria
// "615" : Nigeria
// "616" : Kenya
// "618" : Ivory Coast
// "619" : Tunisia
// "620" : Tanzania
// "621" : Syria
// "622" : Egypt
// "623" : Brunei
// "624" : Libya
// "625" : Jordan
// "626" : Iran
// "627" : Kuwait
// "628" : Saudi Arabia
// "629" : United Arab Emirates
// "640" - "649" : Finland
// "690" - "699" : China
// "700" - "709" : Norway
// "729" : Israel
// "730" - "739" : Sweden
// "740" : Guatemala
// "741" : El Salvador
// "742" : Honduras
// "743" : Nicaragua
// "744" : Costa Rica
// "745" : Panama
// "746" : Dominican Republic
// "750" : Mexico
// "754" - "755" : Canada
// "759" : Venezuela
// "760" - "769" : Switzerland
// "770" - "771" : Colombia
// "773" : Uruguay
// "775" : Peru
// "777" : Bolivia
// "778" - "779" : Argentina
// "780" : Chile
// "784" : Paraguay
// "786" : Ecuador
// "789" - "790" : Brazil
// "800" - "839" : Italy
// "840" - "849" : Spain
// "850" : Cuba
// "858" : Slovakia
// "859" : Czech Republic
// "860" : Serbia
// "865" : Mongolia
// "867" : North Korea
// "868" - "869" : Turkey
// "870" - "879" : Netherlands
// "880" : South Korea
// "884" : Cambodia
// "885" : Thailand
// "888" : Singapore
// "890" : India
// "893" : Vietnam
// "896" : Pakistan
// "899" : Indonesia
// "900" - "919" : Austria
// "930" - "939" : Australia
// "940" - "949" : New Zealand
// "955" : Malaysia
// "958" : Macau
// "977" : ISSN (Serial publications)
// "978" - "979" : ISBN (Books)
// "980" : Refund receipts
// "981" - "984" : Common Currency Coupons
// "990" - "999" : Coupons
std::string code = "4006381333931"; // Starts with "400"
std::string country = ZXing::GTIN::LookupCountryIdentifier(code);
// Returns: "Germany"// Without format (auto-detect)
std::string country1 = ZXing::GTIN::LookupCountryIdentifier("4006381333931");
// With explicit format
std::string country2 = ZXing::GTIN::LookupCountryIdentifier(
"4006381333931", ZXing::BarcodeFormat::EAN13);EAN-13 and EAN-8 can have 2-digit or 5-digit add-on symbols:
#include "ZXing/GTIN.h"
auto barcode = ZXing::ReadBarcode(image);
if (barcode.format() == ZXing::BarcodeFormat::EAN13 ||
barcode.format() == ZXing::BarcodeFormat::EAN8) {
std::string addOn = ZXing::GTIN::EanAddOn(barcode);
if (!addOn.empty()) {
std::cout << "Add-on: " << addOn << "\n";
if (addOn.length() == 2) {
std::cout << "EAN-2 add-on (magazine issue)\n";
} else if (addOn.length() == 5) {
std::cout << "EAN-5 add-on (book price)\n";
}
} else {
std::cout << "No add-on present\n";
}
}// Configure reader to look for add-ons
auto options = ZXing::ReaderOptions()
.setFormats(ZXing::BarcodeFormat::EAN13)
.setEanAddOnSymbol(ZXing::EanAddOnSymbol::Read);
auto barcode = ZXing::ReadBarcode(image, options);
std::string addOn = ZXing::GTIN::EanAddOn(barcode);EAN-2 add-ons encode magazine issue numbers:
#include "ZXing/GTIN.h"
auto barcode = ZXing::ReadBarcode(image);
std::string addOn = ZXing::GTIN::EanAddOn(barcode);
if (addOn.length() == 2) {
std::string issue = ZXing::GTIN::IssueNr(addOn);
std::cout << "Magazine issue: " << issue << "\n";
}// EAN-2 values represent issue numbers
// "01" = Issue 1
// "52" = Issue 52 (weekly publication)
// "12" = Issue 12 (monthly publication)
std::string issue = ZXing::GTIN::IssueNr("06");
// Returns: "6"EAN-5 add-ons encode book prices:
#include "ZXing/GTIN.h"
auto barcode = ZXing::ReadBarcode(image);
std::string addOn = ZXing::GTIN::EanAddOn(barcode);
if (addOn.length() == 5) {
std::string price = ZXing::GTIN::Price(addOn);
if (!price.empty()) {
std::cout << "Price: " << price << "\n";
}
}EAN-5 encoding:
// "51299" = $12.99 USD
// "51995" = $19.95 USD
// "50000" = Free or no price
// "59999" = $99.99 USD (max)
std::string price1 = ZXing::GTIN::Price("51299");
// Returns: "$12.99" or "12.99" depending on implementation
std::string price2 = ZXing::GTIN::Price("50000");
// Returns: "" (no price)// First digit of EAN-5 indicates currency:
// 0 = Pound Sterling (£)
// 1 = (Not used)
// 2 = (Not used)
// 3 = Australian Dollar (A$)
// 4 = New Zealand Dollar (NZ$)
// 5 = US Dollar ($)
// 6 = Canadian Dollar (C$)
// 7 = (Not used)
// 8 = (Not used)
// 9 = (Reserved)// GTIN-8 (EAN-8) : 8 digits
// GTIN-12 (UPC-A) : 12 digits
// GTIN-13 (EAN-13) : 13 digits
// GTIN-14 (ITF-14) : 14 digits (shipping containers)
bool isGtinFormat(ZXing::BarcodeFormat format) {
return format == ZXing::BarcodeFormat::EAN8 ||
format == ZXing::BarcodeFormat::EAN13 ||
format == ZXing::BarcodeFormat::UPCA ||
format == ZXing::BarcodeFormat::UPCE ||
format == ZXing::BarcodeFormat::ITF;
}UPC-E is a compressed form of UPC-A:
// UPC-E: 6 digits (plus check digit)
// UPC-A: 12 digits
// ZXing automatically expands UPC-E to UPC-A format
auto barcode = ZXing::ReadBarcode(image);
if (barcode.format() == ZXing::BarcodeFormat::UPCE) {
std::string expanded = barcode.text();
// Returns expanded 12-digit UPC-A
std::cout << "Expanded: " << expanded << "\n";
}For DataBar and other GS1 formats:
if (barcode.contentType() == ZXing::ContentType::GS1) {
std::cout << "GS1-formatted content\n";
// Content uses GS1 Application Identifiers
std::string gs1Data = barcode.text();
// Parse GS1 AIs (application-specific parsing)
// Common AIs:
// (01) = GTIN
// (10) = Batch/Lot number
// (17) = Expiration date
// (21) = Serial number
// etc.
}#include "ZXing/ReadBarcode.h"
#include "ZXing/GTIN.h"
void processRetailBarcode(const ZXing::ImageView& image) {
auto options = ZXing::ReaderOptions()
.setFormats(ZXing::BarcodeFormat::EAN13 |
ZXing::BarcodeFormat::EAN8 |
ZXing::BarcodeFormat::UPCA |
ZXing::BarcodeFormat::UPCE)
.setEanAddOnSymbol(ZXing::EanAddOnSymbol::Read);
auto barcode = ZXing::ReadBarcode(image, options);
if (!barcode.isValid()) {
std::cerr << "No barcode found\n";
return;
}
// Get code
std::string code = barcode.text();
std::cout << "Code: " << code << "\n";
// Validate check digit
if (!ZXing::GTIN::IsCheckDigitValid(code)) {
std::cerr << "Warning: Invalid check digit\n";
}
// Get country
std::string country = ZXing::GTIN::LookupCountryIdentifier(
code, barcode.format());
if (!country.empty()) {
std::cout << "Origin: " << country << "\n";
}
// Check for add-on
std::string addOn = ZXing::GTIN::EanAddOn(barcode);
if (!addOn.empty()) {
std::cout << "Add-on: " << addOn << "\n";
if (addOn.length() == 2) {
std::cout << "Issue: " << ZXing::GTIN::IssueNr(addOn) << "\n";
} else if (addOn.length() == 5) {
std::string price = ZXing::GTIN::Price(addOn);
if (!price.empty()) {
std::cout << "Price: " << price << "\n";
}
}
}
}// For critical applications, always validate
if (!ZXing::GTIN::IsCheckDigitValid(code)) {
// Reject or flag for manual review
logError("Invalid GTIN check digit");
}// Not all GTIN ranges have country assignments
std::string country = ZXing::GTIN::LookupCountryIdentifier(code);
if (country.empty()) {
// May be restricted distribution, coupon, or other special code
std::cout << "No country assignment\n";
}// Don't require add-on unless specifically needed
std::string addOn = ZXing::GTIN::EanAddOn(barcode);
if (addOn.empty()) {
// Most products don't have add-ons - this is normal
}