【Swift 3】アニメーションGIFを作成してWebViewに表示しよう【CGImageDestination】

こんにちは。

CGImageDestinationを用いてGIF作成をしたので、それを紹介していこうと思います。

今回はいつもよりさらにざっくりとした説明で失礼します。

[iOS][swift] アニメーションGIFを作る」を参考にさせていただいてますので、詳しくはこちらをぜひ。

 

下準備

importで下記を追加しておきます。

import AVFoundation
import ImageIO
import MobileCoreServices

 

GIF作成をしたい画像を入れておく配列を用意します。

private var imageArray:Array<CGImage>!

 

画像はCGImageを用います。

 

UIImageをCGImageに変換する

簡単に.cgImageでUIImageから変換することができます

var image = UIImage(named:"hogehoge.png")
imageArray.append(image.cgImage)

 

resize等を同時にする場合は

    private func resizeImage(image:UIImage,contentSize:CGSize) -> CGImage{
        // リサイズ処理
        let origWidth  = Int(image.size.width)
        let origHeight = Int(image.size.height)
        var resizeWidth:Int = 0, resizeHeight:Int = 0
        if (origWidth < origHeight) {
            resizeWidth = Int(contentSize.width)
            resizeHeight = origHeight * resizeWidth / origWidth
        } else {
            resizeHeight = Int(contentSize.height)
            resizeWidth = origWidth * resizeHeight / origHeight
        }
        
        let resizeSize = CGSize(width:CGFloat(resizeWidth), height:CGFloat(resizeHeight))
        UIGraphicsBeginImageContext(resizeSize)
        
        image.draw(in: CGRect(x:0,y: 0,width: CGFloat(resizeWidth), height:CGFloat(resizeHeight)))
        
        let resizeImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        // 切り抜き処理
        
        let cropRect  = CGRect(
            x:CGFloat((resizeWidth - Int(contentSize.width)) / 2),
            y:CGFloat((resizeHeight - Int(contentSize.height)) / 2),
            width:contentSize.width, height:contentSize.height)
        let cropRef   = (resizeImage?.cgImage)!.cropping(to: cropRect)
        
        return cropRef!
    }

 

もしかすると.cgImageで単純に変換した場合は画像の向きが変わってしまうかもしれません。。。

 

GIFを作成しよう

フレームレートを変更しやすいように定数で用意しておきます

//フレームレート
private let frameRate = CMTimeMake(1,5)

 

そいではGIFを作成する関数を作成していきます。

    private func makeGifImage(){
        //ループカウント 0で無限ループ
        let fileProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]
        //フレームレート
        let frameProperties = [kCGImagePropertyGIFDictionary as String:[kCGImagePropertyGIFDelayTime as String :CMTimeGetSeconds(frameRate)]]
        let url = NSURL(fileURLWithPath:NSTemporaryDirectory()).appendingPathComponent("\(NSUUID().uuidString).gif")
        guard let destination = CGImageDestinationCreateWithURL(url as! CFURL,kUTTypeGIF,imageArray.count,nil)else{
            print("CGImageDestinationの作成に失敗")
            return
        }
        CGImageDestinationSetProperties(destination,fileProperties as CFDictionary?)
        
        //画像を追加
        for image in imageArray{
            CGImageDestinationAddImage(destination,image,frameProperties as CFDictionary?)
        }
        if CGImageDestinationFinalize(destination){
            //GIF生成後の処理をする
            print("成功")
        }else{
            print("GIF生成に失敗")
        }
        
    }

 

urlにGIFが書き出されます。

 

WebViewに作成したGIFを表示しよう

先ほど書き出されたurlからGIFを表示させます。

let animationGifView = UIWebView(frame: CGRect(x:0,y:0,width:300,height:400))
animationGifView.center = CGPoint(x:self.view.frame.width / 2.0,y:self.view.frame.height * 2 / 7.0)

//urlをNSDataに変換
let gifData =  NSData(contentsOf: url!)
//gifをloadする
animationGifView.load(gifData as! Data, mimeType: "image/gif", textEncodingName: "utf-8", baseURL: url!)
self.view.addSubview(animationGifView)

 

 

本当にざっくりコードを紹介しただけですが以上にしたいと思います。

ちなみにUIImageViewにgifをのせても動いてくれません。

ライブラリを使うとできるようになるそうですが、入れたくない人はWebViewを使ってみてください。

 

また付け足しやら書き直しやらするかもしれません。

 
 

 

2018/04/14追記 WKWebViewにしてgistにあげました。
↑age↑ヾ(`・ω・´)ノ シャキーン


WKWebViewの方がいいってなんかどこかで聞いたことあります。

Swift4で動作確認済みです〜。
Swift , ,
コメントは認証制です。詳しくは下記の注意をお読みください。お気軽にコメントお願いします!

Write a Comment

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

Related Memo...

記事を書くほどでもないけれどメモっておきたいこと

テスト投稿。

例えばiphone7 の画面サイズ

750 × 1334
半分375 × 667

iOS

UITableView.RowAnimation の .none はアニメーションするよ

UITableView.RowAnimation の .none はアニメーションがnoneなわけじゃなく、デフォルトの設定を使うよという意味らしい。

The inserted or deleted rows use the default animations.

なのでアニメーションしちゃう。今更の気づき。

 

iOS

UINavigationController + UIScrollView の組み合わせで使っている時に謎の余白ができる時

UINavigationController + UIScrollView の組み合わせで使っていて、UIScrollView 上に AutoLayout で上下左右0で View を設置しているのに、30px程度上にずれてしまうとき。

`navigationController.navigationBar.isTranslucent = false` にすると直るかもしれない。

ScrollView上のコンテンツとNavigationBarの重なっているところが透過していたら多分これで直せるはず。

通常のターゲットではちゃんと動いているのに、iOSSnapshotTestCase を用いたテストでだけこの対応が必要なのよくわからないけれど。。。

iOS
more