通过iOS创build和导出animationgif?
我在iOS应用程序中有一系列用户自定义的图像,这些图像是以简单的,逐帧的翻页样式进行animation的。
我的问题是这样的:有没有办法让用户导出他们的animation作为animationgif? 理想情况下,我想让他们通过电子邮件,社交分享(T / FB)或(最糟糕的情况下)保存一个animation的gif到他们的文档文件夹通过iTunes检索。
我知道如何将.png保存到照片库中,并且find了将animation录制为QT文件的方法( http://www.cimgf.com/2009/02/03/record-your-core-animation – animation/ ),但我还没有find一个方法,只是踢出一个普通的老animationgif。 我在核心animation或其他地方丢失了什么? 有没有人可以推荐的方法,框架或资源? 对不起,如果这个问题太笼统 – 努力寻找出发点。 任何帮助赞赏。
您可以使用Image I / O框架(它是iOS SDK的一部分)创build一个animationGIF。 您还需要包含定义GIFtypes常量的MobileCoreServices
框架。 您需要将这些框架添加到您的目标中,并将其头文件导入到您要创buildanimationGIF的文件中,如下所示:
#import <ImageIO/ImageIO.h> #import <MobileCoreServices/MobileCoreServices.h>
这是最容易解释的例子。 我将向您展示我用于在iPhone 5上制作此GIF的代码:
首先,这是一个帮助函数,它需要一个大小和一个angular度,并以这个angular度返回红色磁盘的UIImage
:
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; }
现在我们可以创buildGIF了。 首先我们将定义一个帧数的常量,因为我们需要它两次:
static void makeAnimatedGif(void) { static NSUInteger const kFrameCount = 16;
我们需要一个属性字典来指定animation应该重复的次数:
NSDictionary *fileProperties = @{ (__bridge id)kCGImagePropertyGIFDictionary: @{ (__bridge id)kCGImagePropertyGIFLoopCount: @0, // 0 means loop forever } };
我们将需要另一个属性字典,我们将附加到每个框架,指定该框架应该显示多长时间:
NSDictionary *frameProperties = @{ (__bridge id)kCGImagePropertyGIFDictionary: @{ (__bridge id)kCGImagePropertyGIFDelayTime: @0.02f, // a float (not double!) in seconds, rounded to centiseconds in the GIF data } };
我们还将在我们的文档目录中为GIF创build一个URL:
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil]; NSURL *fileURL = [documentsDirectoryURL URLByAppendingPathComponent:@"animated.gif"];
现在我们可以创build一个CGImageDestination
,它将GIF写入指定的URL:
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeGIF, kFrameCount, NULL); CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties);
我发现传递fileProperties
作为fileProperties
的最后一个参数不起作用。 你必须使用CGImageDestinationSetProperties
。
现在我们可以创build和编写我们的框架:
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); } }
请注意,我们将帧属性字典与每个帧图像一起传递。
在我们添加了完全指定数量的帧之后,我们最终确定目标并释放它:
if (!CGImageDestinationFinalize(destination)) { NSLog(@"failed to finalize image destination"); } CFRelease(destination); NSLog(@"url=%@", fileURL); }
如果你在模拟器上运行它,你可以从debugging控制台复制URL并粘贴到你的浏览器中来查看图像。 如果您在设备上运行它,则可以使用Xcode Organizer窗口从设备下载应用程序沙箱并查看图像。 或者你可以使用像iExplorer
这样的应用程序,让你直接浏览你的设备的文件系统。 (这不需要越狱。)
我在运行iOS 6.1的iPhone 5上进行了testing,但是我相信代码应该可以在iOS 4.0的基础上工作。
我已经把所有的代码放在这个要点中,以便于复制。
如果你正在寻找Swift 3的解决scheme,你可以看一下https://github.com/onmyway133/GifMagic 。 它有Encoder
和Decoder
,它组装和反汇编gif文件。
基本上,你应该使用Image IO
框架与这些函数CGImageDestinationCreateWithURL
, CGImageDestinationSetProperties
, CGImageDestinationAddImage
, CGImageDestinationFinalize
从注释的API返回的Core Foundation对象在Swift中自动进行内存pipe理 – 您不需要自己调用CFRetain,CFRelease或CFAutorelease函数。
对于Swift 3
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)") } } } }
我已经从上面的答案转换它。 我希望它有帮助。
作为要点提供 。
编辑欢迎。