首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >通过iOS创建和导出动画gif?

通过iOS创建和导出动画gif?
EN

Stack Overflow用户
提问于 2013-02-17 05:09:32
回答 3查看 39.3K关注 0票数 74

我在一个iOS应用程序中有一系列用户自定义的图像,这些图像以简单的、逐帧动画的方式进行动画处理。

我的问题是:有没有一种方法可以允许用户将他们的动画导出为动画gif?理想情况下,我希望使他们能够发送电子邮件、社交共享(T/FB)或(最坏的情况..)将动画gif保存到他们的documents文件夹中,以便通过iTunes检索。

我知道如何将.png保存到图片库,并且我找到了一种将动画录制为QT文件(http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/)的方法,但我还没有找到一种方法来踢出一个普通的老式动画gif。我是不是在Core Animation或其他地方遗漏了什么?有没有任何人可以推荐的方法、框架或资源?抱歉,如果这个问题太笼统--很难找到一个起点。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-17 07:01:36

您可以使用Image I/O框架(它是iOS软件开发工具包的一部分)创建动画GIF。您还需要包含MobileCoreServices框架,它定义了GIF类型常量。您需要将这些框架添加到您的目标,并将它们的头文件导入到要创建动画GIF的文件中,如下所示:

代码语言:javascript
复制
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>

这是最容易用例子来解释的。我将向你展示我用来在我的iPhone 5上制作这个GIF的代码:

首先,下面是一个辅助函数,它接受一个大小和一个角度,并返回该角度下红色圆盘的UIImage

代码语言:javascript
复制
static UIImage *frameImage(CGSize size, CGFloat radians) {
    UIGraphicsBeginImageContextWithOptions(size, YES, 1); {
        [[UIColor whiteColor] setFill];
        UIRectFill(CGRectInfinite);
        CGContextRef gc = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(gc, size.width / 2, size.height / 2);
        CGContextRotateCTM(gc, radians);
        CGContextTranslateCTM(gc, size.width / 4, 0);
        [[UIColor redColor] setFill];
        CGFloat w = size.width / 10;
        CGContextFillEllipseInRect(gc, CGRectMake(-w / 2, -w / 2, w, w));
    }
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

现在我们可以创建GIF了。首先,我们将为帧数定义一个常量,因为我们以后需要它两次:

代码语言:javascript
复制
static void makeAnimatedGif(void) {
    static NSUInteger const kFrameCount = 16;

我们需要一个属性字典来指定动画应该重复的次数:

代码语言:javascript
复制
    NSDictionary *fileProperties = @{
        (__bridge id)kCGImagePropertyGIFDictionary: @{
            (__bridge id)kCGImagePropertyGIFLoopCount: @0, // 0 means loop forever
        }
    };

我们还需要另一个属性字典,我们将把它附加到每个框架,指定框架应该显示多长时间:

代码语言:javascript
复制
    NSDictionary *frameProperties = @{
        (__bridge id)kCGImagePropertyGIFDictionary: @{
            (__bridge id)kCGImagePropertyGIFDelayTime: @0.02f, // a float (not double!) in seconds, rounded to centiseconds in the GIF data
        }
    };

我们还将在文档目录中为GIF创建一个URL:

代码语言:javascript
复制
    NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
    NSURL *fileURL = [documentsDirectoryURL URLByAppendingPathComponent:@"animated.gif"];

现在我们可以创建一个CGImageDestination,它将一个GIF写入指定的URL:

代码语言:javascript
复制
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeGIF, kFrameCount, NULL);
    CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties);

我发现,将fileProperties作为CGImageDestinationCreateWithURL的最后一个参数传递时,不能用于。您必须使用CGImageDestinationSetProperties

现在我们可以创建和编写框架了:

代码语言:javascript
复制
    for (NSUInteger i = 0; i < kFrameCount; i++) {
        @autoreleasepool {
            UIImage *image = frameImage(CGSizeMake(300, 300), M_PI * 2 * i / kFrameCount);
            CGImageDestinationAddImage(destination, image.CGImage, (__bridge CFDictionaryRef)frameProperties);
        }
    }

请注意,我们将帧属性字典与每个帧图像一起传递。

在我们准确地添加了指定数量的帧之后,我们最终确定了目标并释放了它:

代码语言:javascript
复制
    if (!CGImageDestinationFinalize(destination)) {
        NSLog(@"failed to finalize image destination");
    }
    CFRelease(destination);

    NSLog(@"url=%@", fileURL);
}

如果在模拟器上运行此命令,则可以从调试控制台复制URL并将其粘贴到浏览器中以查看图像。如果您在设备上运行它,您可以使用Xcode管理器窗口从设备下载应用程序沙箱并查看图像。或者,你可以使用像iExplorer这样的应用程序,让你直接浏览设备的文件系统。(这不需要越狱。)

我在我的运行iOS 6.1的iPhone 5上测试了这一点,但我相信代码应该可以追溯到iOS 4.0。

为了便于复制,我将所有代码都放在了this gist中。

票数 161
EN

Stack Overflow用户

发布于 2017-09-07 20:05:37

对于Swift 3

代码语言:javascript
复制
import Foundation
import UIKit
import ImageIO
import MobileCoreServices

extension UIImage {
    static func animatedGif(from images: [UIImage]) {
        let fileProperties: CFDictionary = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]  as CFDictionary
        let frameProperties: CFDictionary = [kCGImagePropertyGIFDictionary as String: [(kCGImagePropertyGIFDelayTime as String): 1.0]] as CFDictionary

        let documentsDirectoryURL: URL? = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        let fileURL: URL? = documentsDirectoryURL?.appendingPathComponent("animated.gif")

        if let url = fileURL as CFURL? {
            if let destination = CGImageDestinationCreateWithURL(url, kUTTypeGIF, images.count, nil) {
                CGImageDestinationSetProperties(destination, fileProperties)
                for image in images {
                    if let cgImage = image.cgImage {
                        CGImageDestinationAddImage(destination, cgImage, frameProperties)
                    }
                }
                if !CGImageDestinationFinalize(destination) {
                    print("Failed to finalize the image destination")
                }
                print("Url = \(fileURL)")
            }
        }
    }
}

我已经把它从above answer转换过来了。我希望它能帮上忙。

可作为gist使用。

欢迎进行编辑。

票数 2
EN

Stack Overflow用户

发布于 2017-08-01 17:02:19

如果你正在寻找Swift 3的解决方案,你可以看看https://github.com/onmyway133/GifMagic。它有EncoderDecoder来组装和反汇编gif文件。

基本上,您应该将Image IO框架与以下函数一起使用:CGImageDestinationCreateWithURLCGImageDestinationSetPropertiesCGImageDestinationAddImageCGImageDestinationFinalize

同时使用Swift https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html

从带注释的API返回的

核心基础对象在Swift中自动进行内存管理-您不需要自己调用CFRetain、CFRelease或CFAutorelease函数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14915138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档