Technology & Tools

QR Code Technology: Complete Guide to Generation and Implementation

β€’18 min read min readβ€’By KBC Grandcentral Team
PositionPositionPositionTimingAlignFormat InfoVersionError CorrectionL: 7% recoveryM: 15% recoveryQ: 25% recoveryH: 30% recoveryEncoding ModesπŸ“ Numeric: 0-9πŸ”€ Alphanumeric: A-Z, 0-9, specialπŸ’Ύ Byte: Any 8-bit data🈷️ Kanji: Japanese charactersGeneration Process β†’1. Data AnalysisChoose modeβ†’2. EncodingConvert to binaryβ†’3. Error CorrectionAdd Reed-Solomonβ†’4. Module PlacementCreate matrixβ†’5. MaskingApply pattern QR Code Technology Architecture

QR (Quick Response) codes have revolutionized how we share and access information in the digital age. From contactless payments to marketing campaigns, these two-dimensional barcodes encode data in a matrix of black and white squares that can be scanned by smartphones and dedicated readers. This comprehensive guide explores the technology, algorithms, and best practices for implementing QR codes in modern applications.

Understanding QR Code Structure

A QR code consists of several functional patterns that enable reliable scanning and data recovery:

Core Components

  • Position Detection Patterns: Three large squares in corners that help scanners identify QR code orientation and boundaries
  • Alignment Patterns: Smaller squares that correct for image distortion in larger QR codes
  • Timing Patterns: Alternating black and white modules that help determine the coordinate system
  • Format Information: Data about error correction level and mask pattern used
  • Version Information: Indicates QR code version (size), present in version 7 and higher
  • Data and Error Correction Modules: The actual encoded information with redundancy for error recovery

QR Code Versions and Capacities

VersionModulesNumericAlphanumericByte
121Γ—2141 chars25 chars17 bytes
1057Γ—57331 chars202 chars139 bytes
2097Γ—971,056 chars644 chars442 bytes
40177Γ—1777,089 chars4,296 chars2,953 bytes

Capacities shown are for error correction level L (Low - 7% recovery)

Error Correction with Reed-Solomon

QR codes use Reed-Solomon error correction codes, enabling them to be read even when partially damaged or obscured. Four error correction levels are available:

Level L (Low)

7% of data can be restored

Best for: Clean environments, maximum data capacity

Level M (Medium)

15% of data can be restored

Best for: General use, balanced capacity/reliability

Level Q (Quartile)

25% of data can be restored

Best for: Outdoor use, potential damage expected

Level H (High)

30% of data can be restored

Best for: Harsh conditions, logo embedding

πŸ’‘ Reed-Solomon Algorithm Basics

The algorithm works by treating data as polynomials and adding redundant "check symbols" that allow reconstruction of damaged data. The process involves:

  1. Divide message into blocks
  2. Treat each block as polynomial coefficients
  3. Generate error correction codewords using polynomial division
  4. Append error correction codewords to original data
  5. During decoding, use error correction to fix corrupted modules

Data Encoding Modes

QR codes support four primary encoding modes, each optimized for different data types:

1. Numeric Mode

Characters: 0-9 only

Efficiency: 3.33 bits per character

Example: "123456789" β†’ Most efficient for numbers

2. Alphanumeric Mode

Characters: 0-9, A-Z (uppercase), space, $ % * + - . / :

Efficiency: 5.5 bits per character

Example: "HTTPS://KBC.SH" β†’ Good for URLs

3. Byte Mode

Characters: Any 8-bit byte (ISO 8859-1 or UTF-8)

Efficiency: 8 bits per character

Example: "Hello, δΈ–η•Œ!" β†’ Binary data, mixed languages

4. Kanji Mode

Characters: Japanese Kanji (Shift JIS encoding)

Efficiency: 13 bits per character

Example: "ζΌ’ε­—" β†’ More efficient than byte mode for Japanese

QR Code Generation Implementation

