はじめに
CAlayerや画像に射影変換を適用する時のTipsを残す.
併せてこちらの記事も参照するといいかもしれない.
CALayer編
let layer = CALayer()
self.view.wantsLayer = true //macOSだと必要
self.view.layer?.addSublayer(layer) //親のビューは状況による
layer.frame = self.view.bounds
//layerに何かしらコンテンツを入れる
let rect = CGRect(x: 0, y: 0, width: W, height: H) // コンテンツの大きさ
let filter = CIFilter(name: "CIPerspectiveTransformWithExtent")!
filter.setValue(CIVector(cgRect: rect, forKey: "inputExtent")
filter.setValue(CIVector(x: X1, y: Y1), forKey: "inputTopLeft") //射影変換後のコンテンツ左上頂点の座標
filter.setValue(CIVector(x: X2, y: Y2), forKey: "inputTopRight") //射影変換後のコンテンツ右上頂点の座標
filter.setValue(CIVector(x: X3, y: Y3), forKey: "inputBottomRight") //射影変換後のコンテンツ右下頂点の座標
filter.setValue(CIVector(x: X4, y: Y4), forKey: "inputBottomLeft") //射影変換後のコンテンツ左下頂点の座標
layer.filters = [filter]
画像編
var nsImage = NSImage(name: "hoge")!
let imageData = nsImage.tiffRepresentation!
var ciImage = CIImage(data: imageData)!
let filter = CIFilter(name: "CIPerspectiveTransformWithExtent")!
filter.setValue(ciImage, forKey: "inputImage")
filter.setValue(CIVector(cgRect: ciImage.extent), forKey: "inputExtent")
filter.setValue(CIVector(x: X1, y: Y1), forKey: "inputTopLeft") //射影変換後のコンテンツ左上頂点の座標
filter.setValue(CIVector(x: X2, y: Y2), forKey: "inputTopRight") //射影変換後のコンテンツ右上頂点の座標
filter.setValue(CIVector(x: X3, y: Y3), forKey: "inputBottomRight") //射影変換後のコンテンツ右下頂点の座標
filter.setValue(CIVector(x: X4, y: Y4), forKey: "inputBottomLeft") //射影変換後のコンテンツ左下頂点の座標
ciImage = filter.outputImage!
let rep = NSCIImageRep(ciImage: ciImage)
nsImage = NSImage(size: rep.size)
nsImage.addRepresentation(rep)
補足
CIPerspectiveTransformWithExtentが射影変換用のフィルタなのかは不明ですが,射影変換を手軽に達成できるのでいいですね.しかし,このCIPerspectiveTransformWithExtentは各頂点のパラメータ次第で結果がちゃんと出力されないので要注意です.色々試した感じだと,元のコンテンツより大き過ぎたり,どこかの辺が水平or垂直だとダメ(?)っぽい.引き伸ばしの限界があるのか,ゼロで割っちゃうのかよくわかりません.出力できる時はできる.