mkto
mkto

Reputation: 4665

GIF Image generated on iOS10 no longer loops forever on browser

This is an ObjectiveC method that generates GIF image:

@implementation NSArray (GIFImage)

- (NSString*)GIFImageWithImageDuration:(CGFloat)GIFImageDuration
{
    NSArray *images = self;

    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"animated.gif"];
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path],
                                                                        kUTTypeGIF,
                                                                        images.count,
                                                                        NULL);

    NSDictionary *frameProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:GIFImageDuration]
                                                                                                   forKey:(NSString *)kCGImagePropertyGIFDelayTime]
                                                                forKey:(NSString *)kCGImagePropertyGIFDictionary];


    NSDictionary *gifProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount]
                                                              forKey:(NSString *)kCGImagePropertyGIFDictionary];

    for ( NSInteger index = 0; index < images.count; index++ )
    {
        UIImage *image = (UIImage *)[images objectAtIndex:index];
        CGImageDestinationAddImage(destination, image.CGImage, (CFDictionaryRef)frameProperties);
    }

    CGImageDestinationSetProperties(destination, (CFDictionaryRef)gifProperties);
    CGImageDestinationFinalize(destination);
    CFRelease(destination);
    NSLog(@"animated GIF file created at %@", path);
    return path;
}

@end

Running this method on iOS9 works fine, GIF generated loops forever on browsers:

enter image description here

Running the same method on iOS10 fails, GIF generated no longer loops forever on browsers, it only play once:

enter image description here

Besides, inspired by this answer: https://stackoverflow.com/a/38082881/448662, I did a hex comparison of the two GIFs generated in both iOS9 and iOS10, it appears that a segment (Netscape application extension) is missing in the iOS10 generated GIF, this could be the reason why it doesn't loop, but I can't be sure.

In short, how can we generate GIF image (using ObjectiveC) that loops forever on browser?

enter image description here

Upvotes: 6

Views: 728

Answers (1)

mkto
mkto

Reputation: 4665

I found the solution on a recent commit on this GitHub repo: https://github.com/NSRare/NSGIF/pull/23/files?diff=split

Basically, calling CGImageDestinationSetProperties before CGImageDestinationAddImage solves the problem on iOS10.

This is the working code:

@implementation NSArray (GIFImage)
- (NSString*)GIFImageWithImageDuration:(CGFloat)GIFImageDuration
{
    NSArray *images = self;

    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"animated.gif"];
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path],
                                                                        kUTTypeGIF,
                                                                        images.count,
                                                                        NULL);

    NSDictionary *frameProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:GIFImageDuration]
                                                                                                   forKey:(NSString *)kCGImagePropertyGIFDelayTime]
                                                                forKey:(NSString *)kCGImagePropertyGIFDictionary];


    NSDictionary *gifProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0] forKey:(NSString *)kCGImagePropertyGIFLoopCount]
                                                              forKey:(NSString *)kCGImagePropertyGIFDictionary];

    CGImageDestinationSetProperties(destination, (CFDictionaryRef)gifProperties);

    for ( NSInteger index = 0; index < images.count; index++ )
    {
        UIImage *image = (UIImage *)[images objectAtIndex:index];
        CGImageDestinationAddImage(destination, image.CGImage, (CFDictionaryRef)frameProperties);
    }

    CGImageDestinationFinalize(destination);
    CFRelease(destination);
    NSLog(@"animated GIF file created at %@", path);
    return path;
}

Upvotes: 4

Related Questions