How to Generate Animated QR Codes with EFQRCode: A Complete Guide

EFQRCode generates animated QR codes in GIF, APNG, and video formats by synchronizing animated icons or watermarks with the QR code SVG and encoding frames using CGImageDestination or AVFoundation writers.

The EFQRCode library extends traditional QR code generation with rich styling options, including support for animated content. Whether you need a marketing GIF with a rotating logo or an MP4 video for social media, the animation pipeline in efprefix/efqrcode handles frame synchronization, rasterization, and encoding through a unified Swift API.

Understanding the EFQRCode Animation Architecture

The animation system centers on the EFQRCode.Generator class, which exposes convenience methods like toGIFData and toAPNGData. Internally, the generator delegates to a generic toAnimatedImage routine that coordinates frame extraction, timing reconciliation, and final data encoding.

Key components in Source/EFQRCode+Generator.swift include:

  • toAnimatedImage(format:size:insets:) – A private helper that obtains the frame list [CGImage] and per-frame delays [CGFloat], then calls createAnimatedImageDataWith (lines 779-792).
  • getAnimatedFrames(size:insets:) – Determines if the QR code contains animated SVG elements or animated style images. If detected, it reconciles the icon, watermark, and QR layers into synchronized frames (lines 520-564).
  • reconcileQRImages(image1:image2:style:size:) – Parallelizes frame rendering by creating temporary generators for each animation delay, rasterizing the QR code SVG, and returning CGImage instances (lines 797-842).
  • createAnimatedImageDataWith(format:frames:frameDelays:) – Packs CGImage frames into GIF or APNG using CGImageDestination, applying per-frame delay dictionaries and loop-forever properties (lines 886-926).

The EFAnimatedImageFormat enum in Source/Type/EFAnimatedImageFormat.swift maps supported formats to CoreGraphics UTType identifiers, while Source/Styles/EFQRCodeStyleImage.swift defines EFStyleImageParamsImage, which can hold either static or animated image parameters.

How the Animation Pipeline Works

Frame Generation and Synchronization

When you call toGIFData(width:) or toAPNGData(width:), the generator first checks isAnimated to detect SVG <animate> elements or animated style images. If the style contains an animated icon or watermark, the pipeline enters frame reconciliation mode.

The reconcileQRImages function calculates the least common multiple (LCM) of animation durations between assets to ensure perfect synchronization. It uses an internal OperationQueue to parallelize the rendering of each frame, significantly improving performance for long animations on multi-core devices.

Image Format Support (GIF, APNG, and Video)

EFQRCode supports three output categories:

  1. GIF and APNG – Encoded via CGImageDestination with kCGImagePropertyGIFDelayTime or kCGImagePropertyAPNGDelayTime metadata.
  2. Video (MOV, MP4, M4V) – Generated through an AVFoundation writer pipeline via toVideoData(format:size:insets:) and createVideoDataWith.

The same frame extraction logic applies regardless of output format, allowing you to generate both web-optimized GIFs and broadcast-ready MP4s from identical source configurations.

Code Examples: Creating Animated QR Codes

Example 1: GIF Watermark

Create a QR code with an animated GIF watermark using EFStyleImageParamsImage with a loaded GIF source:

import EFQRCode
import UIKit

// Load animated GIF from bundle
let watermark = try EFImage.gif(named: "watermark")
let style = EFQRCodeStyle.image(
    params: .init(
        image: .init(
            image: watermark,
            mode: .scaleAspectFill,
            alpha: 1.0,
            allowTransparent: true
        )
    )
)

let generator = try EFQRCode.Generator(
    "https://example.com",
    style: .init(style)
)

// Generate GIF data at 300pt width
let gifData = try generator.toGIFData(width: 300)

// Write to temporary directory
let url = FileManager.default.temporaryDirectory.appendingPathComponent("qr.gif")
try gifData.write(to: url)

The toGIFData(width:) method initiates the animated pipeline (see EFQRCode+Generator.swift, lines 395-423).

Example 2: APNG with Rotating Icon

