はじめに
昨日のノイズに続き、今回はトーンカーブです。
サンプルアプリ
実装
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
というフィルターを使って画像のトーンカーブを編集することができます