0
# Legacy Barcode Writing
1
2
ZXing-C++ provides barcode generation capabilities through the legacy `MultiFormatWriter` API. This stable API supports the most common barcode formats with essential configuration options, generating barcodes as `BitMatrix` objects that can be converted to various image formats.
3
4
## MultiFormatWriter Class
5
6
The `MultiFormatWriter` class provides a simple interface for generating barcodes:
7
8
```cpp { .api }
9
class MultiFormatWriter {
10
explicit MultiFormatWriter(BarcodeFormat format);
11
12
// Configuration methods
13
MultiFormatWriter& setEncoding(CharacterSet encoding);
14
MultiFormatWriter& setEccLevel(int level);
15
MultiFormatWriter& setMargin(int margin);
16
17
// Generation methods
18
BitMatrix encode(const std::wstring& contents, int width, int height) const;
19
BitMatrix encode(const std::string& contents, int width, int height) const;
20
};
21
```
22
23
## BitMatrix Class
24
25
The `BitMatrix` class represents the generated barcode as a 2D binary matrix:
26
27
```cpp { .api }
28
class BitMatrix {
29
int width() const;
30
int height() const;
31
bool get(int x, int y) const;
32
void set(int x, int y, bool value);
33
34
// Iterator support and utility methods available
35
};
36
```
37
38
## Supported Formats
39
40
The legacy writer supports these formats:
41
42
- **Linear Formats**: Code 39, Code 93, Code 128, Codabar, EAN-8, EAN-13, ITF, UPC-A, UPC-E
43
- **Matrix Formats**: Aztec, DataMatrix, PDF417, QR Code
44
45
## Basic Usage
46
47
### Simple Barcode Generation
48
49
```cpp
50
#include "ZXing/MultiFormatWriter.h"
51
#include "ZXing/BitMatrix.h"
52
53
// Create QR Code
54
auto writer = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::QRCode);
55
auto matrix = writer.encode("Hello, World!", 300, 300);
56
57
// Check dimensions
58
std::cout << "Generated " << matrix.width() << "x" << matrix.height()
59
<< " barcode" << std::endl;
60
61
// Access individual pixels
62
for (int y = 0; y < matrix.height(); ++y) {
63
for (int x = 0; x < matrix.width(); ++x) {
64
bool isBlack = matrix.get(x, y);
65
// Convert to your image format...
66
}
67
}
68
```
69
70
### Configured Generation
71
72
```cpp
73
// Create Code 128 with custom settings
74
auto writer = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::Code128)
75
.setEncoding(ZXing::CharacterSet::UTF8)
76
.setMargin(20); // 20-pixel quiet zone
77
78
auto matrix = writer.encode("ABC123", 400, 100);
79
```
80
81
## Format-Specific Configuration
82
83
### QR Code Generation
84
85
```cpp
86
// QR Code with error correction and encoding
87
auto qrWriter = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::QRCode)
88
.setEncoding(ZXing::CharacterSet::UTF8)
89
.setEccLevel(2) // Error correction level (0-8)
90
.setMargin(10); // Quiet zone margin
91
92
// Generate QR code for URL
93
auto urlMatrix = qrWriter.encode("https://example.com", 200, 200);
94
95
// Generate QR code for text with special characters
96
auto textMatrix = qrWriter.encode("Hello, 世界! 🌍", 250, 250);
97
98
// Generate QR code for structured data
99
std::string vCard = "BEGIN:VCARD\n"
100
"VERSION:3.0\n"
101
"FN:John Doe\n"
102
"ORG:Example Corp\n"
103
"TEL:+1-555-123-4567\n"
104
"EMAIL:john@example.com\n"
105
"END:VCARD";
106
auto vcardMatrix = qrWriter.encode(vCard, 300, 300);
107
```
108
109
### Linear Barcode Generation
110
111
```cpp
112
// Code 128 for alphanumeric data
113
auto code128Writer = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::Code128)
114
.setMargin(15);
115
116
auto code128Matrix = code128Writer.encode("ABC123XYZ", 400, 80);
117
118
// EAN-13 for product codes
119
auto eanWriter = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::EAN13)
120
.setMargin(10);
121
122
// EAN-13 requires exactly 12 digits (13th is check digit)
123
auto eanMatrix = eanWriter.encode("123456789012", 300, 100);
124
125
// UPC-A for US retail
126
auto upcWriter = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::UPCA)
127
.setMargin(10);
128
129
// UPC-A requires exactly 11 digits (12th is check digit)
130
auto upcMatrix = upcWriter.encode("12345678901", 300, 100);
131
```
132
133
### DataMatrix Generation
134
135
```cpp
136
// DataMatrix for small data encoding
137
auto dmWriter = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::DataMatrix)
138
.setEncoding(ZXing::CharacterSet::UTF8)
139
.setMargin(5);
140
141
// Compact data encoding
142
auto dmMatrix = dmWriter.encode("ID:12345", 100, 100);
143
144
// Larger data with text
145
std::string productInfo = "Product: Widget\nSKU: W12345\nDate: 2024-01-15";
146
auto productMatrix = dmWriter.encode(productInfo, 150, 150);
147
```
148
149
### PDF417 Generation
150
151
```cpp
152
// PDF417 for high-capacity data
153
auto pdf417Writer = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::PDF417)
154
.setEncoding(ZXing::CharacterSet::UTF8)
155
.setEccLevel(4) // Error correction level
156
.setMargin(10);
157
158
// Large text document
159
std::string document = "This is a longer document that can contain "
160
"multiple lines of text with various special "
161
"characters and symbols: !@#$%^&*()";
162
auto docMatrix = pdf417Writer.encode(document, 400, 200);
163
```
164
165
## BitMatrix to Image Conversion
166
167
### Manual Conversion
168
169
```cpp
170
// Convert BitMatrix to raw image data
171
std::vector<uint8_t> convertToImage(const ZXing::BitMatrix& matrix,
172
bool addQuietZone = true) {
173
int width = matrix.width();
174
int height = matrix.height();
175
176
// Add quiet zone if requested
177
int quietZone = addQuietZone ? 20 : 0;
178
int imageWidth = width + 2 * quietZone;
179
int imageHeight = height + 2 * quietZone;
180
181
std::vector<uint8_t> image(imageWidth * imageHeight, 255); // White background
182
183
for (int y = 0; y < height; ++y) {
184
for (int x = 0; x < width; ++x) {
185
if (matrix.get(x, y)) {
186
int imageX = x + quietZone;
187
int imageY = y + quietZone;
188
image[imageY * imageWidth + imageX] = 0; // Black pixel
189
}
190
}
191
}
192
193
return image;
194
}
195
```
196
197
### Scaled Conversion
198
199
```cpp
200
// Convert with scaling for larger output
201
std::vector<uint8_t> convertToScaledImage(const ZXing::BitMatrix& matrix,
202
int scale = 4) {
203
int matrixWidth = matrix.width();
204
int matrixHeight = matrix.height();
205
int imageWidth = matrixWidth * scale;
206
int imageHeight = matrixHeight * scale;
207
208
std::vector<uint8_t> image(imageWidth * imageHeight, 255);
209
210
for (int matrixY = 0; matrixY < matrixHeight; ++matrixY) {
211
for (int matrixX = 0; matrixX < matrixWidth; ++matrixX) {
212
if (matrix.get(matrixX, matrixY)) {
213
// Fill scale x scale block
214
for (int dy = 0; dy < scale; ++dy) {
215
for (int dx = 0; dx < scale; ++dx) {
216
int imageX = matrixX * scale + dx;
217
int imageY = matrixY * scale + dy;
218
image[imageY * imageWidth + imageX] = 0;
219
}
220
}
221
}
222
}
223
}
224
225
return image;
226
}
227
```
228
229
### RGB Conversion
230
231
```cpp
232
// Convert to RGB format
233
std::vector<uint8_t> convertToRGB(const ZXing::BitMatrix& matrix,
234
uint8_t bgR = 255, uint8_t bgG = 255, uint8_t bgB = 255,
235
uint8_t fgR = 0, uint8_t fgG = 0, uint8_t fgB = 0) {
236
int width = matrix.width();
237
int height = matrix.height();
238
std::vector<uint8_t> rgb(width * height * 3);
239
240
for (int y = 0; y < height; ++y) {
241
for (int x = 0; x < width; ++x) {
242
int idx = (y * width + x) * 3;
243
if (matrix.get(x, y)) {
244
rgb[idx] = fgR; // Red
245
rgb[idx + 1] = fgG; // Green
246
rgb[idx + 2] = fgB; // Blue
247
} else {
248
rgb[idx] = bgR; // Red
249
rgb[idx + 1] = bgG; // Green
250
rgb[idx + 2] = bgB; // Blue
251
}
252
}
253
}
254
255
return rgb;
256
}
257
```
258
259
## Integration Examples
260
261
### Using with STB Image Write
262
263
```cpp
264
#define STB_IMAGE_WRITE_IMPLEMENTATION
265
#include <stb_image_write.h>
266
267
void saveBarcodeAsPNG(const ZXing::BitMatrix& matrix, const std::string& filename) {
268
auto imageData = convertToScaledImage(matrix, 4);
269
int width = matrix.width() * 4;
270
int height = matrix.height() * 4;
271
272
stbi_write_png(filename.c_str(), width, height, 1, imageData.data(), width);
273
}
274
275
// Usage
276
auto writer = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::QRCode);
277
auto matrix = writer.encode("Hello, World!", 200, 200);
278
saveBarcodeAsPNG(matrix, "qrcode.png");
279
```
280
281
### Using with OpenCV
282
283
```cpp
284
#include <opencv2/opencv.hpp>
285
286
cv::Mat convertToCvMat(const ZXing::BitMatrix& matrix) {
287
int width = matrix.width();
288
int height = matrix.height();
289
cv::Mat image(height, width, CV_8UC1, cv::Scalar(255));
290
291
for (int y = 0; y < height; ++y) {
292
for (int x = 0; x < width; ++x) {
293
if (matrix.get(x, y)) {
294
image.at<uint8_t>(y, x) = 0;
295
}
296
}
297
}
298
299
return image;
300
}
301
302
// Usage
303
auto writer = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::Code128);
304
auto matrix = writer.encode("CODE128", 400, 100);
305
cv::Mat image = convertToCvMat(matrix);
306
cv::imwrite("code128.png", image);
307
```
308
309
## Error Handling
310
311
### Invalid Parameters
312
313
```cpp
314
try {
315
auto writer = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::EAN13);
316
317
// This will fail - EAN13 requires exactly 12 digits
318
auto matrix = writer.encode("123", 300, 100);
319
320
} catch (const std::exception& e) {
321
std::cout << "Generation failed: " << e.what() << std::endl;
322
}
323
```
324
325
### Format Validation
326
327
```cpp
328
bool validateContentForFormat(const std::string& content, ZXing::BarcodeFormat format) {
329
switch (format) {
330
case ZXing::BarcodeFormat::EAN13:
331
return content.length() == 12 &&
332
std::all_of(content.begin(), content.end(), ::isdigit);
333
334
case ZXing::BarcodeFormat::UPCA:
335
return content.length() == 11 &&
336
std::all_of(content.begin(), content.end(), ::isdigit);
337
338
case ZXing::BarcodeFormat::Code39:
339
// Code39 supports A-Z, 0-9, and special characters
340
return std::all_of(content.begin(), content.end(), [](char c) {
341
return std::isalnum(c) ||
342
c == '-' || c == '.' || c == ' ' || c == '*' ||
343
c == '$' || c == '/' || c == '+' || c == '%';
344
});
345
346
default:
347
return true; // Most formats accept arbitrary strings
348
}
349
}
350
351
// Usage
352
std::string content = "123456789012";
353
if (validateContentForFormat(content, ZXing::BarcodeFormat::EAN13)) {
354
auto writer = ZXing::MultiFormatWriter(ZXing::BarcodeFormat::EAN13);
355
auto matrix = writer.encode(content, 300, 100);
356
}
357
```
358
359
## Advanced Usage
360
361
### Batch Generation
362
363
```cpp
364
class BarcodeGenerator {
365
private:
366
std::map<ZXing::BarcodeFormat, ZXing::MultiFormatWriter> writers_;
367
368
public:
369
BarcodeGenerator() {
370
// Pre-configure writers for different formats
371
writers_.emplace(ZXing::BarcodeFormat::QRCode,
372
ZXing::MultiFormatWriter(ZXing::BarcodeFormat::QRCode)
373
.setEncoding(ZXing::CharacterSet::UTF8)
374
.setEccLevel(2)
375
.setMargin(10));
376
377
writers_.emplace(ZXing::BarcodeFormat::Code128,
378
ZXing::MultiFormatWriter(ZXing::BarcodeFormat::Code128)
379
.setMargin(15));
380
}
381
382
ZXing::BitMatrix generate(const std::string& content,
383
ZXing::BarcodeFormat format,
384
int width, int height) {
385
auto it = writers_.find(format);
386
if (it != writers_.end()) {
387
return it->second.encode(content, width, height);
388
}
389
390
// Fallback to default configuration
391
auto writer = ZXing::MultiFormatWriter(format);
392
return writer.encode(content, width, height);
393
}
394
};
395
396
// Usage for batch processing
397
BarcodeGenerator generator;
398
std::vector<std::string> products = {"12345", "67890", "ABCDE"};
399
400
for (const auto& product : products) {
401
auto matrix = generator.generate(product, ZXing::BarcodeFormat::Code128, 400, 80);
402
// Save or process matrix...
403
}
404
```
405
406
### Size Optimization
407
408
```cpp
409
// Find optimal size for content
410
std::pair<int, int> findOptimalSize(const std::string& content,
411
ZXing::BarcodeFormat format) {
412
auto writer = ZXing::MultiFormatWriter(format);
413
414
// Try different sizes to find minimum
415
std::vector<std::pair<int, int>> sizes = {
416
{100, 100}, {150, 150}, {200, 200}, {250, 250}, {300, 300}
417
};
418
419
for (const auto& size : sizes) {
420
try {
421
auto matrix = writer.encode(content, size.first, size.second);
422
return {matrix.width(), matrix.height()};
423
} catch (...) {
424
continue;
425
}
426
}
427
428
return {300, 300}; // Default fallback
429
}
430
```