Bartson
Bartson

Reputation: 93

What is the most optimized way of changing alpha of blended images in CoreImage in Swift

I want to blend two images with darkenBlendMode and using Slider to manipulate alpha of first and second image. Unfortunately my method is laggy on iPhone 6S. I know that problem is in calling "loadImage" function in every Slider touch but I have no idea how to make it less aggravating. Have you any idea how to repair it?

extension UIImage {

    func alpha(_ value:CGFloat) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        draw(at: CGPoint.zero, blendMode: .normal, alpha: value)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

struct ContentView: View {

    @State private var image: Image?
    @State private var opacity: CGFloat = 0
    let context = CIContext()

    var body: some View {

        return VStack(alignment: .center) {
            image?
                .resizable()
                .padding(14.0)
                .scaledToFit()

            Slider(value: Binding(
                get: {
                    self.opacity
                },
                set: {(newValue) in
                      self.opacity = newValue
                      self.loadImage()
                }
            ), in: -0.5...0.5)
        }
        .onAppear(perform: loadImage)

    }

    func loadImage(){
        let uiInputImage = UIImage(named: "photo1")!.alpha(0.5 + opacity)

        let uiBackgroundInputImage = UIImage(named: "photo2")!.alpha(0.5 - opacity)

        let ciInputImage = CIImage(image: uiInputImage)
        let ciBackgroundInputImage = CIImage(image: uiBackgroundInputImage)


        let currentFilter = CIFilter.darkenBlendMode()

        currentFilter.inputImage = ciInputImage

        currentFilter.backgroundImage = ciBackgroundInputImage

        guard let blendedImage = currentFilter.outputImage else {return}

        if let cgBlendedImage = context.createCGImage(blendedImage, from: blendedImage.extent){
            let uiblendedImage = UIImage(cgImage: cgBlendedImage)



            image = Image(uiImage: uiblendedImage)
        }
    }
}

Upvotes: 0

Views: 581

Answers (1)

Frank Rupprecht
Frank Rupprecht

Reputation: 10383

You could use the CIColorMatrix filter to change the alpha of the images without loading the bitmap data again:

let colorMatrixFilter = CIFilter.colorMatrix()
colorMatrixFilter.inputImage = ciInputImage // no need to load that every time
colorMatrixFilter.inputAVector = CIVector(x: 0, y: 0, z: 0, w: 0.5 + opacity)
let semiTransparentImage = colorMatrixFilter.outputImage

// perform blending

Upvotes: 1

Related Questions