Reputation: 913
I'm currently developing a simple photoshop like application on iphone. When I want to flatten my layers, the labels are at the good position but with a bad font size. Here's my code to flatten :
UIGraphicsBeginImageContext(CGSizeMake(widthDocument,widthDocument));
for (UILabel *label in arrayLabel) {
[label drawTextInRect:label.frame];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Anybody can help me ?
Upvotes: 30
Views: 20534
Reputation: 81
extension UIImage {
class func imageFrom(text: String, width: CGFloat, font: UIFont, textAlignment: NSTextAlignment, lineBreakMode: NSLineBreakMode) -> UIImage? {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
label.text = text
label.font = font
label.textAlignment = textAlignment
label.lineBreakMode = lineBreakMode
label.sizeToFit()
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
Using:
let iv = UIImageView(image: UIImage.imageFrom(text: "Test For \nYarik", width: 537.0, font: UIFont.systemFont(ofSize: 30), textAlignment: .center, lineBreakMode: .byWordWrapping))
iv.contentMode = .scaleAspectFit
Upvotes: 1
Reputation: 1450
I have created a Swift extension to render the UILabel
into a UIImage
:
extension UIImage {
class func imageWithLabel(label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
EDIT: Improved Swift 4 version
extension UIImage {
class func imageWithLabel(_ label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0)
defer { UIGraphicsEndImageContext() }
label.layer.render(in: UIGraphicsGetCurrentContext()!)
return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
}
}
The usage is simple:
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 22))
label.text = bulletString
let image = UIImage.imageWithLabel(label)
Upvotes: 25
Reputation: 4739
for Swift, I use this UIView-extension:
// Updated for Swift 3.0
extension UIView {
var grabbedImage:UIImage? {
get {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0.0)
layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
}
Upvotes: 3
Reputation: 3294
From: pulling an UIImage from a UITextView or UILabel gives white image.
// iOS
- (UIImage *)grabImage {
// Create a "canvas" (image context) to draw in.
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0.0); // high res
// Make the CALayer to draw in our "canvas".
[[self layer] renderInContext: UIGraphicsGetCurrentContext()];
// Fetch an UIImage of our "canvas".
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// Stop the "canvas" from accepting any input.
UIGraphicsEndImageContext();
// Return the image.
return image;
}
// Swift extension w/ usage. credit @Heberti Almeida in below comments
extension UIImage {
class func imageWithLabel(label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
The usage:
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 22))
label.text = bulletString
let image = UIImage.imageWithLabel(label)
Upvotes: 53
Reputation: 1724
You can use renderInContext on any CALayer. It will draw your view's layer on the context. So that you can change it to an image. Also if you do renderInContext on a view , all its subviews will be drawn onto the context. So instead of iterating through all the labels, while adding the labels, you can add those to a containerView. And just need to do renderInContext on that containerView.
Upvotes: 1
Reputation: 11174
you need to render the label in a context
replace
[label drawTextInRect:label.frame];
with
[label.layer renderInContext:UIGraphicsGetCurrentContext()];
and you will need to create one image per label, so move the for loop to outside the begin and end context calls
Upvotes: 5