Here's how to implement QR code generation in various programming environments:

JavaScript/Node.js Implementation

// Using the popular 'qrcode' library
const QRCode = require('qrcode');

// Basic QR code generation
async function generateQRCode(data, options = {}) {
  try {
    // Configuration options
    const config = {
      errorCorrectionLevel: options.errorCorrection || 'M',
      type: options.type || 'image/png',
      quality: options.quality || 0.92,
      margin: options.margin || 4,
      width: options.width || 400,
      color: {
        dark: options.darkColor || '#000000',
        light: options.lightColor || '#FFFFFF'
      }
    };

    // Generate QR code as Data URL
    const qrDataURL = await QRCode.toDataURL(data, config);

    return qrDataURL;
  } catch (error) {
    console.error('QR Code generation failed:', error);
    throw error;
  }
}

// Advanced: Generate with logo embedding
async function generateQRCodeWithLogo(data, logoPath) {
  const QRCodeCanvas = require('qrcode');
  const { createCanvas, loadImage } = require('canvas');

  // Create canvas
  const canvas = createCanvas(400, 400);
  const ctx = canvas.getContext('2d');

  // Generate QR code on canvas
  await QRCodeCanvas.toCanvas(canvas, data, {
    errorCorrectionLevel: 'H', // High for logo embedding
    margin: 2,
    width: 400
  });

  // Load and draw logo in center
  const logo = await loadImage(logoPath);
  const logoSize = 80;
  const logoX = (canvas.width - logoSize) / 2;
  const logoY = (canvas.height - logoSize) / 2;

  // Draw white background for logo
  ctx.fillStyle = 'white';
  ctx.fillRect(logoX - 10, logoY - 10, logoSize + 20, logoSize + 20);

  // Draw logo
  ctx.drawImage(logo, logoX, logoY, logoSize, logoSize);

  return canvas.toDataURL();
}

// Usage examples
generateQRCode('https://kbc.sh', {
  errorCorrection: 'H',
  width: 500,
  darkColor: '#8b5cf6',
  lightColor: '#faf5ff'
}).then(qrCode => {
  console.log('QR Code generated:', qrCode);
});

Python Implementation

# Using the 'qrcode' library
import qrcode
from PIL import Image

def generate_qr_code(data, filename='qrcode.png', **options):
    """
    Generate a QR code with customizable options
    """
    # Create QR code instance
    qr = qrcode.QRCode(
        version=options.get('version', 1),  # 1-40, or None for auto
        error_correction=options.get('error_correction', qrcode.constants.ERROR_CORRECT_M),
        box_size=options.get('box_size', 10),
        border=options.get('border', 4),
    )

    # Add data
    qr.add_data(data)
    qr.make(fit=True)

    # Create image
    img = qr.make_image(
        fill_color=options.get('fill_color', 'black'),
        back_color=options.get('back_color', 'white')
    )

    # Save image
    img.save(filename)
    return img

