or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdexperimental-writing.mdimage-processing.mdindex.mdlegacy-writing.mdreading.mdresult-processing.md

result-processing.mddocs/

0

# Result Processing

1

2

ZXing-C++ provides comprehensive result analysis and metadata extraction through the `Result` (aliased as `Barcode`) class. This includes detailed barcode information, position data, error handling, and support for structured append sequences.

3

4

## Result Class

5

6

The `Result` class (typedef'd as `Barcode`) encapsulates all information about a decoded barcode:

7

8

```cpp { .api }

9

class Result {

10

// Constructors

11

Result() = default;

12

Result(const std::string& text, int y, int xStart, int xStop,

13

BarcodeFormat format, SymbologyIdentifier si, Error error = {},

14

bool readerInit = false);

15

16

// Validity and error checking

17

bool isValid() const;

18

const Error& error() const;

19

20

// Basic barcode information

21

BarcodeFormat format() const;

22

std::string text() const;

23

std::string text(TextMode mode) const;

24

const ByteArray& bytes() const;

25

ByteArray bytesECI() const;

26

27

// Content analysis

28

ContentType contentType() const;

29

bool hasECI() const;

30

31

// Position and orientation

32

const Position& position() const;

33

void setPosition(Position pos);

34

int orientation() const;

35

bool isMirrored() const;

36

bool isInverted() const;

37

38

// Technical metadata

39

std::string ecLevel() const;

40

std::string version() const;

41

std::string symbologyIdentifier() const;

42

bool readerInit() const;

43

int lineCount() const;

44

45

// Structured append support

46

int sequenceSize() const;

47

int sequenceIndex() const;

48

std::string sequenceId() const;

49

bool isLastInSequence() const;

50

bool isPartOfSequence() const;

51

52

// Experimental API extensions

53

#ifdef ZXING_EXPERIMENTAL_API

54

ImageView symbol() const;

55

zint_symbol* zint() const;

56

#endif

57

58

// Comparison

59

bool operator==(const Result& o) const;

60

};

61

62

// Type aliases

63

using Barcode = Result;

64

using Barcodes = std::vector<Barcode>;

65

using Position = QuadrilateralI;

66

```

67

68

## Basic Result Analysis

69

70

### Validity Checking

71

72

```cpp

73

auto result = ZXing::ReadBarcode(image);

74

75

if (result.isValid()) {

76

std::cout << "Successfully decoded barcode" << std::endl;

77

std::cout << "Content: " << result.text() << std::endl;

78

std::cout << "Format: " << ZXing::ToString(result.format()) << std::endl;

79

} else {

80

std::cout << "Failed to decode barcode" << std::endl;

81

if (result.error()) {

82

std::cout << "Error: " << result.error().msg() << std::endl;

83

}

84

}

85

```

86

87

### Content Access

88

89

```cpp

90

auto result = ZXing::ReadBarcode(image);

91

if (result.isValid()) {

92

// Get text with default mode

93

std::string defaultText = result.text();

94

95

// Get text with specific modes

96

std::string plainText = result.text(ZXing::TextMode::Plain);

97

std::string eciText = result.text(ZXing::TextMode::ECI);

98

std::string hriText = result.text(ZXing::TextMode::HRI);

99

std::string hexText = result.text(ZXing::TextMode::Hex);

100

std::string escapedText = result.text(ZXing::TextMode::Escaped);

101

102

// Access raw bytes

103

const ZXing::ByteArray& rawBytes = result.bytes();

104

ZXing::ByteArray eciBytes = result.bytesECI();

105

106

std::cout << "Raw bytes size: " << rawBytes.size() << std::endl;

107

std::cout << "Hex representation: " << hexText << std::endl;

108

}

109

```

110

111

## Content Type Analysis

112

113

### Content Classification

114

115

```cpp { .api }

116

enum class ContentType {

117

Text, Binary, Mixed, GS1, ISO15434, UnknownECI

118

};

119

```

120

121

```cpp

122

auto result = ZXing::ReadBarcode(image);

123

if (result.isValid()) {

124

ZXing::ContentType contentType = result.contentType();

125

126

switch (contentType) {

127

case ZXing::ContentType::Text:

128

std::cout << "Plain text content" << std::endl;

129

break;

130

case ZXing::ContentType::Binary:

131

std::cout << "Binary data content" << std::endl;

132

break;

133

case ZXing::ContentType::Mixed:

134

std::cout << "Mixed text and binary content" << std::endl;

135

break;

136

case ZXing::ContentType::GS1:

137

std::cout << "GS1 formatted data" << std::endl;

138

// Parse GS1 Application Identifiers

139

parseGS1Content(result.text());

140

break;

141

case ZXing::ContentType::ISO15434:

142

std::cout << "ISO 15434 formatted data" << std::endl;

143

break;

144

case ZXing::ContentType::UnknownECI:

145

std::cout << "Unknown ECI encoding" << std::endl;

146

break;

147

}

148

149

// Check for Extended Channel Interpretation

150

if (result.hasECI()) {

151

std::cout << "Contains ECI information" << std::endl;

152

}

153

}

154

```

155

156

### GS1 Data Processing

157

158

```cpp

159

void parseGS1Content(const std::string& gs1Data) {

160

// GS1 data uses Application Identifiers (AIs)

161

// Format: (AI)data(AI)data...

162

163

std::regex aiPattern(R"(\((\d{2,4})\)([^(]*))");

164

std::sregex_iterator iter(gs1Data.begin(), gs1Data.end(), aiPattern);

165

std::sregex_iterator end;

166

167

std::map<std::string, std::string> applicationIdentifiers;

168

169

for (; iter != end; ++iter) {

170

std::string ai = (*iter)[1].str();

171

std::string data = (*iter)[2].str();

172

applicationIdentifiers[ai] = data;

173

174

// Common AIs

175

if (ai == "01") {

176

std::cout << "GTIN: " << data << std::endl;

177

} else if (ai == "10") {

178

std::cout << "Batch/Lot: " << data << std::endl;

179

} else if (ai == "17") {

180

std::cout << "Expiry Date: " << data << std::endl;

181

} else if (ai == "21") {

182

std::cout << "Serial Number: " << data << std::endl;

183

}

184

}

185

}

186

```

187

188

## Position and Orientation Analysis

189

190

### Position Information

191

192

```cpp

193

auto result = ZXing::ReadBarcode(image);

194

if (result.isValid()) {

195

const ZXing::Position& position = result.position();

196

197

// Position is a QuadrilateralI with four corner points

198

auto topLeft = position.topLeft();

199

auto topRight = position.topRight();

200

auto bottomLeft = position.bottomLeft();

201

auto bottomRight = position.bottomRight();

202

203

std::cout << "Barcode corners:" << std::endl;

204

std::cout << " Top-left: (" << topLeft.x << ", " << topLeft.y << ")" << std::endl;

205

std::cout << " Top-right: (" << topRight.x << ", " << topRight.y << ")" << std::endl;

206

std::cout << " Bottom-left: (" << bottomLeft.x << ", " << bottomLeft.y << ")" << std::endl;

207

std::cout << " Bottom-right: (" << bottomRight.x << ", " << bottomRight.y << ")" << std::endl;

208

209

// Orientation in degrees

210

int orientation = result.orientation();

211

std::cout << "Orientation: " << orientation << " degrees" << std::endl;

212

213

// Check for transformations

214

if (result.isMirrored()) {

215

std::cout << "Barcode is mirrored" << std::endl;

216

}

217

218

if (result.isInverted()) {

219

std::cout << "Barcode is inverted (negative)" << std::endl;

220

}

221

}

222

```

223

224

### Geometric Calculations

225

226

```cpp

227

#include <cmath>

228

229

struct BarcodeGeometry {

230

double width;

231

double height;

232

double centerX;

233

double centerY;

234

double area;

235

};

236

237

BarcodeGeometry analyzeBarcodeGeometry(const ZXing::Position& position) {

238

auto tl = position.topLeft();

239

auto tr = position.topRight();

240

auto bl = position.bottomLeft();

241

auto br = position.bottomRight();

242

243

// Calculate dimensions (approximate for non-rectangular barcodes)

244

double topWidth = std::sqrt(std::pow(tr.x - tl.x, 2) + std::pow(tr.y - tl.y, 2));

245

double bottomWidth = std::sqrt(std::pow(br.x - bl.x, 2) + std::pow(br.y - bl.y, 2));

246

double leftHeight = std::sqrt(std::pow(bl.x - tl.x, 2) + std::pow(bl.y - tl.y, 2));

247

double rightHeight = std::sqrt(std::pow(br.x - tr.x, 2) + std::pow(br.y - tr.y, 2));

248

249

// Calculate center point

250

double centerX = (tl.x + tr.x + bl.x + br.x) / 4.0;

251

double centerY = (tl.y + tr.y + bl.y + br.y) / 4.0;

252

253

// Calculate area using shoelace formula

254

double area = 0.5 * std::abs(

255

(tl.x * tr.y - tr.x * tl.y) +

256

(tr.x * br.y - br.x * tr.y) +

257

(br.x * bl.y - bl.x * br.y) +

258

(bl.x * tl.y - tl.x * bl.y)

259

);

260

261

return {

262

(topWidth + bottomWidth) / 2.0, // width

263

(leftHeight + rightHeight) / 2.0, // height

264

centerX,

265

centerY,

266

area

267

};

268

}

269

270

// Usage

271

auto result = ZXing::ReadBarcode(image);

272

if (result.isValid()) {

273

auto geometry = analyzeBarcodeGeometry(result.position());

274

std::cout << "Barcode size: " << geometry.width << " x " << geometry.height << std::endl;

275

std::cout << "Center: (" << geometry.centerX << ", " << geometry.centerY << ")" << std::endl;

276

std::cout << "Area: " << geometry.area << " square pixels" << std::endl;

277

}

278

```

279

280

## Technical Metadata

281

282

### Format-Specific Information

283

284

```cpp

285

auto result = ZXing::ReadBarcode(image);

286

if (result.isValid()) {

287

// Error correction level (format-dependent)

288

std::string ecLevel = result.ecLevel();

289

if (!ecLevel.empty()) {

290

std::cout << "Error correction level: " << ecLevel << std::endl;

291

}

292

293

// Version information (QR Code, DataMatrix, etc.)

294

std::string version = result.version();

295

if (!version.empty()) {

296

std::cout << "Version: " << version << std::endl;

297

}

298

299

// Symbology identifier (ISO/IEC 15424)

300

std::string symbologyId = result.symbologyIdentifier();

301

if (!symbologyId.empty()) {

302

std::cout << "Symbology identifier: " << symbologyId << std::endl;

303

304

// Parse symbology identifier

305

if (symbologyId.length() >= 3) {

306

char code = symbologyId[1]; // Symbology code

307

char modifier = symbologyId[2]; // Modifier character

308

309

std::cout << "Code: " << code << ", Modifier: " << modifier << std::endl;

310

}

311

}

312

313

// Reader initialization flag

314

if (result.readerInit()) {

315

std::cout << "Reader initialization symbol" << std::endl;

316

}

317

318

// Line count (linear barcodes only)

319

int lineCount = result.lineCount();

320

if (lineCount > 0) {

321

std::cout << "Confirmed by " << lineCount << " scan lines" << std::endl;

322

}

323

}

324

```

325

326

### Quality Assessment

327

328

```cpp

329

struct BarcodeQuality {

330

bool isHighQuality;

331

std::vector<std::string> qualityIssues;

332

double confidence;

333

};

334

335

BarcodeQuality assessBarcodeQuality(const ZXing::Barcode& barcode) {

336

BarcodeQuality quality;

337

quality.isHighQuality = true;

338

quality.confidence = 1.0;

339

340

if (!barcode.isValid()) {

341

quality.isHighQuality = false;

342

quality.confidence = 0.0;

343

quality.qualityIssues.push_back("Invalid barcode");

344

return quality;

345

}

346

347

// Check line count for linear barcodes

348

if (barcode.lineCount() > 0 && barcode.lineCount() < 2) {

349

quality.isHighQuality = false;

350

quality.confidence *= 0.7;

351

quality.qualityIssues.push_back("Low line count confirmation");

352

}

353

354

// Check for inversions (may indicate poor image quality)

355

if (barcode.isInverted()) {

356

quality.confidence *= 0.9;

357

quality.qualityIssues.push_back("Inverted barcode detected");

358

}

359

360

// Check for mirroring (unusual)

361

if (barcode.isMirrored()) {

362

quality.confidence *= 0.8;

363

quality.qualityIssues.push_back("Mirrored barcode detected");

364

}

365

366

// Check error correction level

367

std::string ecLevel = barcode.ecLevel();

368

if (!ecLevel.empty()) {

369

// Lower error correction levels indicate less redundancy

370

if (ecLevel == "L" || ecLevel == "0") {

371

quality.confidence *= 0.95;

372

}

373

}

374

375

quality.isHighQuality = quality.confidence > 0.8;

376

return quality;

377

}

378

```

379

380

## Structured Append Processing

381

382

### Sequence Detection

383

384

```cpp

385

void analyzeSequence(const ZXing::Barcode& barcode) {

386

if (barcode.isPartOfSequence()) {

387

int size = barcode.sequenceSize();

388

int index = barcode.sequenceIndex();

389

std::string id = barcode.sequenceId();

390

391

std::cout << "Part of structured append sequence:" << std::endl;

392

std::cout << " Position: " << (index + 1) << " of " << size << std::endl;

393

std::cout << " Sequence ID: " << id << std::endl;

394

395

if (barcode.isLastInSequence()) {

396

std::cout << " This is the last part" << std::endl;

397

}

398

399

// Handle unknown sequence size (PDF417)

400

if (size == 0) {

401

std::cout << " Unknown total sequence size" << std::endl;

402

}

403

} else {

404

std::cout << "Single barcode (not part of sequence)" << std::endl;

405

}

406

}

407

```

408

409

### Sequence Collection and Merging

410

411

```cpp

412

class SequenceCollector {

413

private:

414

std::map<std::string, std::vector<ZXing::Barcode>> sequences_;

415

416

public:

417

void addBarcode(const ZXing::Barcode& barcode) {

418

if (!barcode.isPartOfSequence()) {

419

// Process single barcode immediately

420

processSingleBarcode(barcode);

421

return;

422

}

423

424

std::string sequenceId = barcode.sequenceId();

425

sequences_[sequenceId].push_back(barcode);

426

427

// Check if sequence is complete

428

if (isSequenceComplete(sequenceId)) {

429

processCompleteSequence(sequenceId);

430

}

431

}

432

433

private:

434

bool isSequenceComplete(const std::string& sequenceId) {

435

auto& sequence = sequences_[sequenceId];

436

437

if (sequence.empty()) return false;

438

439

int expectedSize = sequence[0].sequenceSize();

440

if (expectedSize == 0) {

441

// Unknown size - check for last marker

442

return std::any_of(sequence.begin(), sequence.end(),

443

[](const ZXing::Barcode& b) { return b.isLastInSequence(); });

444

}

445

446

// Known size - check if we have all parts

447

if (static_cast<int>(sequence.size()) != expectedSize) {

448

return false;

449

}

450

451

// Verify we have all indices

452

std::set<int> indices;

453

for (const auto& barcode : sequence) {

454

indices.insert(barcode.sequenceIndex());

455

}

456

457

return static_cast<int>(indices.size()) == expectedSize &&

458

*indices.begin() == 0 &&

459

*indices.rbegin() == expectedSize - 1;

460

}

461

462

void processCompleteSequence(const std::string& sequenceId) {

463

auto& sequence = sequences_[sequenceId];

464

465

// Sort by sequence index

466

std::sort(sequence.begin(), sequence.end(),

467

[](const ZXing::Barcode& a, const ZXing::Barcode& b) {

468

return a.sequenceIndex() < b.sequenceIndex();

469

});

470

471

// Merge sequence using library function

472

auto merged = ZXing::MergeStructuredAppendSequence(sequence);

473

474

if (merged.isValid()) {

475

std::cout << "Successfully merged sequence " << sequenceId << std::endl;

476

std::cout << "Merged content: " << merged.text() << std::endl;

477

478

// Process merged result

479

processSingleBarcode(merged);

480

} else {

481

std::cout << "Failed to merge sequence " << sequenceId << std::endl;

482

}

483

484

// Clean up

485

sequences_.erase(sequenceId);

486

}

487

488

void processSingleBarcode(const ZXing::Barcode& barcode) {

489

// Your barcode processing logic here

490

std::cout << "Processing: " << barcode.text() << std::endl;

491

}

492

};

493

494

// Usage

495

SequenceCollector collector;

496

auto results = ZXing::ReadBarcodes(image);

497

498

for (const auto& result : results) {

499

collector.addBarcode(result);

500

}

501

```

502

503

### Automatic Sequence Merging

504

505

```cpp

506

// Simplified approach using library functions

507

std::vector<ZXing::Barcode> processImageWithSequenceMerging(const ZXing::ImageView& image) {

508

// Read all barcodes

509

auto allResults = ZXing::ReadBarcodes(image);

510

511

// Automatically merge structured append sequences

512

auto mergedResults = ZXing::MergeStructuredAppendSequences(allResults);

513

514

std::cout << "Found " << allResults.size() << " individual barcodes" << std::endl;

515

std::cout << "After merging: " << mergedResults.size() << " results" << std::endl;

516

517

return mergedResults;

518

}

519

```

520

521

## Error Handling and Analysis

522

523

### Comprehensive Error Analysis

524

525

```cpp

526

void analyzeErrors(const std::vector<ZXing::Barcode>& results) {

527

std::map<ZXing::Error::Type, int> errorCounts;

528

std::vector<ZXing::Barcode> validResults;

529

std::vector<ZXing::Barcode> errorResults;

530

531

for (const auto& result : results) {

532

if (result.isValid()) {

533

validResults.push_back(result);

534

} else {

535

errorResults.push_back(result);

536

errorCounts[result.error().type()]++;

537

}

538

}

539

540

std::cout << "Results summary:" << std::endl;

541

std::cout << " Valid: " << validResults.size() << std::endl;

542

std::cout << " Errors: " << errorResults.size() << std::endl;

543

544

if (!errorResults.empty()) {

545

std::cout << "Error breakdown:" << std::endl;

546

for (const auto& [type, count] : errorCounts) {

547

std::string typeName;

548

switch (type) {

549

case ZXing::Error::Format: typeName = "Format"; break;

550

case ZXing::Error::Checksum: typeName = "Checksum"; break;

551

case ZXing::Error::Unsupported: typeName = "Unsupported"; break;

552

default: typeName = "Unknown"; break;

553

}

554

std::cout << " " << typeName << ": " << count << std::endl;

555

}

556

}

557

}

558

```

559

560

## Performance Monitoring

561

562

### Result Processing Metrics

563

564

```cpp

565

struct ProcessingMetrics {

566

std::chrono::milliseconds detectionTime;

567

int totalBarcodes;

568

int validBarcodes;

569

int errorBarcodes;

570

std::map<ZXing::BarcodeFormat, int> formatCounts;

571

};

572

573

ProcessingMetrics processImageWithMetrics(const ZXing::ImageView& image) {

574

auto start = std::chrono::high_resolution_clock::now();

575

576

auto results = ZXing::ReadBarcodes(image);

577

578

auto end = std::chrono::high_resolution_clock::now();

579

auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

580

581

ProcessingMetrics metrics;

582

metrics.detectionTime = duration;

583

metrics.totalBarcodes = results.size();

584

585

for (const auto& result : results) {

586

if (result.isValid()) {

587

metrics.validBarcodes++;

588

metrics.formatCounts[result.format()]++;

589

} else {

590

metrics.errorBarcodes++;

591

}

592

}

593

594

return metrics;

595

}

596

597

void printMetrics(const ProcessingMetrics& metrics) {

598

std::cout << "Processing completed in " << metrics.detectionTime.count() << "ms" << std::endl;

599

std::cout << "Total barcodes: " << metrics.totalBarcodes << std::endl;

600

std::cout << "Valid: " << metrics.validBarcodes << std::endl;

601

std::cout << "Errors: " << metrics.errorBarcodes << std::endl;

602

603

if (!metrics.formatCounts.empty()) {

604

std::cout << "Format distribution:" << std::endl;

605

for (const auto& [format, count] : metrics.formatCounts) {

606

std::cout << " " << ZXing::ToString(format) << ": " << count << std::endl;

607

}

608

}

609

}

610

```

611

612

## Structured Append Utility Functions

613

614

```cpp { .api }

615

/**

616

* Merge a list of Barcodes from one Structured Append sequence to a single barcode

617

*/

618

Barcode MergeStructuredAppendSequence(const Barcodes& results);

619

620

/**

621

* Automatically merge all Structured Append sequences found in the given list of barcodes

622

*/

623

Barcodes MergeStructuredAppendSequences(const Barcodes& barcodes);

624

```