如何从UILabel创建一个图像?

27

我目前在开发一个类似于iPhone上的简单Photoshop应用程序。当我想要将我的图层压缩时,标签的位置很好,但字体大小不正确。以下是我的压缩代码:

UIGraphicsBeginImageContext(CGSizeMake(widthDocument,widthDocument));

for (UILabel *label in arrayLabel) {
    [label drawTextInRect:label.frame];
}

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

有谁能帮我吗?

6个回答

51

来自:从UITextView或UILabel获取UIImage会得到白色图像

// 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扩展。鸣谢下面评论中的@Heberti Almeida

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
    }
}

使用方法:

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 22))
label.text = bulletString
let image = UIImage.imageWithLabel(label)

是的,我看过这篇帖子,但是用这个解决方案我无法得到高清晰度的文件。但是你让我明白了我的问题所在!非常感谢!! - Jonathan
7
为了在视网膜显示屏上获得清晰的图像,我们需要使用此行替换您方法中的第一行:UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0.0);这个问题及其被接受的答案所示。也许您希望更新您的回答,包括该信息。 - anneblue
如果您需要一个透明的图像,请在UIGraphicsBeginImageContextWithOptions中将不透明度设置为“NO”。 - Heberti Almeida
能否将标签渲染为其实际大小的三倍而不失去锐度? - Kashif

25

我创建了一个Swift扩展,将UILabel渲染成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
    }
}

编辑:Swift 4 版本已经改进

extension UIImage {
    class func imageWithLabel(_ label: UILabel) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0)
        defer { UIGraphicsEndImageContext() }
        label.layer.render(in: UIGraphicsGetCurrentContext()!)
        return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
    }
}

使用方法非常简单:

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 22))
label.text = bulletString
let image = UIImage.imageWithLabel(label)

5
你需要在上下文中渲染标签。
替换。
[label drawTextInRect:label.frame];

使用

[label.layer renderInContext:UIGraphicsGetCurrentContext()];

你需要为每个标签创建一个图像,因此将for循环移到开始和结束上下文调用之外。


2

对于Swift,我使用这个UIView扩展:

// 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
        }
    }
}

1
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
    }

}

使用:

    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

请不要贴上没有任何解释的代码。 - koen

1
您可以在任何CALayer上使用renderInContext。它将在上下文中绘制您的视图层,以便您可以将其更改为图像。此外,如果您在视图上执行renderInContext,则所有子视图都将绘制到上下文中。因此,在添加标签时,您可以将它们添加到一个容器视图中,而不是遍历所有标签。然后只需要在该容器视图上执行renderInContext即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接