or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated

docs

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++

geometry.mddocs/reference/

Geometry and Position

ZXing-C++ provides geometry types for representing barcode positions, points, and quadrilaterals. These types are used to describe where barcodes are located in images.

Point Types

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

Point Operations

// 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

Using Points

Creating Points

// 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 conversion

Accessing Coordinates

ZXing::PointI point(100, 50);

int x = point.x;
int y = point.y;

std::cout << "Point: (" << x << ", " << y << ")\n";

Point Arithmetic

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)

Geometric Calculations

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

Pixel Centers

// Convert integer pixel coordinate to floating-point center
ZXing::PointI pixel(10, 20);
ZXing::PointF center = ZXing::centered(pixel);  // (10.5, 20.5)

Quadrilateral Type

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

Quadrilateral Factory Functions

// 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);

Quadrilateral Operations

// 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>>&);

Using Quadrilaterals

Getting Barcode Position

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";
}

Creating Quadrilaterals

// 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 200

Array-Style Access

Quadrilateral 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);

Quadrilateral Geometry

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";
}

Detecting Overlaps

ZXing::QuadrilateralI quad1(/* ... */);
ZXing::QuadrilateralI quad2(/* ... */);

// Check if bounding boxes intersect (fast approximation)
if (ZXing::HaveIntersectingBoundingBoxes(quad1, quad2)) {
    std::cout << "Quadrilaterals may overlap\n";
}

Blending Quadrilaterals

// Blend two quadrilaterals (average their corners)
ZXing::QuadrilateralI quad1(/* ... */);
ZXing::QuadrilateralI quad2(/* ... */);

ZXing::QuadrilateralI blended = ZXing::Blend(quad1, quad2);

Converting to String

ZXing::QuadrilateralI quad(/* ... */);

std::string str = ZXing::ToString(quad);
std::cout << "Position: " << str << "\n";
// Output example: "[(10,10), (110,10), (110,110), (10,110)]"

Drawing Barcode Positions

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);
}

Coordinate System

ZXing-C++ uses standard image coordinates:

  • Origin (0, 0) is at top-left of image
  • X-axis increases to the right
  • Y-axis increases downward
(0,0) ────────> X
  │
  │
  │
  v
  Y

Position Accuracy

Linear Barcodes

Linear (1D) barcodes return a position with:

  • Top-left and top-right at the top edge
  • Bottom-left and bottom-right at the bottom edge
  • X coordinates span the barcode width
// Linear barcode typically has rectangular position
if (barcode.format() == ZXing::BarcodeFormat::Code128) {
    auto pos = barcode.position();
    // pos forms a rectangle
}

2D Barcodes

2D barcodes return accurate corner positions:

  • QR Code: corners of the finder pattern area
  • Data Matrix: corners of the timing pattern area
  • Aztec: corners of the bull's eye area
// 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)
}

Setting Position

// 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);

Related

  • Barcode Results - Using position in Barcode results
  • Barcode Reading - Detection returns position information
  • Images - Image coordinate system and dimensions