0
# QR Code Support
1
2
Complete QR Code implementation with encoding, decoding, error correction levels, and advanced configuration options for the most widely used 2D barcode format.
3
4
## Capabilities
5
6
### QR Code Reader
7
8
Specialized reader implementation for QR Code decoding with optimized detection algorithms.
9
10
```java { .api }
11
/**
12
* QR Code specific decoder implementation
13
* Optimized for QR Code detection and decoding
14
*/
15
public final class QRCodeReader implements Reader {
16
/**
17
* Standard constructor
18
*/
19
public QRCodeReader();
20
21
/**
22
* Decode QR code from binary bitmap
23
* @param image Binary bitmap containing QR code
24
* @return Decoded result
25
* @throws NotFoundException if no QR code found
26
* @throws ChecksumException if QR code checksum fails
27
* @throws FormatException if QR code format is invalid
28
*/
29
@Override
30
public Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException;
31
32
/**
33
* Decode QR code with hints
34
* @param image Binary bitmap containing QR code
35
* @param hints Decoding hints for configuration
36
* @return Decoded result
37
* @throws NotFoundException if no QR code found
38
* @throws ChecksumException if QR code checksum fails
39
* @throws FormatException if QR code format is invalid
40
*/
41
@Override
42
public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints) throws NotFoundException, ChecksumException, FormatException;
43
44
/**
45
* Reset internal state
46
*/
47
@Override
48
public void reset();
49
}
50
```
51
52
### QR Code Writer
53
54
Specialized writer implementation for QR Code encoding with comprehensive configuration options.
55
56
```java { .api }
57
/**
58
* QR Code specific encoder implementation
59
* Supports all QR code versions, error correction levels, and encoding modes
60
*/
61
public final class QRCodeWriter implements Writer {
62
/**
63
* Standard constructor
64
*/
65
public QRCodeWriter();
66
67
/**
68
* Encode content as QR code
69
* @param contents Text content to encode
70
* @param format Must be BarcodeFormat.QR_CODE
71
* @param width Preferred width in pixels
72
* @param height Preferred height in pixels
73
* @return BitMatrix representing QR code
74
* @throws WriterException if encoding fails
75
*/
76
@Override
77
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) throws WriterException;
78
79
/**
80
* Encode content as QR code with hints
81
* @param contents Text content to encode
82
* @param format Must be BarcodeFormat.QR_CODE
83
* @param width Preferred width in pixels
84
* @param height Preferred height in pixels
85
* @param hints Encoding configuration hints
86
* @return BitMatrix representing QR code
87
* @throws WriterException if encoding fails
88
*/
89
@Override
90
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map<EncodeHintType,?> hints) throws WriterException;
91
}
92
```
93
94
**Usage Examples:**
95
96
```java
97
import com.google.zxing.qrcode.*;
98
import com.google.zxing.*;
99
import com.google.zxing.common.BitMatrix;
100
import java.util.Map;
101
import java.util.HashMap;
102
103
// Basic QR code encoding
104
QRCodeWriter writer = new QRCodeWriter();
105
BitMatrix qrMatrix = writer.encode("Hello World", BarcodeFormat.QR_CODE, 300, 300);
106
107
// QR code encoding with error correction
108
Map<EncodeHintType, Object> hints = new HashMap<>();
109
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
110
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
111
hints.put(EncodeHintType.MARGIN, 4);
112
113
BitMatrix qrCode = writer.encode("https://example.com", BarcodeFormat.QR_CODE, 400, 400, hints);
114
115
// QR code decoding
116
QRCodeReader reader = new QRCodeReader();
117
Result result = reader.decode(binaryBitmap);
118
String decodedText = result.getText();
119
```
120
121
### Error Correction Levels
122
123
QR codes support four levels of Reed-Solomon error correction for different reliability requirements.
124
125
```java { .api }
126
/**
127
* QR Code error correction levels
128
* Higher levels provide more error recovery at cost of data capacity
129
*/
130
public enum ErrorCorrectionLevel {
131
/**
132
* Level L - Low (recovers ~7% of data)
133
* Best for clean environments, maximum data capacity
134
*/
135
L,
136
137
/**
138
* Level M - Medium (recovers ~15% of data)
139
* Balanced error correction, recommended for most uses
140
*/
141
M,
142
143
/**
144
* Level Q - Quartile (recovers ~25% of data)
145
* Good for potentially damaged environments
146
*/
147
Q,
148
149
/**
150
* Level H - High (recovers ~30% of data)
151
* Maximum error recovery, reduced data capacity
152
*/
153
H;
154
155
/**
156
* Get bits value for this error correction level
157
* @return Two-bit representation (0-3)
158
*/
159
public int getBits();
160
161
/**
162
* Create from bits value
163
* @param bits Two-bit value (0-3)
164
* @return Corresponding ErrorCorrectionLevel
165
*/
166
public static ErrorCorrectionLevel forBits(int bits);
167
}
168
```
169
170
**Error Correction Usage:**
171
172
```java
173
// Configure different error correction levels
174
Map<EncodeHintType, Object> hints = new HashMap<>();
175
176
// Maximum data capacity (for clean environments)
177
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
178
179
// Balanced (recommended for most uses)
180
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
181
182
// High reliability (for damaged/dirty environments)
183
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
184
185
BitMatrix qr = writer.encode("Data", BarcodeFormat.QR_CODE, 300, 300, hints);
186
```
187
188
### QR Code Versions and Capacity
189
190
QR codes come in 40 different versions (sizes) with varying data capacities.
191
192
```java { .api }
193
/**
194
* QR Code version information
195
* Defines size, capacity, and error correction codewords
196
*/
197
public final class Version {
198
/**
199
* Get version for specified version number
200
* @param versionNumber Version number (1-40)
201
* @return Version instance
202
* @throws IllegalArgumentException if version number invalid
203
*/
204
public static Version getVersionForNumber(int versionNumber);
205
206
/**
207
* Get version number
208
* @return Version number (1-40)
209
*/
210
public int getVersionNumber();
211
212
/**
213
* Get dimension in modules
214
* @return Dimension (21x21 for version 1, up to 177x177 for version 40)
215
*/
216
public int getDimensionForVersion();
217
218
/**
219
* Get total number of codewords
220
* @return Total codewords for this version
221
*/
222
public int getTotalCodewords();
223
224
/**
225
* Get data capacity for error correction level and mode
226
* @param ecLevel Error correction level
227
* @param mode Encoding mode
228
* @return Maximum characters that can be encoded
229
*/
230
public int getCharacterCountBits(Mode mode);
231
}
232
```
233
234
### Encoding Modes
235
236
QR codes support multiple encoding modes optimized for different content types.
237
238
```java { .api }
239
/**
240
* QR Code encoding modes
241
* Different modes optimize encoding for specific character sets
242
*/
243
public enum Mode {
244
/**
245
* Numeric mode: digits 0-9
246
* Most efficient for numeric-only content
247
* 3.33 bits per digit
248
*/
249
NUMERIC,
250
251
/**
252
* Alphanumeric mode: 0-9, A-Z, space, $, %, *, +, -, ., /, :
253
* Efficient for uppercase alphanumeric content
254
* 5.5 bits per character
255
*/
256
ALPHANUMERIC,
257
258
/**
259
* Byte mode: any 8-bit data
260
* Default mode for arbitrary content
261
* 8 bits per byte
262
*/
263
BYTE,
264
265
/**
266
* Kanji mode: Shift_JIS Kanji characters
267
* Optimized for Japanese Kanji
268
* 13 bits per character
269
*/
270
KANJI,
271
272
/**
273
* ECI mode: Extended Channel Interpretation
274
* Specifies character set for following data
275
*/
276
ECI,
277
278
/**
279
* Structured Append mode
280
* Links multiple QR codes into sequence
281
*/
282
STRUCTURED_APPEND,
283
284
/**
285
* FNC1 mode variants
286
* GS1 and AIM application indicators
287
*/
288
FNC1_FIRST_POSITION,
289
FNC1_SECOND_POSITION,
290
291
/**
292
* Terminator (internal use)
293
*/
294
TERMINATOR;
295
296
/**
297
* Get mode bits value
298
* @return Bit representation of mode
299
*/
300
public int getBits();
301
302
/**
303
* Get character count bits for version
304
* @param version QR code version
305
* @return Number of bits used for character count
306
*/
307
public int getCharacterCountBits(Version version);
308
}
309
```
310
311
### QR Code Specific Hints
312
313
Additional encoding options specific to QR codes.
314
315
```java
316
// QR-specific encoding hints
317
Map<EncodeHintType, Object> qrHints = new HashMap<>();
318
319
// Force specific version (size)
320
qrHints.put(EncodeHintType.QR_VERSION, 10); // Force version 10 (57x57 modules)
321
322
// Specify mask pattern (0-7, or let encoder choose)
323
qrHints.put(EncodeHintType.QR_MASK_PATTERN, 3);
324
325
// Enable compact mode (implementation-specific)
326
qrHints.put(EncodeHintType.QR_COMPACT, Boolean.TRUE);
327
328
// Character encoding
329
qrHints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
330
331
// Margin size (quiet zone)
332
qrHints.put(EncodeHintType.MARGIN, 4); // 4-module margin
333
334
BitMatrix qr = writer.encode("Content", BarcodeFormat.QR_CODE, 300, 300, qrHints);
335
```
336
337
### Data Capacity by Version and Error Correction
338
339
QR code capacity varies significantly by version and error correction level:
340
341
| Version | Size | Numeric (L/M/Q/H) | Alphanumeric (L/M/Q/H) | Byte (L/M/Q/H) |
342
|---------|---------|-------------------|------------------------|----------------|
343
| 1 | 21×21 | 41/34/27/17 | 25/20/16/10 | 17/14/11/7 |
344
| 10 | 57×57 | 652/513/364/288 | 395/311/221/174 | 271/213/151/119|
345
| 20 | 97×97 | 1,473/1,135/815/596 | 892/687/493/362 | 613/472/339/248|
346
| 40 | 177×177 | 7,089/5,596/3,993/2,953 | 4,296/3,391/2,420/1,785 | 2,953/2,331/1,663/1,271|
347
348
### Advanced QR Code Features
349
350
#### Structured Append
351
352
Link multiple QR codes to encode larger amounts of data:
353
354
```java
355
// Create sequence of linked QR codes (implementation would require custom encoding)
356
// QR code 1 of 3: contains structured append header + partial data
357
// QR code 2 of 3: contains structured append header + partial data
358
// QR code 3 of 3: contains structured append header + remaining data
359
```
360
361
#### ECI (Extended Channel Interpretation)
362
363
Specify character encodings for international text:
364
365
```java
366
// ECI support for different character sets
367
Map<EncodeHintType, Object> hints = new HashMap<>();
368
hints.put(EncodeHintType.CHARACTER_SET, "Shift_JIS"); // Japanese
369
// or "ISO-8859-1", "UTF-8", etc.
370
371
BitMatrix qr = writer.encode("国際化テキスト", BarcodeFormat.QR_CODE, 300, 300, hints);
372
```
373
374
### QR Code Detection Process
375
376
The QR code reader uses a sophisticated detection process:
377
378
1. **Finder Pattern Detection**: Locate the three corner squares
379
2. **Alignment Pattern Detection**: Find internal alignment patterns
380
3. **Timing Pattern Analysis**: Extract timing patterns for grid alignment
381
4. **Format Information Reading**: Read error correction level and mask pattern
382
5. **Version Information Reading**: Determine QR code version/size
383
6. **Data Extraction**: Sample data modules using detected grid
384
7. **Error Correction**: Apply Reed-Solomon error correction
385
8. **Mode Detection**: Determine encoding mode(s) used
386
9. **Data Decoding**: Decode based on detected modes
387
388
### Performance Optimization
389
390
```java
391
// For continuous QR code scanning, reuse reader instance
392
QRCodeReader reader = new QRCodeReader();
393
394
// Configure hints once for better performance
395
Map<DecodeHintType, Object> hints = new HashMap<>();
396
hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.of(BarcodeFormat.QR_CODE));
397
hints.put(DecodeHintType.TRY_HARDER, Boolean.FALSE); // Faster scanning
398
399
// Process multiple images
400
for (BinaryBitmap bitmap : images) {
401
try {
402
Result result = reader.decode(bitmap, hints);
403
processResult(result);
404
} catch (NotFoundException e) {
405
// No QR code in this image
406
}
407
}
408
```
409
410
### Error Handling
411
412
```java
413
try {
414
Result result = qrReader.decode(bitmap);
415
416
// Check if it's actually a QR code
417
if (result.getBarcodeFormat() == BarcodeFormat.QR_CODE) {
418
String content = result.getText();
419
420
// Check for structured append
421
Map<ResultMetadataType, Object> metadata = result.getResultMetadata();
422
if (metadata != null && metadata.containsKey(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) {
423
// Handle multi-part QR code sequence
424
handleStructuredAppend(result);
425
}
426
}
427
428
} catch (ChecksumException e) {
429
// QR code found but data is corrupted beyond repair
430
System.err.println("QR code data corrupted");
431
} catch (FormatException e) {
432
// Invalid QR code format
433
System.err.println("Invalid QR code format");
434
} catch (NotFoundException e) {
435
// No QR code found in image
436
System.err.println("No QR code detected");
437
}
438
```
439
440
## QR Code Best Practices
441
442
### Content Optimization
443
- Use numeric mode for digits-only content
444
- Use alphanumeric mode for uppercase letters and limited symbols
445
- Consider content length vs. error correction level trade-offs
446
- Test readability at target physical sizes
447
448
### Error Correction Selection
449
- **Level L**: Clean printing, controlled environments, maximum data
450
- **Level M**: General purpose, balanced capacity/reliability
451
- **Level Q**: Potentially damaged environments, outdoor use
452
- **Level H**: Maximum error recovery, harsh conditions
453
454
### Physical Considerations
455
- Maintain adequate quiet zone (4+ modules margin)
456
- Ensure sufficient contrast between modules and background
457
- Consider minimum module size for intended scanning distance
458
- Test with target scanning devices and applications