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++ provides geometry types for representing barcode positions, points, and quadrilaterals. These types are used to describe where barcodes are located in images.
template <typename T>
struct PointT {
T x;
T y;
// Constructors
constexpr PointT(); // Default (0, 0)
constexpr PointT(T x, T y);
template <typename U>
explicit PointT(const PointT<U>& p); // Convert from other type
// Operators
template <typename U>
PointT& operator+=(const PointT<U>& b);
};
// Common type aliases
using PointI = PointT<int>; // Integer point
using PointF = PointT<double>; // Floating-point point// Comparison
bool operator==(const PointT<T>&, const PointT<T>&);
bool operator!=(const PointT<T>&, const PointT<T>&);
// Arithmetic
PointT<T> operator-(const PointT<T>&); // Negation
auto operator+(const PointT<T>&, const PointT<U>&); // Addition
auto operator-(const PointT<T>&, const PointT<U>&); // Subtraction
auto operator*(const PointT<T>&, const PointT<U>&); // Element-wise multiply
PointT<T> operator*(U scalar, const PointT<T>&); // Scalar multiply
PointT<T> operator/(const PointT<T>&, U scalar); // Scalar divide
// Geometric functions
auto dot(const PointT<T>&, const PointT<U>&); // Dot product
auto cross(PointT<T>, PointT<T>); // Cross product (2D)
T sumAbsComponent(PointT<T>); // L1 norm (Manhattan)
auto length(PointT<T>); // L2 norm (Euclidean)
T maxAbsComponent(PointT<T>); // L-infinity norm
auto distance(PointT<T>, PointT<T>); // Distance between points
PointF centered(PointI); // Get pixel center
PointF centered(PointF); // Get pixel center
PointF normalized(PointT<T>); // Normalize to unit vector
PointT<T> bresenhamDirection(PointT<T>); // Bresenham line direction
PointT<T> mainDirection(PointT<T>); // Main axis direction// Integer points
ZXing::PointI p1; // (0, 0)
ZXing::PointI p2(100, 50); // (100, 50)
ZXing::PointI p3{200, 150}; // (200, 150)
// Floating-point points
ZXing::PointF pf1; // (0.0, 0.0)
ZXing::PointF pf2(100.5, 50.3);
// Convert between types
ZXing::PointI pi(100, 50);
ZXing::PointF pf(pi); // Explicit conversionZXing::PointI point(100, 50);
int x = point.x;
int y = point.y;
std::cout << "Point: (" << x << ", " << y << ")\n";ZXing::PointI p1(100, 50);
ZXing::PointI p2(30, 20);
// Addition
ZXing::PointI sum = p1 + p2; // (130, 70)
// Subtraction
ZXing::PointI diff = p1 - p2; // (70, 30)
// Negation
ZXing::PointI neg = -p1; // (-100, -50)
// Scalar multiplication
ZXing::PointI scaled = 2 * p1; // (200, 100)
// Scalar division
ZXing::PointI divided = p1 / 2; // (50, 25)
// In-place addition
p1 += p2; // p1 is now (130, 70)ZXing::PointI p1(3, 4);
ZXing::PointI p2(1, 2);
// Dot product
auto dot = ZXing::dot(p1, p2); // 3*1 + 4*2 = 11
// Cross product (z-component of 3D cross in xy-plane)
auto cross = ZXing::cross(p1, p2); // 3*2 - 4*1 = 2
// Distance
auto dist = ZXing::distance(p1, p2); // sqrt((3-1)^2 + (4-2)^2)
// Length/magnitude
auto len = ZXing::length(p1); // sqrt(3^2 + 4^2) = 5.0
// Normalize to unit vector
ZXing::PointF normalized = ZXing::normalized(p1); // (0.6, 0.8)
// Manhattan distance (L1 norm)
int manhattan = ZXing::sumAbsComponent(p1); // |3| + |4| = 7
// Chebyshev distance (L-inf norm)
int chebyshev = ZXing::maxAbsComponent(p1); // max(|3|, |4|) = 4// Convert integer pixel coordinate to floating-point center
ZXing::PointI pixel(10, 20);
ZXing::PointF center = ZXing::centered(pixel); // (10.5, 20.5)template <typename T>
class Quadrilateral : public std::array<T, 4> {
public:
using Point = T;
// Constructors
Quadrilateral(); // Default
Quadrilateral(T tl, T tr, T br, T bl); // Four corners
template <typename U>
Quadrilateral(PointT<U> tl, PointT<U> tr,
PointT<U> br, PointT<U> bl);
// Corner accessors
constexpr Point topLeft() const;
constexpr Point topRight() const;
constexpr Point bottomRight() const;
constexpr Point bottomLeft() const;
// Orientation
double orientation() const; // Angle in radians
};
// Type aliases
using QuadrilateralF = Quadrilateral<PointF>;
using QuadrilateralI = Quadrilateral<PointI>;
using Position = QuadrilateralI; // Used in Barcode class// Create rectangle
Quadrilateral<PointT> Rectangle(int width, int height,
typename PointT::value_t margin = 0);
// Create centered square
Quadrilateral<PointT> CenteredSquare(int size);
// Create line (for linear barcodes)
Quadrilateral<PointT> Line(int y, int xStart, int xStop);// Validation
bool IsConvex(const Quadrilateral<PointT>&);
// Transformation
Quadrilateral<PointT> Scale(const Quadrilateral<PointT>&, int factor);
Quadrilateral<PointT> RotatedCorners(const Quadrilateral<PointT>&,
int n, bool mirror);
// Geometry
PointT Center(const Quadrilateral<PointT>&);
Quadrilateral<PointT> BoundingBox(const Quadrilateral<PointT>&);
bool IsInside(const PointT&, const Quadrilateral<PointT>&);
bool HaveIntersectingBoundingBoxes(const Quadrilateral<PointT>&,
const Quadrilateral<PointT>&);
Quadrilateral<PointT> Blend(const Quadrilateral<PointT>&,
const Quadrilateral<PointT>&);
// Conversion
std::string ToString(const Quadrilateral<PointT<T>>&);auto barcode = ZXing::ReadBarcode(image);
if (barcode.isValid()) {
// Get position (quadrilateral)
const ZXing::Position& pos = barcode.position();
// Access corners
ZXing::PointI tl = pos.topLeft();
ZXing::PointI tr = pos.topRight();
ZXing::PointI br = pos.bottomRight();
ZXing::PointI bl = pos.bottomLeft();
std::cout << "Top-left: (" << tl.x << ", " << tl.y << ")\n";
std::cout << "Top-right: (" << tr.x << ", " << tr.y << ")\n";
std::cout << "Bottom-right: (" << br.x << ", " << br.y << ")\n";
std::cout << "Bottom-left: (" << bl.x << ", " << bl.y << ")\n";
}// Create from four points
ZXing::PointI tl(10, 10);
ZXing::PointI tr(110, 10);
ZXing::PointI br(110, 110);
ZXing::PointI bl(10, 110);
ZXing::QuadrilateralI quad(tl, tr, br, bl);
// Create rectangle
auto rect = ZXing::Rectangle<ZXing::PointI>(200, 100, 10); // 10px margin
// Create centered square
auto square = ZXing::CenteredSquare<ZXing::PointI>(100);
// Create line (for linear barcode position)
auto line = ZXing::Line<ZXing::PointI>(50, 10, 200); // y=50, x=10 to 200Quadrilateral extends std::array<T, 4>:
ZXing::QuadrilateralI quad(/* ... */);
// Array-style indexing (0=TL, 1=TR, 2=BR, 3=BL)
ZXing::PointI corner0 = quad[0]; // Top-left
ZXing::PointI corner1 = quad[1]; // Top-right
ZXing::PointI corner2 = quad[2]; // Bottom-right
ZXing::PointI corner3 = quad[3]; // Bottom-left
// Iterate corners
for (const auto& corner : quad) {
std::cout << "(" << corner.x << ", " << corner.y << ")\n";
}
// Size is always 4
static_assert(quad.size() == 4);ZXing::QuadrilateralI quad(/* ... */);
// Get center point
ZXing::PointI center = ZXing::Center(quad);
// Get bounding box (axis-aligned rectangle)
ZXing::QuadrilateralI bbox = ZXing::BoundingBox(quad);
// Check if convex
if (ZXing::IsConvex(quad)) {
std::cout << "Quadrilateral is convex\n";
}
// Get orientation
double angle = quad.orientation(); // Radians
int degrees = static_cast<int>(angle * 180.0 / M_PI);
// Scale
ZXing::QuadrilateralI scaled = ZXing::Scale(quad, 2); // 2x larger
// Check if point is inside
ZXing::PointI point(50, 50);
if (ZXing::IsInside(point, quad)) {
std::cout << "Point is inside quadrilateral\n";
}ZXing::QuadrilateralI quad1(/* ... */);
ZXing::QuadrilateralI quad2(/* ... */);
// Check if bounding boxes intersect (fast approximation)
if (ZXing::HaveIntersectingBoundingBoxes(quad1, quad2)) {
std::cout << "Quadrilaterals may overlap\n";
}// Blend two quadrilaterals (average their corners)
ZXing::QuadrilateralI quad1(/* ... */);
ZXing::QuadrilateralI quad2(/* ... */);
ZXing::QuadrilateralI blended = ZXing::Blend(quad1, quad2);ZXing::QuadrilateralI quad(/* ... */);
std::string str = ZXing::ToString(quad);
std::cout << "Position: " << str << "\n";
// Output example: "[(10,10), (110,10), (110,110), (10,110)]"void drawBarcode(const ZXing::Barcode& barcode) {
if (!barcode.isValid()) return;
const ZXing::Position& pos = barcode.position();
// Draw quadrilateral outline
drawLine(pos.topLeft(), pos.topRight(), color_green);
drawLine(pos.topRight(), pos.bottomRight(), color_green);
drawLine(pos.bottomRight(), pos.bottomLeft(), color_green);
drawLine(pos.bottomLeft(), pos.topLeft(), color_green);
// Draw corner markers
drawCircle(pos.topLeft(), 5, color_red);
drawCircle(pos.topRight(), 5, color_red);
drawCircle(pos.bottomRight(), 5, color_red);
drawCircle(pos.bottomLeft(), 5, color_red);
// Draw center point
ZXing::PointI center = ZXing::Center(pos);
drawCircle(center, 3, color_blue);
}ZXing-C++ uses standard image coordinates:
(0,0) ────────> X
│
│
│
v
YLinear (1D) barcodes return a position with:
// Linear barcode typically has rectangular position
if (barcode.format() == ZXing::BarcodeFormat::Code128) {
auto pos = barcode.position();
// pos forms a rectangle
}2D barcodes return accurate corner positions:
// 2D barcodes can be rotated or skewed
if (barcode.format() == ZXing::BarcodeFormat::QRCode) {
auto pos = barcode.position();
// pos may be a general quadrilateral (not necessarily axis-aligned)
}// Create or modify a barcode's position
ZXing::Barcode barcode = /* ... */;
ZXing::QuadrilateralI newPos(
ZXing::PointI(10, 10),
ZXing::PointI(110, 15),
ZXing::PointI(105, 115),
ZXing::PointI(5, 110)
);
barcode.setPosition(newPos);