-
Notifications
You must be signed in to change notification settings - Fork 0
Image Gernerating
-
TargetμΌλ‘νλ Viewλ₯Ό ꡬννλ€.
- ν΄λΉ λ·°λ₯Ό κ·Έλλ‘ μ΄λ―Έμ§λ‘ λ§λ€κΈ° λλ¬Έμ λ°λ‘ Viewλ₯Ό λ§λ€κ±°λ μλμ κ°μ΄ λ°λλ λ΄μ©μ΄ μλ€λ©΄ extensionμ computed propertyλ‘ κ΅¬νν΄λ λλ€.
// λ λν΄μΌ νλ λ·° extension RendererTestView { private var TargetImageView: some View { ZStack{ Color.white VStack { Text("HELLO\nWORLD") .font(.title) .multilineTextAlignment(.center) } .padding(40) .background(.purple) .foregroundColor(.white) .shadow(color: .purple, radius: 10) } } }
-
TargetImageViewμ μ¬μ΄μ¦λ₯Ό GeometryReaderλ₯Ό ν΅ν΄ μ μ₯νλ€.
GeometryReader { geo in TargetImageView .onAppear { self.geoSize = CGSize(width: geo.size.width, height: geo.size.height) } }
-
λ λ λ²νΌμ ν΄λ¦ν κ²½μ° μλμ κ°μ΄ asImageλ₯Ό ν΅ν΄ μ΄λ―Έμ§λ₯Ό λ λνλ€.
Button { renderImage = TargetImageView.asImage(size: self.geoSize) } label: { Text("generate image") }
-
Viewμ λν extensionμ μλμ κ°μ΄ UIHostingControllerλ₯Ό ν΅ν΄ ν΄λΉ Viewλ₯Ό UIViewλ‘ μ¬μ©κ°λ₯νκ² νλ€.
extension View { func asImage(size: CGSize) -> UIImage { let controller = UIHostingController(rootView: self) controller.view.bounds = CGRect(origin: .zero, size: size) let image = controller.view.asImage(size: size) return image } }
-
UIViewμ λν΄μ μμ Extensionμ ν΅ν΄ asImageλ₯Ό ꡬννλ€. UIGraphicsImageRenderλ₯Ό ν΅ν΄ ν΄λΉ λ·°μ ν¬κΈ°λ§νΌ μ΄λ―Έμ§λ₯Ό λ λν΄μ returnν΄μ€λ€.
extension UIView { func asImage(size: CGSize) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1 return UIGraphicsImageRenderer(size: size, format: format).image { context in self.drawHierarchy(in: self.layer.bounds, afterScreenUpdates: true) } } }
-
λ°μ μ΄λ―Έμ§λ₯Ό 보μ¬μ£Όκ±°λ μ²λ¦¬νλ€.
struct RendererTestView: View { @State var geoSize: CGSize = .init(width: 0, height: 0) @State var renderImage: UIImage? var body: some View { VStack { GeometryReader { geo in TargetImageView .onAppear { self.geoSize = CGSize(width: geo.size.width, height: geo.size.height) } } // Imageλ₯Ό λ°μ κ²½μ° unWrappingν΄μ 보μ¬μ€λ€. if let uiImage = renderImage { Image(uiImage: uiImage) } else { Spacer() .frame(height: 200) } Button { renderImage = TargetImageView.asImage(size: self.geoSize) } label: { Text("generate image") } } .padding() } }
Core Graphicμμ μ§μμ§μνλ λ λλ¬λ‘
UIGraphicsImageRendererλ₯Ό ν΅ν΄UIImageλ₯Ό λ λν μ μλ€.
-
[UIGraphicsImageRendererFormat](https://developer.apple.com/documentation/uikit/uigraphicsimagerendererformat): λ λνλimageμ scale λ±μ μ€μ ν μ μλ€. -
[drawHierarchy(in:afterScreenUpdates:)](https://developer.apple.com/documentation/uikit/uiview/1622589-drawhierarchy): νμ¬ νλ©΄μμ κ·Έλ €μ§ νλ©΄μ renderν©λλ€.
UIHostingControllerλ SwiftUIλ·°λ₯Ό UIKitμμ μ¬μ©ν μ μκ² λμμ€λ€. μ λ€λ¦μΌλ‘ κ°μ§λContentμ SwiftUIλ·°λ₯Ό λ£μ΄μ μ μΈνλ©΄ ν΄λΉ λ·°λ UIKitμμ μ¬μ©κ°λ₯ν λ·°λ‘ νμ© κ°λ₯νκ² λλ€. μ¬κΈ°μλ ν΄λΉ λ·°μ λν΄UIGraphicsImageRendererλΌλ UIKit κΈ°λ₯μ μ¬μ©ν΄μΌ ν΄μUIHostingControllerλ₯Ό μ¬μ©νκ² λμλ€.
open class UIHostingController<Content> : UIViewController where Content : View//
// RendererTestView.swift
// test
//
// Created by Seungui Moon on 10/9/23.
//
import SwiftUI
struct RendererTestView: View {
@State var geoSize: CGSize = .init(width: 0, height: 0)
@State var highresImage: UIImage = UIImage()
@State var renderImage: UIImage?
var body: some View {
VStack {
GeometryReader { geo in
TargetImageView(cgSize: geo.size)
.onAppear {
self.geoSize = CGSize(width: geo.size.width, height: geo.size.height)
}
}
if let uiImage = renderImage {
Image(uiImage: uiImage)
.resizable()
.scaledToFit()
.frame(width: 200,height: 200)
}
Button {
renderImage = TargetImageView(cgSize: self.geoSize).asImage(size: self.geoSize)
} label: {
Text("generate image")
.frame(height: 200)
}
}
.padding()
}
}
#Preview {
RendererTestView()
}
extension UIView {
func asImage(size: CGSize) -> UIImage {
let format = UIGraphicsImageRendererFormat()
format.scale = 1
return UIGraphicsImageRenderer(size: size, format: format).image { context in
self.drawHierarchy(in: self.layer.bounds, afterScreenUpdates: true)
}
}
}
extension View {
func asImage(size: CGSize) -> UIImage {
let controller = UIHostingController(rootView: self)
controller.view.bounds = CGRect(origin: .zero, size: size)
let image = controller.view.asImage(size: size)
return image
}
}
struct TargetImageView: View {
@State var cgSize: CGSize
var body: some View {
ZStack{
Color.white
VStack {
Text("HELLO\nWORLD")
.font(.title)
.multilineTextAlignment(.center)
}
.padding(40)
.background(.purple)
.foregroundColor(.white)
.shadow(color: .purple, radius: 10)
}
}
}