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 callscreateAnimatedImageDataWith(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 returningCGImageinstances (lines 797-842).createAnimatedImageDataWith(format:frames:frameDelays:)– PacksCGImageframes into GIF or APNG usingCGImageDestination, 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:
- GIF and APNG – Encoded via
CGImageDestinationwithkCGImagePropertyGIFDelayTimeorkCGImagePropertyAPNGDelayTimemetadata. - Video (MOV, MP4, M4V) – Generated through an AVFoundation writer pipeline via
toVideoData(format:size:insets:)andcreateVideoDataWith.
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: trueinEFStyleImageParamsImageif your source GIF or APNG contains alpha channels. Otherwise, transparent pixels render as opaque. - Frame calculation – Use
calculateSize(width:)orcalculateSize(height:)on the generator instance to determine the exactCGSizebefore exporting, ensuring your UI containers match the output dimensions. - Parallel rendering – Frame generation utilizes
OperationQueuefor concurrent processing. Long animations with many frames benefit significantly from multi-core devices. - Size insets – Pass explicit
insetsparameters totoGIFDataortoAPNGDataif you need padding around the QR code within the animation canvas.
Summary
- EFQRCode generates animated QR codes through
EFQRCode.Generatorwith methods liketoGIFData,toAPNGData, andtoMp4Data. - The animation pipeline reconciles frames from animated icons, watermarks, or SVG elements using
reconcileQRImagesand parallel processing. - Animated image formats use
CGImageDestinationwith per-frame delay dictionaries, while video formats use AVFoundation writers. - Set
allowTransparent: truefor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →