うるおいらんど

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

CGImageSwiftUIWebView

追記があります。

こんにちは。

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を使ってみてください。

 

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

   

 

参考リンク

Additional Notes追記

WKWebViewにしてgistにあげました。

↑age↑ヾ(`・ω・´)ノ シャキーン

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

Swift4で動作確認済みです〜。

Comments

コメントはありません。

現在コメントフォームは工事中です。