Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 201
mkto Avatar asked Oct 28 '16 17:10

mkto


People also ask

How to loop a GIF on Windows 10?

Upload a GIF file Select a GIF file from your folder after clicking on ‘Choose GIF File’. You can also drag and drop your GIF image into the box. 2. Loop your GIF Create a loop by adding the same GIF image. Just click on the plus (+) button on the bottom-right of the editor and select the same file. 3. Export your GIF Click on ‘Export’.

Why are my GIFs looping?

The GIF is completely fine the problem is on a modern internet browser's side. Affected browsers are Opera, IE, and Chrome (didn't test others). After some investigation on the matter (by comparing looping and non-looping images), I found out that these browsers' GIF decoders are ignoring the looping parameters in GIF files.

How to create infinite looping GIFs in seconds?

Create infinite looping GIFs in seconds, with just a few clicks. You don’t need to download an app or create an account. VEED’s online GIF editor lets you loop your animated GIF images. You can also create cool new GIFs from YouTube videos and convert videos of different formats into GIF files. Simply upload your video or paste a YouTube link.

Why can’t I see GIFs on my iPhone?

If you don't see #images, it is possible that you are in a region where GIFs are not supported. In this situation, you can change the region to a country that supports this feature. On your iPhone, go to Settings and tap on "General". Scroll down to "Laguage & Region" to change the settings.


1 Answers

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;
}
like image 188
mkto Avatar answered Nov 06 '22 20:11

mkto