def generate_qr_with_logo(data, logo_path, output_path='qr_with_logo.png'):
    """
    Generate QR code with embedded logo
    """
    # Generate base QR code with high error correction
    qr = qrcode.QRCode(
        error_correction=qrcode.constants.ERROR_CORRECT_H,
        box_size=10,
        border=4,
    )
    qr.add_data(data)
    qr.make(fit=True)

    # Create QR image
    qr_img = qr.make_image(fill_color="black", back_color="white").convert('RGB')

    # Open and resize logo
    logo = Image.open(logo_path)

    # Calculate logo size (max 30% of QR code)
    qr_width, qr_height = qr_img.size
    logo_size = min(qr_width, qr_height) // 4

    # Resize logo
    logo = logo.resize((logo_size, logo_size), Image.LANCZOS)

    # Calculate position (center)
    logo_pos = ((qr_width - logo_size) // 2, (qr_height - logo_size) // 2)

    # Create white background for logo
    from PIL import ImageDraw
    draw = ImageDraw.Draw(qr_img)
    draw.rectangle(
        [logo_pos, (logo_pos[0] + logo_size, logo_pos[1] + logo_size)],
        fill='white'
    )

    # Paste logo
    qr_img.paste(logo, logo_pos, logo if logo.mode == 'RGBA' else None)

    # Save result
    qr_img.save(output_path)
    return qr_img

# Usage
generate_qr_code('https://kbc.sh/tools/qr-code-generator',
                 error_correction=qrcode.constants.ERROR_CORRECT_H,
                 box_size=15,
                 fill_color='#8b5cf6',
                 back_color='#faf5ff')

QR Code Scanning and Decoding

Implementing QR code scanning in web applications using modern browser APIs:

// Modern Web QR Scanner using jsQR library
import jsQR from 'jsqr';

class QRScanner {
  constructor(videoElementId, canvasElementId) {
    this.video = document.getElementById(videoElementId);
    this.canvas = document.getElementById(canvasElementId);
    this.canvasContext = this.canvas.getContext('2d');
    this.scanning = false;
  }

  async startScanning(onScanSuccess, onScanError) {
    try {
      // Request camera access
      const stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: 'environment' } // Use back camera on mobile
      });

      this.video.srcObject = stream;
      this.video.setAttribute('playsinline', true); // iOS compatibility
      this.video.play();

      this.scanning = true;
      this.scan(onScanSuccess, onScanError);
    } catch (error) {
      console.error('Camera access denied:', error);
      onScanError(error);
    }
  }

  scan(onSuccess, onError) {
    if (!this.scanning) return;

    if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
      // Set canvas dimensions to match video
      this.canvas.height = this.video.videoHeight;
      this.canvas.width = this.video.videoWidth;

      // Draw video frame to canvas
      this.canvasContext.drawImage(
        this.video,
        0, 0,
        this.canvas.width,
        this.canvas.height
      );

      // Get image data
      const imageData = this.canvasContext.getImageData(
        0, 0,
        this.canvas.width,
        this.canvas.height
      );

      // Attempt to decode QR code
      const code = jsQR(
        imageData.data,
        imageData.width,
        imageData.height,
        {
          inversionAttempts: 'dontInvert',
        }
      );

      if (code) {
        // QR code detected
        this.drawDetectionBox(code.location);
        onSuccess(code.data, code);
      }
    }

    // Continue scanning
    requestAnimationFrame(() => this.scan(onSuccess, onError));
  }

  drawDetectionBox(location) {
    // Draw corners of detected QR code
    this.canvasContext.beginPath();
    this.canvasContext.moveTo(location.topLeftCorner.x, location.topLeftCorner.y);
    this.canvasContext.lineTo(location.topRightCorner.x, location.topRightCorner.y);
    this.canvasContext.lineTo(location.bottomRightCorner.x, location.bottomRightCorner.y);
    this.canvasContext.lineTo(location.bottomLeftCorner.x, location.bottomLeftCorner.y);
    this.canvasContext.lineTo(location.topLeftCorner.x, location.topLeftCorner.y);
    this.canvasContext.lineWidth = 4;
    this.canvasContext.strokeStyle = '#00FF00';
    this.canvasContext.stroke();
  }

  stopScanning() {
    this.scanning = false;
    if (this.video.srcObject) {
      this.video.srcObject.getTracks().forEach(track => track.stop());
    }
  }
}

// Usage
const scanner = new QRScanner('video-preview', 'qr-canvas');

scanner.startScanning(
  (data, code) => {
    console.log('QR Code scanned:', data);
    console.log('Full code object:', code);

    // Process scanned data
    processQRData(data);
  },
  (error) => {
    console.error('Scanning error:', error);
  }
);

