Merge pull request #2067 from dreampiggy/feature_gif_encoding_macOS
Add the animated GIF encoding support for SDWebImageGIFCoder on macOS(use NSImage's API)
This commit is contained in:
commit
30275b4415
|
@ -45,8 +45,7 @@
|
|||
|
||||
if (count <= 1) {
|
||||
animatedImage = [[UIImage alloc] initWithData:data];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
NSMutableArray *images = [NSMutableArray array];
|
||||
|
||||
NSTimeInterval duration = 0.0f;
|
||||
|
@ -103,9 +102,7 @@
|
|||
NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
|
||||
if (delayTimeUnclampedProp) {
|
||||
frameDuration = [delayTimeUnclampedProp floatValue];
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
|
||||
if (delayTimeProp) {
|
||||
frameDuration = [delayTimeProp floatValue];
|
||||
|
@ -147,11 +144,22 @@
|
|||
}
|
||||
|
||||
NSMutableData *imageData = [NSMutableData data];
|
||||
NSUInteger frameCount = 0; // assume static images by default
|
||||
CFStringRef imageUTType = [NSData sd_UTTypeFromSDImageFormat:format];
|
||||
NSUInteger frameCount = 1;
|
||||
if (image.images) {
|
||||
frameCount = image.images.count;
|
||||
#if SD_MAC
|
||||
NSBitmapImageRep *bitmapRep;
|
||||
for (NSImageRep *imageRep in image.representations) {
|
||||
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
|
||||
bitmapRep = (NSBitmapImageRep *)imageRep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bitmapRep) {
|
||||
frameCount = [[bitmapRep valueForProperty:NSImageFrameCount] unsignedIntegerValue];
|
||||
}
|
||||
#else
|
||||
frameCount = image.images.count;
|
||||
#endif
|
||||
|
||||
// Create an image destination. GIF does not support EXIF image orientation
|
||||
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, imageUTType, frameCount, NULL);
|
||||
|
@ -160,29 +168,30 @@
|
|||
return nil;
|
||||
}
|
||||
|
||||
#ifdef SD_MAC
|
||||
CGImageDestinationAddImage(imageDestination, image.CGImage, nil);
|
||||
#else
|
||||
if (!image.images) {
|
||||
if (frameCount == 0) {
|
||||
// for static single GIF images
|
||||
CGImageDestinationAddImage(imageDestination, image.CGImage, nil);
|
||||
} else {
|
||||
// for animated GIF images
|
||||
NSUInteger loopCount = image.sd_imageLoopCount;
|
||||
NSTimeInterval totalDuration = image.duration;
|
||||
NSTimeInterval frameDuration = totalDuration / frameCount;
|
||||
NSDictionary *gifProperties = @{(__bridge_transfer NSString *)kCGImagePropertyGIFDictionary: @{(__bridge_transfer NSString *)kCGImagePropertyGIFLoopCount : @(loopCount)}};
|
||||
CGImageDestinationSetProperties(imageDestination, (__bridge CFDictionaryRef)gifProperties);
|
||||
for (size_t i = 0; i < frameCount; i++) {
|
||||
@autoreleasepool {
|
||||
NSDictionary *frameProperties = @{(__bridge_transfer NSString *)kCGImagePropertyGIFDictionary : @{(__bridge_transfer NSString *)kCGImagePropertyGIFUnclampedDelayTime : @(frameDuration)}};
|
||||
#if SD_MAC
|
||||
// NSBitmapImageRep need to manually change frame. "Good taste" API
|
||||
[bitmapRep setProperty:NSImageCurrentFrame withValue:@(i)];
|
||||
float frameDuration = [[bitmapRep valueForProperty:NSImageCurrentFrameDuration] floatValue];
|
||||
CGImageRef frameImageRef = bitmapRep.CGImage;
|
||||
#else
|
||||
float frameDuration = image.duration / frameCount;
|
||||
CGImageRef frameImageRef = image.images[i].CGImage;
|
||||
#endif
|
||||
NSDictionary *frameProperties = @{(__bridge_transfer NSString *)kCGImagePropertyGIFDictionary : @{(__bridge_transfer NSString *)kCGImagePropertyGIFUnclampedDelayTime : @(frameDuration)}};
|
||||
CGImageDestinationAddImage(imageDestination, frameImageRef, (__bridge CFDictionaryRef)frameProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Finalize the destination.
|
||||
if (CGImageDestinationFinalize(imageDestination) == NO) {
|
||||
// Handle failure.
|
||||
|
|
|
@ -89,11 +89,11 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
return nil;
|
||||
}
|
||||
|
||||
#if SD_MAC
|
||||
return [[UIImage alloc] initWithData:data];
|
||||
#else
|
||||
|
||||
UIImage *image = [[UIImage alloc] initWithData:data];
|
||||
|
||||
#if SD_MAC
|
||||
return image;
|
||||
#else
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
|
@ -105,14 +105,12 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
image = [UIImage animatedImageWithImages:@[image] duration:image.duration];
|
||||
return image;
|
||||
}
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIImageOrientation orientation = [[self class] sd_imageOrientationFromImageData:data];
|
||||
if (orientation != UIImageOrientationUp) {
|
||||
image = [UIImage imageWithCGImage:image.CGImage
|
||||
scale:image.scale
|
||||
orientation:orientation];
|
||||
}
|
||||
#endif
|
||||
|
||||
return image;
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue