MetalPetal and SwiftUI: A Powerful Combination for High-Performance Image Manipulation

Jerry PM
4 min readFeb 27, 2023

Pod Image Filter in Swift

Have you ever wanted to add advanced image processing filters to your SwiftUI app? With MetalPetal, you can create stunning visual effects that will impress your users. In this tutorial, we will learn how to use MetalPetal to apply filters to images in SwiftUI.

Metal Petal is a pod library, so we need to add the MetalPetal pod to our project https://github.com/MetalPetal/MetalPetal

Creating a basic image filter

Let’s start by creating a basic filter that will invert the colors of an image. First, we need to create a new view that will display our image and the filter button. Add the following code to your project:

struct ContentViewOne: View {

@State var inputImage = UIImage(named: "_image_")!

var body: some View {
VStack {
Image(uiImage: inputImage)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 300, height: 300)

Button("Apply Filter") {
inputImage = applyFilter(inputImage)
}
}
}

func applyFilter(_ image: UIImage) -> UIImage {
let context = try! MTIContext(device: MTLCreateSystemDefaultDevice()!)

// Load the input image into a MetalPetal image object
let input = MTIImage(__cgImage: image.cgImage!, options: [.SRGB: false], isOpaque: true)

// Create a MetalPetal filter
let filter = MTIColorInvertFilter()
filter.inputImage = input

// Apply the filter
let output = filter.outputImage!

// Render the output image to a CGImage
let cgImage = try! context.makeCGImage(from: output)

// Convert the CGImage to a UIImage
let outputImage = UIImage(cgImage: cgImage)

return outputImage
}
}

This view contains an inputImage state variable, which represents the image we want to filter. The applyFilter function takes an image as input, applies the MTIColorInvertFilter filter to it, and returns the filtered image.

When the user taps the “Apply Filter” button, the inputImage state variable is updated with the filtered image.

Creating a more advanced image filter

Now, let’s create a more image filter that will allow the user to choose between different filters and adjust the strength of the filter. Add the following code to your project:

struct ContentViewTwo: View {

@State var inputImage = UIImage(named: "_image_")!
@State var currentFilter: MTIUnaryFilter = MTIColorInvertFilter()
@State var filterStrength: Double = 1.0

var body: some View {
VStack {
Image(uiImage: inputImage)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 300, height: 300)

Slider(value: $filterStrength, in: 0.0...1.0, step: 0.01, onEditingChanged: { _ in
applyFilter()
})

HStack {
Button("Invert") {
currentFilter = MTIColorInvertFilter()
applyFilter()
}
Button("Grayscale") {
currentFilter = MTIDotScreenFilter()
applyFilter()
}
Button("Sepia") {
currentFilter = MTICLAHEFilter()
applyFilter()
}
}
}
}

func applyFilter() {
let context = try! MTIContext(device: MTLCreateSystemDefaultDevice()!)

// Load the input image into a MetalPetal image object
let input = MTIImage(__cgImage: inputImage.cgImage!, options: [.SRGB: false], isOpaque: true)

// Create a MetalPetal filter
let filter = currentFilter
filter.inputImage = input

// Apply the filter
let output = filter.outputImage!

// Render the output image to a CGImage
let cgImage = try! context.makeCGImage(from: output)

// Convert the CGImage to a UIImage
let outputImage = UIImage(cgImage: cgImage)

inputImage = outputImage
}
}

Conclusion

To summarize, in this article we learned how to use the MetalPetal framework in SwiftUI to apply image filters to a UIImage. We started by importing the MetalPetal pod and creating two different views for applying filters.

In the first view, we applied a single filter called MTICLAHEFilter() which enhances the contrast of the image. In the second view, we added the ability to choose between three different filters (invert, grayscale, and sepia), and a slider to control the strength of the filter.

In both views, we used the MTIContext class to create a MetalKit context that is used to apply the filter to the image. We also used the MTIImage class to create a MetalPetal image object from the UIImage and the MTIUnaryFilter class to create the filter that we want to apply.

By the end of this tutorial, you should have a good understanding of how to use MetalPetal in SwiftUI to apply filters to images. With this knowledge, you can explore the MetalPetal framework further and create your own custom filters to apply to images.

If you want to more know about the filter you can see this article
https://www.alfianlosari.com/posts/building-cross-platform-swiftui-ios-macos-app/

My Swift UI Wallpaper app Filter and you can edit your image too from your photo in this template has been sold on the CodeCanyon website. Thank you for reading my article.
https://codecanyon.net/item/wallpaper-wizard/43965325 😄

--

--