// Data processing examples
function processQRData(data) {
  // URL detection
  if (data.startsWith('http://') || data.startsWith('https://')) {
    window.location.href = data;
  }

  // Email detection
  else if (data.startsWith('mailto:')) {
    window.location.href = data;
  }

  // Phone number detection
  else if (data.startsWith('tel:')) {
    window.location.href = data;
  }

  // vCard contact detection
  else if (data.startsWith('BEGIN:VCARD')) {
    parseVCard(data);
  }

  // WiFi configuration
  else if (data.startsWith('WIFI:')) {
    parseWiFiConfig(data);
  }

  // Plain text
  else {
    displayText(data);
  }
}

Practical Applications and Use Cases

πŸ’³ Payments & Finance

  • β€’ Mobile payment systems (Alipay, WeChat Pay)
  • β€’ Cryptocurrency wallet addresses
  • β€’ Invoice generation and tracking
  • β€’ Banking authentication tokens

πŸ“± Marketing & Engagement

  • β€’ Product packaging and labels
  • β€’ Event tickets and registration
  • β€’ Restaurant menus (contactless)
  • β€’ Promotional campaigns and coupons

πŸ” Authentication & Security

  • β€’ Two-factor authentication (2FA/TOTP)
  • β€’ WiFi network credentials sharing
  • β€’ Digital identity verification
  • β€’ Secure document signing

πŸ“¦ Logistics & Tracking

  • β€’ Package tracking and delivery
  • β€’ Inventory management systems
  • β€’ Asset tagging and monitoring
  • β€’ Supply chain transparency

Special QR Code Formats

// WiFi Configuration QR Code
const wifiConfig = {
  ssid: 'MyNetwork',
  password: 'SecurePassword123',
  encryption: 'WPA' // WPA, WEP, or nopass
};

const wifiQRString = `WIFI:T:${wifiConfig.encryption};S:${wifiConfig.ssid};P:${wifiConfig.password};;`;

// vCard Contact QR Code
const vCardData = `BEGIN:VCARD
VERSION:3.0
FN:John Doe
ORG:KBC Grandcentral
TEL:+1-555-123-4567
EMAIL:[email protected]
URL:https://kbc.sh
ADR:;;123 Main St;San Francisco;CA;94105;USA
END:VCARD`;

// Event/Calendar QR Code
const eventData = `BEGIN:VEVENT
SUMMARY:Team Meeting
DTSTART:20251120T140000Z
DTEND:20251120T150000Z
LOCATION:Conference Room A
DESCRIPTION:Monthly team sync
END:VEVENT`;

// Email Composition QR Code
const emailQR = 'mailto:[email protected]?subject=Support Request&body=Hello, I need help with...';

// SMS/Text Message QR Code
const smsQR = 'SMSTO:+15551234567:Hello from QR code!';

// Generate QR codes for each format
generateQRCode(wifiQRString);    // WiFi credentials
generateQRCode(vCardData);       // Contact card
generateQRCode(eventData);       // Calendar event
generateQRCode(emailQR);         // Email template
generateQRCode(smsQR);           // SMS message

Security Considerations

⚠️ QR Code Security Risks

  • QRishing (QR Phishing): Malicious QR codes linking to phishing websites
  • URL Manipulation: Short URLs hiding malicious destinations
  • Data Injection: Embedded scripts or SQL injection attempts
  • Physical Tampering: Stickers placed over legitimate QR codes
  • Session Hijacking: QR codes exposing authentication tokens

Best Security Practices

  1. 1. Always Preview URLs Before Opening

    Display the full URL to users before navigating, allowing them to verify the destination

  2. 2. Implement Content Security Policy (CSP)

    Prevent execution of malicious scripts from scanned QR data

  3. 3. Validate and Sanitize Input

    Never trust QR code data; validate format and sanitize content

  4. 4. Use HTTPS Only

    Generate QR codes with HTTPS URLs to ensure encrypted connections

  5. 5. Set Expiration for Sensitive QR Codes

    Time-limited codes for authentication, payments, or access control

  6. 6. Implement Rate Limiting

    Prevent brute-force attacks on QR-based authentication systems

