Metalの恩恵は受けつつCore Imageで「手軽に」画像処理
Metalでシェーダを書けば自由自在にGPU-acceleratedな画像処理を行えるわけですが、Core Imageの200種類近くある豊富なフィルタを利用しつつ、Metalの恩恵も受ける、という選択肢もあります。
既存のCore Imageのフィルタ(CIFilter
)を利用することで、以下のようなメリットがあります。
- 自分でイチから書かなくて良い
- もちろんこっちの方が楽
- 画像処理のプロが書いたであろうものを利用した方が大抵の場合良い結果が得られる
- 種類がたくさんある
- 簡単に使える
- 数行書くだけ
- どのフィルタも基本的な使い方は同じ
- CIFilterはMetalとシームレスに統合されるようにつくられている(後述)
- ビルトインフィルタの一部はMetal Performance Shadersを用いて実装されている
(Core ImageのCIPixellate
フィルタをパラメータを変えつつ60fpsでMTKViewに描画。実装方法は後述)
MetalとCIFilterの連携について
「Metalとシームレスに統合」と上で書きましたが、それだけ言われてもなんのこっちゃ、という感じだと思います。
このテーマについてはWWDC2015の「What's New in Core Image」というセッションで詳しく解説されています。
上の図は、Core Imageのフィルタはコマンドバッファのどこにでも挿入できるよ、ということを言っています。
「MetalでリサイズしたテクスチャをCore Imageで画像処理してMetalで描画」みたいなことをしたいとして、そのためにCPUとGPUを行ったり来たりみたいなムダなことはしないので安心して併用してください、ということかと思います。
実装
MTLTexture
にCore Imageで画像処理 → MTKView
に描画する、という実装例を示します。
MetalでGPUベースレンダリングするためのコンテキスト(CIContext
)を生成しておきます。
private let device: MTLDevice
private let context: CIContext
device = MTLCreateSystemDefaultDevice()!
context = CIContext(mtlDevice: device)
MTLTexture
から入力用のCIImage
を生成します。
let inputImage = CIImage(mtlTexture: texture, options: nil)
何らかのCore Imageフィルタ(CIFilter
)を生成し、入力画像とパラメータをセットします。
let filter = CIFilter(name: "CIPixellate")!
filter.setValue(inputImage, forKey: kCIInputImageKey)
filter.setValue(50.0, forKey: kCIInputScaleKey)
MTKView
のdrawInView:
メソッド内で、CIFilterの出力画像(outputImage
)を描画します。
guard let outputImage = filter.outputImage else {return}
let commandBuffer = commandQueue.makeCommandBuffer()
let colorSpace = CGColorSpaceCreateDeviceRGB()
context.render(outputImage, to: drawable.texture, commandBuffer: commandBuffer, bounds: outputImage.extent, colorSpace: colorSpace)
commandBuffer.present(drawable)
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
CIImage
をCAMetalDrawable
のtexture
(MTLTexture
)に書き込むために、CIContext
のrender(_:to:commandBuffer:bounds:colorSpace:)
を使用するのがポイントです。1
注意点
MTLTesture
からCIImage
を生成する際、画像が上下反転してしまいます。
というわけで実際にはy方向にフリップさせて使ってます。
let inputImage = CIImage(mtlTexture: texture, options: nil)?.applying(CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: CGFloat(texture.height)))
-
MTKViewを用いて2Dテクスチャを表示する基本についてはこちらに書いてあります:MetalでUIImageViewライクに画像を表示する - 最小実装編 - Qiita ↩
Author And Source
この問題について(Metalの恩恵は受けつつCore Imageで「手軽に」画像処理), 我々は、より多くの情報をここで見つけました https://qiita.com/shu223/items/4c0f8073477f787e1627著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .