0

Consider this MRE

struct MRE: View {
    @State var image: UIImage?
    
    @ViewBuilder
    func makeView() -> some View {
        VStack(spacing: 0) {
            Image("cat")
                .resizable()
                .aspectRatio(contentMode: .fit)

            Text("HELLO")
                .font(.system(size: 56))
        }
        .padding()
    }

    var body: some View {
        VStack {
            makeView()
            
            if let image = image {
                Image(uiImage: image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
            }
            
            Button {
                image = makeView().asImage()
            } label: {
                Text("copy")
            }
        }
    }
}

extension View {
    func asImage(scale: CGFloat = 1) -> UIImage {
        // Must ignore safe area due to a bug in iOS 15+ https://stackoverflow.com/a/69819567/1011161
        let controller = UIHostingController(rootView: edgesIgnoringSafeArea(.top))
        let view = controller.view
        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: CGPoint(x: 0, y: 0), size: targetSize)
        view?.backgroundColor = .clear

        let format = UIGraphicsImageRendererFormat()
        format.scale = scale // Ensures 3x-scale images. You can customise this however you like.
        let renderer = UIGraphicsImageRenderer(size: targetSize, format: format)
        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
}

It gives the following image, where the image looks exactly right, but the text always come out small. How to fix?

enter image description here

I have now also added the use of SwiftUI's Renderer, same thing

@MainActor func useRenderer() -> UIImage? {
        let renderer = ImageRenderer(content: makeView())
      
        renderer.scale = displayScale

        return renderer.uiImage
    }

Button {
   image = useRenderer()
   } label: {
   Text("copy2")
}
erotsppa
  • 14,248
  • 33
  • 123
  • 181
  • You didn't set the `scale` parameter. – matt Jul 27 '23 at 14:47
  • @matt I've tried the number 1,2,3. Text is always small – erotsppa Jul 27 '23 at 15:00
  • It's not a matter of the text being "rendered at a different size" ... the issue is related to the original image size. For example, here is what I get when using `100x100`, `100x300` and `300x100` images: https://i.stack.imgur.com/7XaI3.png (I set the background to blue so we can see the rendered image framing) – DonMag Jul 28 '23 at 16:18

0 Answers0