Fix AppKit SDImageCoderHelper does not use APNG instead of GIF for animated image creation

This commit is contained in:
DreamPiggy
2026-02-26 15:24:16 +08:00
parent d04692e787
commit 1bf9029df1
2 changed files with 22 additions and 23 deletions
+9 -21
View File
@@ -19,6 +19,8 @@
#import "SDInternalMacros.h"
#import "SDDeviceHelper.h"
#import "SDImageIOAnimatedCoderInternal.h"
#import "SDImageAPNGCoder.h"
#import "SDImageGIFCoder.h"
#import <Accelerate/Accelerate.h>
#define kCGColorSpaceDeviceRGB CFSTR("kCGColorSpaceDeviceRGB")
@@ -174,35 +176,21 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
#else
NSMutableData *imageData = [NSMutableData data];
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:format];
// Create an image destination. GIF does not support EXIF image orientation
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, imageUTType, frameCount, NULL);
if (!imageDestination) {
// Handle failure.
NSData *imageData;
if (format == SDImageFormatPNG) {
imageData = [SDImageAPNGCoder.sharedCoder encodedDataWithFrames:frames loopCount:0 format:format options:nil];
} else {
imageData = [SDImageGIFCoder.sharedCoder encodedDataWithFrames:frames loopCount:0 format:format options:nil];
}
if (!imageData) {
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)}};
CGImageDestinationAddImage(imageDestination, frameImageRef, (__bridge CFDictionaryRef)frameProperties);
}
// Finalize the destination.
if (CGImageDestinationFinalize(imageDestination) == NO) {
// Handle failure.
CFRelease(imageDestination);
return nil;
}
CFRelease(imageDestination);
CGFloat scale = MAX(frames.firstObject.image.scale, 1);
SDAnimatedImageRep *imageRep = [[SDAnimatedImageRep alloc] initWithData:imageData];
+13 -2
View File
@@ -450,7 +450,18 @@
// Test old API
UIImage *animatedImage = [SDImageCoderHelper animatedImageWithFrames:frames];
NSData *data = [SDImageGIFCoder.sharedCoder encodedDataWithImage:animatedImage format:SDImageFormatGIF options:nil];
SDImageFormat format;
if (@available(iOS 12.0, tvOS 12.0, macOS 10.14, watchOS 5.0, *)) {
format = SDImageFormatPNG;
} else {
format = SDImageFormatGIF;
}
NSData *data;
if (format == SDImageFormatPNG) {
data = [SDImageAPNGCoder.sharedCoder encodedDataWithImage:animatedImage format:format options:nil];;
} else {
data = [SDImageGIFCoder.sharedCoder encodedDataWithImage:animatedImage format:format options:nil];
}
expect(data).notTo.beNil();
#if SD_MAC
@@ -458,7 +469,7 @@
SDAnimatedImageRep *rep = (SDAnimatedImageRep *)animatedImage.representations.firstObject;
expect([rep isKindOfClass:SDAnimatedImageRep.class]);
expect(rep.animatedImageData).equal(data);
expect(rep.animatedImageFormat).equal(SDImageFormatGIF);
expect(rep.animatedImageFormat).equal(format);
#endif
// Test new API