Added support to encode APNG instead of GIF, when no animated image format provided by dreampiggy · Pull Request #3867 · SDWebImage/SDWebImage
178-197: ⚠️ Potential issue | 🔴 Critical
Bug: format variable is declared but never used — animated frames always encoded as GIF.
Lines 178–183 compute format based on OS version (PNG for iOS 12+ / macOS 10.14+, GIF otherwise), but line 184 ignores it and hardcodes SDImageFormatGIF:
CFStringRef imageUTType = [NSData sd_UTTypeFromImageFormat:SDImageFormatGIF]; // always GIF
Additionally, line 196 uses GIF-specific property keys (kCGImagePropertyGIFDictionary / kCGImagePropertyGIFDelayTime) regardless of the format. For APNG, these should use the PNG-specific equivalents nested inside kCGImagePropertyPNGDictionary (e.g., kCGImagePropertyAPNGDelayTime).
As a result, animatedImageWithFrames: always produces GIF data regardless of OS version, defeating the purpose of this PR.
🐛 Proposed fix
SDImageFormat format;
if (`@available`(iOS 12.0, tvOS 12.0, macOS 10.14, watchOS 5.0, *)) {
format = SDImageFormatPNG;
} else {
format = SDImageFormatGIF;
}
- CFStringRef imageUTType = [NSData sd_UTTypeFromImageFormat:SDImageFormatGIF];
- // Create an image destination. GIF does not support EXIF image orientation
+ CFStringRef imageUTType = [NSData sd_UTTypeFromImageFormat:format];
+ // Create an image destination. GIF/APNG does not support EXIF image orientation
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, imageUTType, frameCount, NULL);
if (!imageDestination) {
// Handle failure.
return nil;
}
for (size_t i = 0; i < frameCount; i++) {
SDImageFrame *frame = frames[i];
NSTimeInterval frameDuration = frame.duration;
CGImageRef frameImageRef = frame.image.CGImage;
- NSDictionary *frameProperties = @{(__bridge NSString *)kCGImagePropertyGIFDictionary : @{(__bridge NSString *)kCGImagePropertyGIFDelayTime : @(frameDuration)}};
+ NSDictionary *frameProperties;
+ if (format == SDImageFormatPNG) {
+ frameProperties = @{(__bridge NSString *)kCGImagePropertyPNGDictionary : @{(__bridge NSString *)kCGImagePropertyAPNGDelayTime : @(frameDuration)}};
+ } else {
+ frameProperties = @{(__bridge NSString *)kCGImagePropertyGIFDictionary : @{(__bridge NSString *)kCGImagePropertyGIFDelayTime : @(frameDuration)}};
+ }
CGImageDestinationAddImage(imageDestination, frameImageRef, (__bridge CFDictionaryRef)frameProperties);
}