在 iOS10 上生成的 GIF 图像不再在浏览器上永远循环

Posted

技术标签:

【中文标题】在 iOS10 上生成的 GIF 图像不再在浏览器上永远循环【英文标题】:GIF Image generated on iOS10 no longer loops forever on browser 【发布时间】:2017-03-11 15:37:27 【问题描述】:

这是一个生成GIF图像的ObjectiveC方法:

@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

ios9 上运行此方法效果很好,GIF 会在浏览器上永久生成循环:

在 iOS10 上运行同样的方法失败,生成的 GIF 不再在浏览器上永远循环,它只播放一次:

此外,受此答案的启发:https://***.com/a/38082881/448662,我对 iOS9 和 iOS10 中生成的两个 GIF 进行了十六进制比较,似乎 iOS10 生成的 GIF 中缺少一个片段(Netscape 应用程序扩展),这可能是它不循环的原因,但我不能确定。

简而言之,我们如何生成在浏览器上永久循环的 GIF 图像(使用 ObjectiveC)?

【问题讨论】:

据我所知,这一切都取决于 imageview animationRepeat 属性。 我需要生成的 GIF 在浏览器上正确循环(在 iOS 上生成的图像将上传到服务器,然后在网站上呈现)。编辑了我的问题以澄清这一点。 @mkto 缺少NETSCAPE 扩展命令是问题所在。如果你可以在你的 API 的第一帧之前添加一个 application extension 块(对不起,不要在 IOS 上编码,所以我不知道是否可能)然后就这样做。如果不使用另一个编码器库或将块注入自己(最好是在内存中),那么您在我链接的答案中得到的所有需要​​编码的东西(在子链接中也是找到正确位置的 C++ 代码为它)。 【参考方案1】:

我在此 GitHub 存储库的最近提交中找到了解决方案: https://github.com/NSRare/NSGIF/pull/23/files?diff=split

基本上,在 CGImageDestinationAddImage 之前调用 CGImageDestinationSetProperties 可以解决 iOS10 上的问题。

这是工作代码:

@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;

【讨论】:

以上是关于在 iOS10 上生成的 GIF 图像不再在浏览器上永远循环的主要内容,如果未能解决你的问题,请参考以下文章

如何保证对我的服务器的请求是由我的 iOS 应用程序在真实设备上生成的?

Puttygen 和 NodeJS 上生成的 RSA 密钥的长度不同

Beanstalk:如何将服务器上生成的文件同步回 beanstalk 存储库?

Apollo Android 客户端 - 无法访问类路径上生成的类

GIF 图像不显示在 iPhone 上

当必须首先在服务器上生成图像时,将图像异步预加载到浏览器缓存中