SwiftyLifestyle
SwiftyLifestyle

Reputation: 496

Render a MTIImage

Please don't judge me I'm just learning Swift.

Recently I installed MetalPetal framework and I followed the instructions:

https://github.com/MetalPetal/MetalPetal#example-code

But I get error because of MTIContext. Maybe I have to declare something more of MetalPetal?

My Code:

My Code

import UIKit
import MetalPetal
import CoreGraphics

class ViewController: UIViewController {

    @IBOutlet weak var image1: UIImageView!
    override func viewDidLoad() {

        super.viewDidLoad()




        weak var image: UIImage?
        image = image1.image
        var ciImage = CIImage(image: image!)
        var cgImage1 = convertCIImageToCGImage(inputImage: ciImage!)
        let imageFromCGImage = MTIImage(cgImage: cgImage1!)


        let inputImage = imageFromCGImage
        let filter = MTISaturationFilter()
        filter.saturation = 1
        filter.inputImage = inputImage

        let outputImage = filter.outputImage


        let context = MTIContext()

        do {
            try context.render(outputImage, to: pixelBuffer)

            var image3: CIImage? = try context.makeCIImage(from: outputImage!)

            //context.makeCIImage(from: image)

            //context.makeCGImage(from: image)
        } catch {
            print(error)
        }





        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    func convertCIImageToCGImage(inputImage: CIImage) -> CGImage? {
        let context = CIContext(options: nil)
        if let cgImage = context.createCGImage(inputImage, from: inputImage.extent) {
            return cgImage
        }
        return nil
    }

}

@YuAo

Upvotes: 3

Views: 2301

Answers (1)

Stephan Schlecht
Stephan Schlecht

Reputation: 27126

Input Image

An UIImage is based on either underlying Quartz image (can be retrieved with cgImage) or an underlying Core Image (can be retrieved from UIImage with ciImage).

MTIImage offers constructors for both types.

MTIContext

A MTIContext must be initialized with a device that can be retrieved by calling MTLCreateSystemDefaultDevice().

Rendering

A rendering to a pixel buffer is not needed. We can get the result by calling makeCGImage.

Test

I've taken your source code above and slightly adapted it to the aforementioned points.

I also added a second UIImageView to see the result of the filtering. I also changed the saturation to 0 to see if the filter works

If GPU or shaders are involved it makes sense to test on a real device and not on the simulator.

The result looks like this:

saturation test

In the upper area you see the original jpg, in the lower area the filter is applied.

Swift

The simplified Swift code that produces this result looks like this:

override func viewDidLoad() {

    super.viewDidLoad()

    guard let image = UIImage(named: "regensburg.jpg") else { return }
    guard let cgImage = image.cgImage else { return }

    imageView1.image = image

    let filter = MTISaturationFilter()
    filter.saturation = 0
    filter.inputImage = MTIImage(cgImage: cgImage)

    if let device = MTLCreateSystemDefaultDevice(),
        let outputImage = filter.outputImage {
        do {
            let context = try MTIContext(device: device)
            let filteredImage = try context.makeCGImage(from: outputImage)
            imageView2.image = UIImage(cgImage: filteredImage)
        } catch {
            print(error)
        }
    }
}

Upvotes: 6

Related Questions