ios – Save a SwiftUI Image with an overlaid pattern to Photos App


I’m trying to save a SwiftUI Image to Photos App. I created a pattern overlay for it. But as a result, an I have an image with a pattern of a different size at Photos App. Is it possible to apply a pattern and save an image in the same form? Or initially display it in the form in which it will be saved.

How do I see it in my app
enter image description here

How do I see it in the Photos App
enter image description here

My code:

struct ImageWithGridOverlayView: View {
    
    @Binding var image: UIImage?
    @Binding var patternElementSideSize: CGFloat
    @Binding var didSave: Bool
    
    @Environment(\.displayScale) private var displayScale
    
    var body: some View {
        if let image {
            imageView(image)
                .overlay {
                    gridView()
                }
                .onChange(of: didSave, { _, _ in
                    save()
                })
        }
    }
    
    @ViewBuilder
    private func gridView() -> some View {
        let size = CGSize(width: patternElementSideSize, height: patternElementSideSize)
        let image = UIImage(resource: .grid).resized(to: size)
        Image(uiImage: image)
            .resizable(resizingMode: .tile)
    }
    
    @ViewBuilder
    private func imageView(_ image: UIImage) -> some View {
        Image(uiImage: image)
            .resizable()
            .frame(maxWidth: .infinity)
            .scaledToFit()
    }
    
    @MainActor
    private func save() {
        guard let uiImage = self.render(scale: displayScale) else { return }
        UIImageWriteToSavedPhotosAlbum(uiImage, nil, nil, nil)
    }
    
}

fileprivate extension UIImage {
    func resized(to size: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

fileprivate extension View {
    @MainActor
    func render(scale displayScale: CGFloat = 1.0) -> UIImage? {
        let renderer = ImageRenderer(content: self)
        renderer.scale = displayScale
        
        return renderer.uiImage
    }
}

I also tried to use VStack and HStack to create a pattern, but the result was the same.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img