Context
The user is sketching with straight lines on a canvas in the current CGContext. The user can draw straight lines, scale(pinch), and translate(pan) the whole drawing. Once the user leaves the drawing scene, the app saves into a data structure all the drawn lines.
Problem
I want to save the drawing into an image (png, jpeg doesn't matter) when the user is on a completely different scene, hitting upload to send the image of the drawing to the server.
So far, I've found a way to export to an image only the current core graphics context. But I can't figure out how to create a context on the background, replicate the drawing from the stored data and then export it to an image, without rendering it on the screen.
I don't want to save the image while the user is on the canvas scene because I need to save the image without any transformations applied (i.e., scale, translate).
CodePudding user response:
You could save it (to docs or temp directory) when the user finishes drawing, then load it to upload / display, etc.
Or, use UIGraphicsImageRenderer
to generate a UIImage
using your saved data structure.
Here's a quick, very simple example.
We create an array of points, then generate an image looping through those points with .addLine
to a bezier path:
class RenderDrawingVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let points: [CGPoint] = [
CGPoint(x: 60, y: 40),
CGPoint(x: 140, y: 40),
CGPoint(x: 140, y: 80),
CGPoint(x: 160, y: 120),
CGPoint(x: 100, y: 160),
CGPoint(x: 80, y: 120),
CGPoint(x: 20, y: 20),
]
let img = renderImage(bkgColor: .systemYellow, lineColor: .systemRed, size: CGSize(width: 200, height: 200), points: points)
// img is now a 200x200 UIImage
// save it, upload it, display it, whatever
}
func renderImage(bkgColor: UIColor, lineColor: UIColor, size: CGSize, points: [CGPoint]) -> UIImage {
let fmt = UIGraphicsImageRendererFormat()
fmt.scale = 1
fmt.opaque = true
let rndr = UIGraphicsImageRenderer(size: size, format: fmt)
let newImg = rndr.image { ctx in
ctx.cgContext.setFillColor(bkgColor.cgColor)
ctx.cgContext.addRect(CGRect(origin: .zero, size: size))
ctx.cgContext.drawPath(using: .fill)
let bez = UIBezierPath()
bez.move(to: points[0])
for i in 1..<points.count {
bez.addLine(to: points[i])
}
ctx.cgContext.setFillColor(UIColor.clear.cgColor)
ctx.cgContext.setStrokeColor(lineColor.cgColor)
ctx.cgContext.setLineWidth(4)
ctx.cgContext.setLineJoin(.round)
ctx.cgContext.setLineCap(.round)
ctx.cgContext.addPath(bez.cgPath)
ctx.cgContext.drawPath(using: .stroke)
}
return newImg
}
}
The resulting image: