我有在一个简单的,一帧一帧翻转书样式进行动画iOS应用中的一系列用户自定义图像。
我的问题是:有没有办法可以让用户将他们的动画导出为GIF动画? 理想情况下,我想,让他们到电子邮件,社交共享(T / FB)或(最坏情况..)通过iTunes GIF动画保存到自己的文件夹进行检索。
我知道如何.png文件保存到照片库,我找到了一种方法来记录动画为QT文件( http://www.cimgf.com/2009/02/03/record-your-core-animation -动画/ ),但我还没有找到一种方法来只踢了一个普通的老gif动画。 我缺少的核心动画东西,或别的地方? 是否有任何方法,框架或资源,任何人都可以推荐? 很抱歉,如果问题是过于笼统 - 努力寻找一个起点。
您可以使用图像I / O框架(这是iOS的SDK的一部分)创建动画GIF。 您还希望包括MobileCoreServices
框架,它定义了GIF类型常量。 您需要这些框架要在其中创建动画GIF,像这样的文件添加到您的目标,并导入自己的头:
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
这是最简单的例子来解释。 我会告诉你我用来做在我的iPhone 5这个GIF的代码:
首先,这里是一个辅助函数,它的尺寸和角度,并返回一个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;
}
现在,我们可以创建GIF。 首先,我们将定义一个常数的帧数,因为我们需要它后来两次:
static void makeAnimatedGif(void) {
static NSUInteger const kFrameCount = 16;
我们需要一个属性字典,以指定的时间动画应该重复次数:
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的URL:
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
NSURL *fileURL = [documentsDirectoryURL URLByAppendingPathComponent:@"animated.gif"];
现在,我们可以创建一个CGImageDestination
写入一个GIF到指定的网址:
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeGIF, kFrameCount, NULL);
CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties);
我发现,通过fileProperties
作为最后一个参数CGImageDestinationCreateWithURL
不起作用 。 你必须使用CGImageDestinationSetProperties
。
现在,我们可以创建并写入我们的框架:
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);
}
如果您在模拟器中运行这个,你可以从调试控制台复制网址并将其粘贴到浏览器中看到的图像。 如果您在设备上运行它,你可以使用Xcode的管理窗口,从设备下载的应用程序沙箱,并期待在图像。 或者你可以像使用一个应用程序iExplorer
,可以让你直接浏览设备的文件系统。 (这不需要越狱)。
我测试了这个在我的iPhone 5运行iOS 6.1,但我相信代码应工作早的iOS 4.0。
我已经把所有的代码都在这个要点 ,便于复制。
如果您正在寻找斯威夫特3解决方案,你可以看看https://github.com/onmyway133/GifMagic 。 它具有Encoder
和Decoder
,其组装和拆卸gif文件。
基本上,你应该使用Image IO
框架,这些功能CGImageDestinationCreateWithURL
, CGImageDestinationSetProperties
, CGImageDestinationAddImage
, CGImageDestinationFinalize
还与斯威夫特https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html
核心基础,从注释的API返回的对象是自动存储在管理斯威夫特,你不需要调用CFRetain,CFRelease,或CFAutorelease功能自己。
对于斯威夫特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)")
}
}
}
}
我从转换它上面的回答 。 我希望它能帮助。
可以作为一个依据 。
编辑欢迎。