Secure QR Code Validation Example

// Secure QR code data validation
function validateQRData(data) {
  const validators = {
    url: (data) => {
      try {
        const url = new URL(data);

        // Check for HTTPS
        if (url.protocol !== 'https:') {
          return { valid: false, error: 'Only HTTPS URLs allowed' };
        }

        // Check against whitelist
        const allowedDomains = ['kbc.sh', 'trusted-domain.com'];
        const isAllowed = allowedDomains.some(domain =>
          url.hostname === domain || url.hostname.endsWith(`.${domain}`)
        );

        if (!isAllowed) {
          return { valid: false, error: 'Domain not in whitelist' };
        }

        return { valid: true, type: 'url', data: url.href };
      } catch {
        return { valid: false, error: 'Invalid URL format' };
      }
    },

    email: (data) => {
      const emailRegex = /^mailto:([a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/;
      const match = data.match(emailRegex);

      if (!match) {
        return { valid: false, error: 'Invalid email format' };
      }

      return { valid: true, type: 'email', data: match[1] };
    },

    phone: (data) => {
      const phoneRegex = /^tel:(\+?[0-9]{10,15})$/;
      const match = data.match(phoneRegex);

      if (!match) {
        return { valid: false, error: 'Invalid phone format' };
      }

      return { valid: true, type: 'phone', data: match[1] };
    }
  };

  // Sanitize input
  const sanitized = data.trim();

  // Detect type and validate
  if (sanitized.startsWith('http://') || sanitized.startsWith('https://')) {
    return validators.url(sanitized);
  } else if (sanitized.startsWith('mailto:')) {
    return validators.email(sanitized);
  } else if (sanitized.startsWith('tel:')) {
    return validators.phone(sanitized);
  }

  // Plain text - sanitize for XSS
  const sanitizedText = sanitized
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;');

  return { valid: true, type: 'text', data: sanitizedText };
}

// Usage with user confirmation
function handleScannedQR(qrData) {
  const validation = validateQRData(qrData);

  if (!validation.valid) {
    alert(`Security Warning: ${validation.error}`);
    return;
  }

  if (validation.type === 'url') {
    // Show confirmation dialog
    const confirmed = confirm(`Open this URL?\n\n${validation.data}`);
    if (confirmed) {
      window.location.href = validation.data;
    }
  } else {
    // Process other validated data
    processValidatedData(validation);
  }
}

Performance Optimization

πŸ“ Size Optimization

  • β€’ Choose appropriate error correction level
  • β€’ Use numeric/alphanumeric modes when possible
  • β€’ Minimize data length (use URL shorteners)
  • β€’ Optimize version selection (smaller is faster)

🎨 Visual Optimization

  • β€’ Ensure sufficient contrast (3:1 minimum)
  • β€’ Add quiet zone (4 modules minimum)
  • β€’ Use vector formats (SVG) when possible
  • β€’ Avoid excessive customization (dots, gradients)

πŸ“± Scanning Optimization

  • β€’ Print at minimum 2Γ—2 cm (0.8Γ—0.8 inches)
  • β€’ Use matte finish to reduce glare
  • β€’ Test scanning from various distances
  • β€’ Consider lighting conditions

⚑ Generation Performance

  • β€’ Cache frequently generated codes
  • β€’ Use Web Workers for bulk generation
  • β€’ Implement lazy loading for displays
  • β€’ Pre-generate static codes at build time

Related Tools on KBC Grandcentral

Conclusion

QR code technology has evolved from inventory tracking to become an essential tool for contactless information sharing in our digital world. Understanding the underlying structure, encoding modes, error correction mechanisms, and security considerations enables developers to implement robust QR code solutions.

Whether you're building payment systems, marketing campaigns, authentication workflows, or logistics tracking, QR codes provide a reliable, standardized method for bridging physical and digital experiences. By following best practices for generation, security, and implementation, you can create QR code solutions that are both user-friendly and secure.