1
2

【Swift】CIFilterで画像のトーンカーブを調整する

Last updated at Posted at 2023-10-13

はじめに

昨日のノイズに続き、今回はトーンカーブです。

サンプルアプリ

Simulator Screen Recording - iPhone 15 - 2023-10-13 at 21.41.03.gif

実装

import SwiftUI

struct ToneCurveView: View {
    private let image = UIImage(named: "sample")!
    
    @State private var uiImage: UIImage?
    
    @State private var inputPoint0x: CGFloat = 0.0
    @State private var inputPoint0y: CGFloat = 0.0
    @State private var inputPoint1x: CGFloat = 0.0
    @State private var inputPoint1y: CGFloat = 0.0
    @State private var inputPoint2x: CGFloat = 0.0
    @State private var inputPoint2y: CGFloat = 0.0
    @State private var inputPoint3x: CGFloat = 0.0
    @State private var inputPoint3y: CGFloat = 0.0
    @State private var inputPoint4x: CGFloat = 0.0
    @State private var inputPoint4y: CGFloat = 0.0
    
    var body: some View {
        ScrollView {
            VStack {
                if let uiImage {
                    Image(uiImage: uiImage)
                        .resizable()
                        .scaledToFit()
                } else {
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFit()
                }

                Button {
                    applyToneCurve()
                } label: {
                    Text("更新")
                }

                VStack(spacing: 0) {
                    Text("Point0(x): \(inputPoint0x.description)")
                    Slider(value: $inputPoint0x, in: 0.0...1.0)
                }
                
                VStack(spacing: 0) {
                    Text("Point0(y): \(inputPoint0y.description)")
                    Slider(value: $inputPoint0y, in: 0.0...1.0)
                }
                
                VStack(spacing: 0) {
                    Text("Point1(x): \(inputPoint1x.description)")
                    Slider(value: $inputPoint1x, in: 0.0...1.0)
                }
                
                VStack(spacing: 0) {
                    Text("Point1(y): \(inputPoint1y.description)")
                    Slider(value: $inputPoint1y, in: 0.0...1.0)
                }
                
                VStack(spacing: 0) {
                    Text("Point2(x): \(inputPoint2x.description)")
                    Slider(value: $inputPoint2x, in: 0.0...1.0)
                }
                
                VStack(spacing: 0) {
                    Text("Point2(y): \(inputPoint2y.description)")
                    Slider(value: $inputPoint2y, in: 0.0...1.0)
                }
                 
                VStack(spacing: 0) {
                    Text("Point3(x): \(inputPoint3x.description)")
                    Slider(value: $inputPoint3x, in: 0.0...1.0)
                }
                
                VStack(spacing: 0) {
                    Text("Point3(y): \(inputPoint3y.description)")
                    Slider(value: $inputPoint3y, in: 0.0...1.0)
                }
                
                VStack(spacing: 0) {
                    Text("Point4(x): \(inputPoint4x.description)")
                    Slider(value: $inputPoint4x, in: 0.0...1.0)
                }
                
                VStack(spacing: 0) {
                    Text("Point4(y): \(inputPoint4y.description)")
                    Slider(value: $inputPoint4y, in: 0.0...1.0)
                }
            }
            .padding(.horizontal, 20)
        }
    }
    
    func applyToneCurve() {
        let context = CIContext()
        let inputImage = CIImage(image: image)!
        // トーンカーブを調整
        let toneCurveFilter = CIFilter(name: "CIToneCurve", parameters: [
            kCIInputImageKey: inputImage,
            "inputPoint0": CIVector(x: inputPoint0x,  y: inputPoint0y),
            "inputPoint1": CIVector(x: inputPoint1x, y: inputPoint1y),
            "inputPoint2": CIVector(x: inputPoint2x,  y: inputPoint2y),
            "inputPoint3": CIVector(x: inputPoint3x, y: inputPoint3y),
            "inputPoint4": CIVector(x: inputPoint4x,  y: inputPoint4y)
        ])!
        // 出力
        guard let outputImage = toneCurveFilter.outputImage else { return }
        guard let cgImage = context.createCGImage(outputImage, from: inputImage.extent) else { return }
        self.uiImage = UIImage(cgImage: cgImage)
    }
}

おわり

CIToneCurveというフィルターを使って画像のトーンカーブを編集することができます

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2