QR Decoder Compatibility Reference
This document provides comprehensive information about QR code decoder compatibility with SegnoMMS stylized QR codes, including known limitations and recommendations for different use cases.
Overview
SegnoMMS generates visually stylized QR codes that prioritize aesthetic appeal while maintaining functional scanability. However, some combinations of visual styling and decoder implementations may result in reduced compatibility compared to standard square-module QR codes.
This reference documents tested decoder compatibility across different configurations to help developers make informed decisions about styling choices for their specific use cases.
Error Correction Level Reference
QR codes use Reed-Solomon error correction to recover from damage or scanning issues. Higher error correction levels allow more data recovery but reduce available data capacity:
Level |
Recovery Capacity |
Recommended Use |
|---|---|---|
L (Low) |
~7% damage recovery |
Clean environments, maximum data capacity needed |
M (Medium) |
~15% damage recovery |
Standard usage, good balance (default) |
Q (Quartile) |
~25% damage recovery |
Stylized QR codes, moderate visual effects |
H (High) |
~30% damage recovery |
Heavy styling, logos, outdoor use, critical applications |
For stylized QR codes, use at least Level M. For connected shapes, merged modules, or centerpiece overlays, Level Q or H is strongly recommended to compensate for the visual modifications that may affect scanning.
Decoder Library Compatibility Matrix
The following decoders have been tested with SegnoMMS output:
Recommended Decoders (High Compatibility): - zxingcpp - ZXing C++ implementation with Python bindings - OpenCV QRCodeDetector - Part of opencv-python package - pyzbar - Python wrapper for ZBar library (requires system dependencies)
Mobile and Web Decoders: - Most smartphone camera apps use ZXing or similar algorithms - Web-based QR scanners vary widely in capability
Installation
# Recommended: ZXing C++ (no system dependencies)
pip install zxingcpp
# Alternative: OpenCV
pip install opencv-python
# Alternative: PyZBar (requires libzbar)
# On macOS: brew install zbar
# On Ubuntu: sudo apt-get install libzbar0
pip install pyzbar
Known Compatibility Issues
Based on systematic testing, the following configurations have known decoder compatibility limitations:
Error Correction Level Issues
Low Error Correction (Level L)
- Issue: Connected shapes with ECC Level L may have insufficient error correction
- Affected Configuration: error="L" with shape="connected"
- Affected Decoders: zxingcpp, opencv
- Recommendation: Use ECC Level M or higher for connected/merged shapes
- Explanation: Visual styling reduces available error correction capacity
Compatibility Recommendations
High Compatibility Configurations
For maximum decoder compatibility, use these “safe” configurations:
# Safest configuration - works with all tested decoders
safe_config = {
'shape': 'square',
'scale': 10,
'dark': '#000000',
'light': '#FFFFFF',
'error': 'M' # Medium error correction
}
# Safe rounded appearance
safe_rounded = {
'shape': 'squircle',
'safe_mode': True,
'scale': 10,
'error': 'M'
}
# Safe connected modules
safe_connected = {
'shape': 'connected',
'safe_mode': True,
'error': 'Q', # Higher ECC for merging
'scale': 12
}
Balanced Styling Configurations
These configurations provide good visual appeal with reasonable compatibility:
# Stylized but compatible
balanced_config = {
'shape': 'rounded',
'safe_mode': True,
'scale': 15, # Larger scale for better definition
'error': 'M',
'dark': '#1a1a2e',
'light': '#f5f5f5'
}
# Connected modules with safety
balanced_connected = {
'shape': 'connected',
'connectivity': '8-way',
'merge': 'soft',
'safe_mode': True,
'error': 'H', # Highest ECC for complex styling
'scale': 12
}
Testing and Validation
Decoder Testing Methodology
When deploying SegnoMMS QR codes, follow this testing approach:
Generate test codes with your exact configuration
Convert to PNG using the same process as production
Test with multiple decoders (zxingcpp, opencv, mobile apps)
Verify across different scales and viewing conditions
Document compatibility for your specific use case
Example Testing Code
import segno
from segnomms import write
import io
from pathlib import Path
from typing import Any, Dict, List, Optional
def test_decoder_compatibility(
config: Dict,
test_data: str = "Test Message",
output_dir: Optional[Path] = None
) -> Dict[str, Any]:
"""
Test decoder compatibility for a configuration.
Args:
config: Dictionary of configuration options for write()
test_data: Data to encode in the QR code
output_dir: Optional directory for saving test files
Returns:
Dictionary with test results from all available decoders
"""
import tempfile
import shutil
# Create QR code with specified error level
qr = segno.make(test_data, error=config.get('error', 'M'))
# Generate SVG
output = io.StringIO()
write(qr, output, **config)
svg_content = output.getvalue()
# Prepare output directory
if output_dir is None:
output_dir = Path(tempfile.mkdtemp(prefix='qr_test_'))
else:
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
# Save SVG
svg_path = output_dir / "test.svg"
with open(svg_path, 'w') as f:
f.write(svg_content)
# Convert SVG to PNG for testing
# Using cairosvg for reliable conversion
try:
import cairosvg
png_path = output_dir / "test.png"
cairosvg.svg2png(
bytestring=svg_content.encode('utf-8'),
write_to=str(png_path),
dpi=200,
output_width=400,
output_height=400
)
except ImportError:
return {
'error': 'cairosvg not installed',
'suggestion': 'pip install cairosvg',
'config': config
}
# Test with available decoders
test_results = {
'config': config,
'test_data': test_data,
'svg_path': str(svg_path),
'png_path': str(png_path),
'decoders': {}
}
# Test with zxingcpp
try:
import zxingcpp
from PIL import Image
img = Image.open(png_path)
result = zxingcpp.read_barcode(img)
test_results['decoders']['zxingcpp'] = {
'available': True,
'detected': result is not None,
'decoded': result.text if result else None,
'matches': result.text == test_data if result else False,
'error': None
}
except ImportError:
test_results['decoders']['zxingcpp'] = {
'available': False,
'error': 'zxingcpp not installed'
}
except Exception as e:
test_results['decoders']['zxingcpp'] = {
'available': True,
'detected': False,
'error': str(e)
}
# Test with OpenCV
try:
import cv2
img = cv2.imread(str(png_path))
detector = cv2.QRCodeDetector()
data, bbox, _ = detector.detectAndDecode(img)
test_results['decoders']['opencv'] = {
'available': True,
'detected': bbox is not None,
'decoded': data if data else None,
'matches': data == test_data if data else False,
'error': None
}
except ImportError:
test_results['decoders']['opencv'] = {
'available': False,
'error': 'opencv-python not installed'
}
except Exception as e:
test_results['decoders']['opencv'] = {
'available': True,
'detected': False,
'error': str(e)
}
# Test with pyzbar
try:
from pyzbar import pyzbar
from PIL import Image
img = Image.open(png_path)
results = pyzbar.decode(img)
if results:
decoded_data = results[0].data.decode('utf-8')
test_results['decoders']['pyzbar'] = {
'available': True,
'detected': True,
'decoded': decoded_data,
'matches': decoded_data == test_data,
'error': None
}
else:
test_results['decoders']['pyzbar'] = {
'available': True,
'detected': False,
'decoded': None,
'matches': False,
'error': 'No QR code detected'
}
except ImportError:
test_results['decoders']['pyzbar'] = {
'available': False,
'error': 'pyzbar not installed (requires system libzbar)'
}
except Exception as e:
test_results['decoders']['pyzbar'] = {
'available': True,
'detected': False,
'error': str(e)
}
# Calculate summary
available_decoders = [name for name, result in test_results['decoders'].items()
if result.get('available', False)]
successful_decoders = [name for name, result in test_results['decoders'].items()
if result.get('matches', False)]
test_results['summary'] = {
'total_decoders': len(available_decoders),
'successful_decoders': len(successful_decoders),
'success_rate': len(successful_decoders) / len(available_decoders)
if available_decoders else 0.0,
'all_passed': len(successful_decoders) == len(available_decoders)
and len(available_decoders) > 0
}
return test_results
def print_test_results(results: Dict) -> None:
"""Pretty print decoder test results."""
print(f"\n{'='*60}")
print("QR Decoder Compatibility Test Results")
print(f"{'='*60}")
print(f"Configuration: {results['config']}")
print(f"Test Data: {results['test_data']}")
print(f"\nDecoder Results:")
print(f"{'-'*60}")
for decoder_name, decoder_result in results['decoders'].items():
if not decoder_result.get('available', False):
print(f" {decoder_name}: ❌ Not available - {decoder_result.get('error', 'Unknown')}")
elif decoder_result.get('matches', False):
print(f" {decoder_name}: ✅ SUCCESS - Decoded correctly")
elif decoder_result.get('detected', False):
print(f" {decoder_name}: ⚠️ MISMATCH - Decoded as '{decoder_result.get('decoded')}'")
else:
error = decoder_result.get('error', 'Detection failed')
print(f" {decoder_name}: ❌ FAILED - {error}")
print(f"\n{'-'*60}")
summary = results['summary']
print(f"Summary: {summary['successful_decoders']}/{summary['total_decoders']} decoders succeeded")
print(f"Success Rate: {summary['success_rate']*100:.1f}%")
print(f"Overall: {'✅ PASS' if summary['all_passed'] else '❌ FAIL'}")
print(f"{'='*60}\n")
def batch_test_configurations(configs: List[Dict], test_data: str = "https://example.com") -> None:
"""Test multiple configurations and report results."""
all_results = []
for i, config in enumerate(configs, 1):
print(f"\n[{i}/{len(configs)}] Testing configuration...")
results = test_decoder_compatibility(config, test_data)
print_test_results(results)
all_results.append(results)
# Print aggregate summary
print(f"\n{'='*60}")
print("AGGREGATE TEST RESULTS")
print(f"{'='*60}")
total_configs = len(all_results)
passed_configs = sum(1 for r in all_results if r['summary']['all_passed'])
print(f"Total Configurations Tested: {total_configs}")
print(f"Fully Compatible: {passed_configs}")
print(f"Partial Compatibility: {total_configs - passed_configs}")
print(f"Overall Compatibility Rate: {passed_configs/total_configs*100:.1f}%")
print(f"{'='*60}\n")
# Example Usage
if __name__ == "__main__":
# Test individual configuration
config = {
'shape': 'circle',
'safe_mode': True,
'scale': 10,
'error': 'M'
}
results = test_decoder_compatibility(config, "https://example.com")
print_test_results(results)
# Test multiple configurations
test_configs = [
{'shape': 'square', 'scale': 10, 'error': 'M'},
{'shape': 'circle', 'safe_mode': True, 'scale': 10, 'error': 'M'},
{'shape': 'rounded', 'safe_mode': True, 'scale': 15, 'error': 'M'},
{'shape': 'connected', 'safe_mode': True, 'scale': 12, 'error': 'H'},
]
batch_test_configurations(test_configs)
Performance Considerations
SVG to Bitmap Conversion
The quality of SVG→PNG/JPEG conversion significantly affects decoder compatibility:
Rendering Settings Impact: - DPI: Higher DPI (≥150) improves fine detail preservation - Antialiasing: May blur edges; consider disabling for small QR codes - Scale: Larger output dimensions generally improve compatibility - Format: PNG preserves sharp edges better than JPEG
Recommended Conversion Settings:
conversion_settings = {
'dpi': 200,
'width': 400, # Minimum 400px for reliable decoding
'height': 400,
'background': 'white',
'format': 'PNG'
}
Mobile Camera Considerations
Mobile QR code scanning has additional constraints:
Minimum size: QR codes should be at least 2cm (0.8”) for reliable mobile scanning
Contrast: Maintain high contrast ratios (≥7:1) for accessibility
Lighting: Test under various lighting conditions
Distance: QR codes are typically scanned from 10-50cm distance
Troubleshooting Decoder Issues
Common Problems and Solutions
“QR code not detected” - Increase scale parameter (try 12-20) - Enable safe_mode if using non-square shapes - Increase error correction level - Check contrast ratio between dark/light colors
“Detected but can’t decode content” - Increase error correction level (try ‘H’) - Reduce visual complexity (disable merging, use simpler shapes) - Test with different decoders
“Works on some devices but not others” - Test with multiple decoder implementations - Consider using “high compatibility” configuration - Document known limitations for users
“Intermittent scanning failures” - Increase quiet zone (border parameter) - Use larger scale for small QR codes - Test SVG→bitmap conversion quality
Decoder-Specific Notes
ZXing C++ - Generally most permissive with styling - Good performance with connected modules - May struggle with very small scales
OpenCV QRCodeDetector - Sensitive to edge definition - Works well with high-contrast configurations - May have issues with complex merged shapes
PyZBar - Requires system library installation - Good compatibility with standard configurations - May be sensitive to image preprocessing
Future Compatibility
Decoder Algorithm Evolution
QR decoder algorithms continue to evolve, potentially improving compatibility with stylized codes:
Machine learning approaches may better handle non-standard shapes
Improved edge detection could handle merged modules more reliably
Multi-scale analysis might improve small QR code recognition
However, compatibility with older devices and legacy decoders remains important for broad accessibility.
SegnoMMS Development
Future SegnoMMS versions may include:
Compatibility scoring during configuration validation
Decoder-specific optimization modes
Automatic safe mode recommendations
Enhanced SVG rendering for better bitmap conversion
Recommendations for Library Users
Production Deployment Checklist
Before deploying stylized QR codes in production:
Test with target decoders (mobile apps, web scanners, etc.)
Validate across different devices and operating systems
Document known limitations for end users
Provide fallback options (URL shorteners, manual entry)
Monitor scanning success rates if possible
Configuration Selection Guidelines
Critical Applications (payment, authentication) - Use high compatibility configurations - Test extensively with target decoders - Consider multiple QR code sizes/formats
Marketing Materials (posters, business cards) - Balanced styling acceptable - Include fallback information - Test under expected viewing conditions
Decorative Applications (art, design elements) - Full styling freedom - Clearly communicate any scanning limitations - Consider QR codes as supplementary, not primary interface
Documentation and Support
When documenting QR codes for end users:
Include Scanning Instructions: - Recommended scanning apps if compatibility is limited - Optimal scanning distance and lighting - Alternative access methods (typed URLs, etc.)
Set Appropriate Expectations: - Acknowledge that stylized QR codes may require specific scanners - Provide clear fallback options - Consider user accessibility needs
Conclusion
SegnoMMS enables creation of visually appealing QR codes while maintaining good decoder compatibility for most configurations. Understanding the documented limitations allows developers to make informed decisions about styling trade-offs.
For maximum compatibility, use the recommended “safe” configurations. For applications requiring specific styling, thorough testing with target decoders is essential.
The QR code ecosystem continues to evolve, and future decoder improvements may resolve some current limitations. Until then, this compatibility reference provides guidance for reliable deployment of stylized QR codes.
Phase 4 Advanced Features Compatibility
Phase 4 features (frames, centerpieces, gradients) introduce additional compatibility considerations beyond basic shape styling. These features can significantly impact scannability and require careful testing.
Frame Shape Compatibility
Frame shapes affect decoder recognition by altering the QR code’s boundary detection:
Frame Shape |
ZXing C++ |
OpenCV |
PyZBar |
Mobile Apps |
Recommended Settings |
|---|---|---|---|---|---|
square (none) |
✅ Excellent |
✅ Excellent |
✅ Excellent |
✅ Excellent |
Standard settings |
rounded-rect |
✅ Very Good |
✅ Very Good |
✅ Good |
⚠️ Variable |
corner_radius ≤ 0.2, border ≥ 4 |
circle |
⚠️ Good |
⚠️ Good |
⚠️ Fair |
❌ Poor |
border ≥ 5, clip_mode=’clip’ |
squircle |
⚠️ Good |
⚠️ Fair |
❌ Poor |
❌ Poor |
border ≥ 5, simple shapes only |
custom |
❌ Variable |
❌ Variable |
❌ Poor |
❌ Poor |
Extensive testing required |
Production Recommendations:
High Compatibility: Use no frame or
rounded-rectwith small corner radiusTesting Required: Circle and squircle frames need thorough validation
Avoid in Production: Custom frames without comprehensive decoder testing
Centerpiece (Logo Area) Compatibility
Centerpiece areas impact error correction capability and pattern recognition:
Error Level |
Max Safe Size |
Recommended Size |
Notes |
|---|---|---|---|
L (7%) |
0.05 |
0.03 |
Very limited logo space |
M (15%) |
0.12 |
0.08 |
Suitable for small logos |
Q (25%) |
0.18 |
0.12 |
Good logo visibility |
H (30%) |
0.25 |
0.15 |
Maximum logo area |
Centerpiece Shape Compatibility:
Rectangle: Best compatibility, most predictable
Circle: Good with most decoders, test mobile apps
Squircle: Variable compatibility, requires testing
Critical Guidelines:
Always use
centerpiece_margin ≥ 2for safety bufferTest centerpiece + frame combinations thoroughly
Consider fallback QR codes for critical applications
Use highest error correction level (H) for large centerpieces
Combined Features Compatibility Risk
When combining multiple Phase 4 features, compatibility risks multiply:
Warning
High Risk Combinations (Extensive Testing Required):
Circle frame + large centerpiece + gradient background
Custom frame + squircle centerpiece
Fade clip mode + connected shapes + centerpiece
Lower Risk Combinations:
Rounded-rect frame + small rect centerpiece + solid background
No frame + small circle centerpiece + simple shapes
PNG Conversion for Phase 4 Features
Phase 4 features require special attention during PNG conversion:
# Recommended settings for Phase 4 features
conversion_settings = {
'dpi': 300, # Higher DPI for frame clarity
'width': 600, # Larger size for centerpiece detail
'height': 600,
'background': 'white',
'antialias': False, # Sharp edges for frame detection
'format': 'PNG'
}
Testing Protocol for Phase 4:
Generate test QR codes with your exact Phase 4 configuration
Convert to PNG using recommended settings
Test with multiple libraries (zxingcpp, OpenCV, pyzbar)
Validate on mobile devices your users will actually use
Test edge cases (low light, angled scanning, small sizes)
Implement fallbacks if any decoder fails