Skip to content

Commit

Permalink
Update Filter Demo (#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
shima11 authored Jul 28, 2024
1 parent ab3839f commit c512d1e
Showing 1 changed file with 88 additions and 18 deletions.
106 changes: 88 additions & 18 deletions Dev/Sources/SwiftUIDemo/DemoFilterView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,71 @@ struct DemoFilterView: View {
}
}

struct MotionBlurFilter: Filtering {

let kernel = CIKernel(source:
"""
kernel vec4 motionBlur(sampler image, vec2 size, float sampleCount, float blur) {
int sampleCountInt = int(floor(sampleCount));
vec4 accumulator = vec4(0.0);
vec2 dc = destCoord();
float normalisedValue = length(((dc / size) - 0.5) * 2.0);
float strength = clamp((normalisedValue), 0.0, 1.0);
vec2 vector = normalize((dc - (size / 2.0)) / size);
vec2 velocity = vector * strength * blur;
vec2 redOffset = -vector * strength * (blur * 1.0);
vec2 greenOffset = -vector * strength * (blur * 1.5);
vec2 blueOffset = -vector * strength * (blur * 2.0);
for (int i=0; i < sampleCountInt; i++) {
accumulator.r += sample(image, samplerTransform(image, dc + redOffset)).r;
redOffset -= velocity / sampleCount;
accumulator.g += sample(image, samplerTransform(image, dc + greenOffset)).g;
greenOffset -= velocity / sampleCount;
accumulator.b += sample(image, samplerTransform(image, dc + blueOffset)).b;
blueOffset -= velocity / sampleCount;
}
return vec4(vec3(accumulator / float(sampleCountInt)), 1.0);
}
""")!

func apply(to image: CIImage, sourceImage: CIImage) -> CIImage {

let width = image.extent.width + image.extent.minX*2
let height = image.extent.height + image.extent.minY*2

let base = Double(sqrt(pow(width, 2) + pow(height, 2)))
let radius = base / 40

let args = [
image,
CIVector(
x: width,
y: height
),
20,
radius,
] as [Any]

return kernel.apply(
extent: image.extent,
roiCallback: { _, rect in
rect
},
arguments: args
)!
}
}

let invertFilter: InvertFilter = .init()
let grayscaleFilter: GrayscaleFilter = .init()
let motionBlurFilter: MotionBlurFilter = .init()

@StateObject var editingStack: EditingStack
@State var invertToggle: Bool = false
@State var grascaleToggle: Bool = false
@State var grayscaleToggle: Bool = false
@State var motionBlurToggle: Bool = false

@State var resultImage: ResultImage?

init(
editingStack: @escaping () -> EditingStack
Expand All @@ -52,33 +111,44 @@ struct DemoFilterView: View {

ViewHost(instantiated: ImagePreviewView(editingStack: editingStack))

SwiftUICropView(editingStack: editingStack, contentInset: .zero)
.clipped()

VStack {
Toggle("Invert", isOn: $invertToggle)
.onChange(of: invertToggle) { newValue in
editingStack.set(filters: {
$0.additionalFilters = [
grascaleToggle ? grayscaleFilter.asAny() : nil,
invertToggle ? invertFilter.asAny() : nil,
].compactMap({ $0 })
})
}
Toggle("Grayscale", isOn: $grayscaleToggle)
Toggle("MotionBlur", isOn: $motionBlurToggle)
}
.onChange(of: [invertToggle, grayscaleToggle, motionBlurToggle], perform: { _ in
editingStack.set(filters: {
$0.additionalFilters = [
grayscaleToggle ? grayscaleFilter.asAny() : nil,
invertToggle ? invertFilter.asAny() : nil,
motionBlurToggle ? motionBlurFilter.asAny() : nil,
].compactMap({ $0 })
})
})
.padding()

Toggle("Grayscale", isOn: $grascaleToggle)
.onChange(of: grascaleToggle) { newValue in
editingStack.set(filters: {
$0.additionalFilters = [
grascaleToggle ? grayscaleFilter.asAny() : nil,
invertToggle ? invertFilter.asAny() : nil,
].compactMap({ $0 })
})
Button("Done") {
try! editingStack.makeRenderer().render { result in
switch result {
case let .success(rendered):
self.resultImage = .init(cgImage: rendered.cgImage)
case let .failure(error):
print(error)
}
}
}
.padding()

}
.onAppear {
editingStack.start()
}
.sheet(item: $resultImage) {
RenderedResultView(result: $0)
}

}

}
Expand Down

0 comments on commit c512d1e

Please sign in to comment.