Supply a sequence of images as an animated icon for APNG output:

import EFQRCode
import UIKit

// Load sequence of PNGs forming a rotation animation
let iconFrames: [CGImage] = (1...12).compactMap { idx in
    UIImage(named: "icon_\(idx)")?.cgImage
}
let delays: [CGFloat] = Array(repeating: 0.08, count: iconFrames.count)

// Build animated image parameters
let animatedIcon = EFStyleParamImage.animated(images: iconFrames, imageDelays: delays)

let style = EFQRCodeStyle.image(
    params: .init(
        icon: .init(
            image: animatedIcon,
            mode: .scaleAspectFit,
            alpha: 1.0,
            allowTransparent: false
        )
    )
)

let generator = try EFQRCode.Generator(
    "Animated icon demo",
    style: .init(style)
)

// Generate APNG at 400pt width
let apngData = try generator.toAPNGData(width: 400)

let apngURL = FileManager.default.temporaryDirectory.appendingPathComponent("qr.png")
try apngData.write(to: apngURL)

toAPNGData(width:) shares implementation logic with the GIF exporter (lines 427-445 in EFQRCode+Generator.swift).

Example 3: MP4 Video Output

Generate video files for platforms that don't support animated images:

import EFQRCode
import UIKit

// Reuse animated icon from previous example
let style = EFQRCodeStyle.image(
    params: .init(
        icon: .init(image: animatedIcon)
    )
)

let generator = try EFQRCode.Generator(
    "Video output example",
    style: .init(style)
)

// Generate MP4 at 500pt width
let mp4Data = try generator.toMp4Data(width: 500)

let videoURL = FileManager.default.temporaryDirectory.appendingPathComponent("qr.mp4")
try mp4Data.write(to: videoURL)

Video generation routes through toVideoData and createVideoDataWith in the same generator source file.

Performance Optimization and Best Practices

When generating animated QR codes with EFQRCode, consider these implementation details from the source code:

  • Transparency handling – Set allowTransparent: true in EFStyleImageParamsImage if your source GIF or APNG contains alpha channels. Otherwise, transparent pixels render as opaque.
  • Frame calculation – Use calculateSize(width:) or calculateSize(height:) on the generator instance to determine the exact CGSize before exporting, ensuring your UI containers match the output dimensions.
  • Parallel rendering – Frame generation utilizes OperationQueue for concurrent processing. Long animations with many frames benefit significantly from multi-core devices.
  • Size insets – Pass explicit insets parameters to toGIFData or toAPNGData if you need padding around the QR code within the animation canvas.

Summary

  • EFQRCode generates animated QR codes through EFQRCode.Generator with methods like toGIFData, toAPNGData, and toMp4Data.
  • The animation pipeline reconciles frames from animated icons, watermarks, or SVG elements using reconcileQRImages and parallel processing.
  • Animated image formats use CGImageDestination with per-frame delay dictionaries, while video formats use AVFoundation writers.
  • Set allowTransparent: true for alpha channel support and use built-in size calculators to preview dimensions before generation.

Frequently Asked Questions

Can EFQRCode generate animated QR codes with transparent backgrounds?

Yes. When configuring your EFStyleImageParamsImage, set the allowTransparent parameter to true. This preserves alpha channels from animated GIF or APNG sources during frame rasterization in reconcileQRImages.

What video formats does EFQRCode support for animated QR codes?

EFQRCode supports MOV, MP4, and M4V outputs. These are generated through the toMovData, toMp4Data, and toM4VData methods, which utilize AVFoundation writers rather than CGImageDestination.

How does EFQRCode handle different animation durations for icons and watermarks?

The library automatically calculates the least common multiple (LCM) of animation durations between assets using the internal lcm(_:_:) function. This ensures synchronized looping regardless of differing frame counts or delay timings between the icon and watermark.

Is frame rendering parallelized in EFQRCode?

Yes. The reconcileQRImages function distributes frame generation across an OperationQueue, allowing multiple frames to render simultaneously on multi-core processors. This significantly reduces generation time for complex animations with many frames.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →