IOSアプリ内に、ユーザーがカスタマイズした一連の画像があり、シンプルなフレームごとのフリップブックスタイルでアニメーション化されています。
私の質問はこれです:ユーザーがアニメーションをアニメーションgifとしてエクスポートできるようにする方法はありますか?理想的には、メール、ソーシャル共有(T/FB)、または(最悪の場合)アニメートされたgifをドキュメントフォルダに保存して、iTunesで取得できるようにしたいと思います。
.pngを写真ライブラリに保存する方法を知っていて、アニメーションをQTファイルとして記録する方法を見つけました( http://www.cimgf.com/2009/02/03/record-your -core-animation-animation / )、しかし、私は単純な古いアニメーションGIFを追い出す方法を見つけていません。 Core Animationまたは他の場所に何か不足していますか?誰もが推奨できるアプローチ、フレームワーク、またはリソースはありますか?質問が一般的すぎる場合は申し訳ありません-出発点を見つけるのに苦労しています。
Image I/Oフレームワーク(iOS SDKの一部)を使用して、アニメーションGIFを作成できます。 GIFタイプ定数を定義するMobileCoreServices
フレームワークも含める必要があります。次のように、これらのフレームワークをターゲットに追加し、アニメーション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を作成できます。最初にフレーム数の定数を定義します。これは後で2回必要になるためです。
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"];
これで、指定されたURLにGIFを書き込むCGImageDestination
を作成できます。
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeGIF, kFrameCount, NULL);
CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties);
fileProperties
の最後の引数としてCGImageDestinationCreateWithURL
を渡すと、notが機能しないことがわかりました。 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);
}
シミュレータでこれを実行する場合、デバッグコンソールからURLをコピーし、ブラウザに貼り付けて画像を表示できます。デバイスで実行する場合、Xcode Organizerウィンドウを使用して、デバイスからアプリサンドボックスをダウンロードし、画像を見ることができます。または、iExplorer
などのアプリを使用して、デバイスのファイルシステムを直接参照できます。 (これはジェイルブレイクを必要としません。)
IOS 6.1を実行しているiPhone 5でこれをテストしましたが、コードはiOS 4.0まで遡って動作するはずです。
簡単にコピーできるように、すべてのコードを this Gist に入れました。
ForSwift 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)")
}
}
}
}
上記の回答 から変換しました。役に立てば幸いです。
Gist として利用可能。
編集を歓迎します。
Swift 3ソリューションを探している場合は、 https://github.com/onmyway133/GifMagic をご覧ください。Encoder
およびDecoder
は、gifファイルをアセンブルおよびディスアセンブルします。
基本的に、これらの関数でImage IO
フレームワークを使用する必要がありますCGImageDestinationCreateWithURL
、CGImageDestinationSetProperties
、CGImageDestinationAddImage
、CGImageDestinationFinalize
注釈付きAPIから返されるCore Foundationオブジェクトは、Swiftで自動的にメモリ管理されます。CFRetain、CFRelease、またはCFAutorelease関数を自分で呼び出す必要はありません。