環境
- Xcode:13.3.1
- Swift:5.6
点描のソースコード例
点描するには、CIFilterの「CIPointillize」を使う
class SampleViewController: UIViewController {
@IBOutlet weak var testDisplayImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// AssetsにDummyって名前の適当な画像を置く
let dummyImage = UIImage(named: "Dummy")!
let pointillizeImage = addPointillizeEffect(for: dummyImage)
self.testDisplayImage.image = pointillizeImage
}
func addPointillizeEffect(for image: UIImage) -> UIImage {
// どこらへんに描画するか(今回は中央に描画されるように設定)
let center: CIVector = CIVector(x: self.testDisplayImage.bounds.midX, y: self.testDisplayImage.bounds.midY)
// 丸の大きさ
let radius = 40.0
if let inputImage = image.toCIImage() {
let filter: CIFilter = CIFilter(name: "CIPointillize",
parameters: [kCIInputImageKey: inputImage,
kCIInputRadiusKey : radius,
kCIInputCenterKey : center])!
// CIPointillizeになった画像が出力される
if let outputImage = filter.outputImage {
// CIContextを通してCGImageに変換
let context = CIContext(options: nil)
if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
let filteredImage = UIImage(cgImage: cgImage)
return filteredImage
}
}
}
// 変換できなかったら元の画像を返す
return image
}
}
extension UIImage {
func toCIImage() -> CIImage? {
if let ciImage = self.ciImage {
return ciImage
}
if let cgImage = self.cgImage {
return CIImage(cgImage: cgImage)
}
return nil
}
}
※ UIImageViewは、SafeAreaいっぱいになるような制約をつけてる
実行結果
- 左:結果
- 右:元々の画像
補足
- パラメータの設定
加工したい画像は、kCIInputImageKey
で指定する。必須。
どこらへんに描画するかは、kCIInputCenterKey
で指定する。
なにも設定しなければデフォルト値が設定される。
丸の大きさは、kCIInputRadiusKey
で指定する。
なにも設定しなければデフォルト値が設定される。画像サイズに対しての丸の大きさ。
CIFilter.setValue(Any?, forKey: String) でもパラメータを設定できる
- リリース処理
古い記事だと、ContextとCGImageのリリース処理をしているが、Swift5でリリース処理を書くと、
'CGImageRelease' is unavailable: Core Foundation objects are automatically memory managed
というメッセージがでる。もうリリース処理はいらないのかも。
参考になった記事
- Appleのリファレンス
- UIImageのextensionについて
- Assetsに置いてある画像からCIImageを取得しようとすると、CIImageがnilになってしまった。これを回避する方法を以下の記事を参考にした。
- 実行結果からわかるとおり、もともとの画像より小さくなって出力されてしまう。
- どうにかしたい時に参考になる。