SwiftUI: How to blend between UIImages without pulsating/pumping effect?

I want to smootlhy blend two or more UIImages without pulsating/pumping effect but cannot achieve this.

I have created a simple example code to visualize my issue. Two UIImages with exactly the same content ("gear") are initialized. The images are then manipulated via "func resizeImage()" with:

UIGraphicsBeginImageContext() defer { UIGraphicsEndImageContext() } draw(in: CGRect())

This custom draw: (in:) is important for me as in my app there is a lot of custom drawing logic.

In the body I use a PhaseAnimator to animate through the different stages of my custom animation.

The result is always a pulsating/pumping effect which is unwanted. If the shape of two blended UIImages is exactly the same, there should not be any noticeable difference, especially no intensity change.

How to get a smooth blend without pulsating/pumping effect?

Any help appreciated.

import SwiftUI

struct ContentView: View {
    @State var widgetSize: CGFloat = 128
    let img1 = UIImage(systemName: "gear")!
    let img2 = UIImage(systemName: "gear")!
    
    func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage {
        let scale = newWidth / image.size.width
        let newHeight = image.size.height * scale
        UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
        image.draw(in: CGRectMake(0, 0, newWidth, newHeight))
        guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else { return UIImage(systemName: "questionmark")! }
        UIGraphicsEndImageContext()
        return newImage
    }
    
    var body: some View {
        PhaseAnimator([1, 2]) { phase in

            // This is just for demonstration purposes
            // I have two or more UIImages that I want to smootlhy blend
            // The UIImages are created with image.draw
            // the result is a pulsating animation but I would expect
            // a smooth blend over with no noticable change when there are two
            // UIImages with identical content

            let i1 = self.resizeImage(image: img1, newWidth: widgetSize)
            let i2 = self.resizeImage(image: img2, newWidth: widgetSize)
            
            VStack {
                Image(uiImage: phase == 1 ? i1 : i2)
                    .renderingMode(.template)
                    .foregroundStyle(.white)
                    .background(.black)
                Spacer()
            }
        }
    }
}


#Preview {
    ContentView()
}
Answered by DTS Engineer in 795453022

The phase animator is cycling through the list of phases in the order that you provide using the default animation. Have you tried providing an animation based on the phase. Controlling the timing and movements of your animations Sample project and article covers this extensively, please review those resources and hopefully it helps.

The phase animator is cycling through the list of phases in the order that you provide using the default animation. Have you tried providing an animation based on the phase. Controlling the timing and movements of your animations Sample project and article covers this extensively, please review those resources and hopefully it helps.

SwiftUI: How to blend between UIImages without pulsating/pumping effect?
 
 
Q