如何在iOS Swift中向图像添加文本?


79

我环顾四周,但未能弄清楚如何获取文本,将其覆盖在图像上,然后将两者合并为一个UIImage

我已经用我能想到的搜索字词用尽了Google,因此,如果有人有解决方案或至少有一个提示,他们可以指出它,将不胜感激。

Answers:


178

好吧...我想通了:

func textToImage(drawText: NSString, inImage: UIImage, atPoint: CGPoint) -> UIImage{

    // Setup the font specific variables
    var textColor = UIColor.whiteColor()
    var textFont = UIFont(name: "Helvetica Bold", size: 12)!

    // Setup the image context using the passed image
    let scale = UIScreen.mainScreen().scale
    UIGraphicsBeginImageContextWithOptions(inImage.size, false, scale)

    // Setup the font attributes that will be later used to dictate how the text should be drawn
    let textFontAttributes = [
        NSFontAttributeName: textFont,
        NSForegroundColorAttributeName: textColor,
    ]

    // Put the image into a rectangle as large as the original image
    inImage.drawInRect(CGRectMake(0, 0, inImage.size.width, inImage.size.height))

    // Create a point within the space that is as bit as the image
    var rect = CGRectMake(atPoint.x, atPoint.y, inImage.size.width, inImage.size.height)

    // Draw the text into an image
    drawText.drawInRect(rect, withAttributes: textFontAttributes)

    // Create a new image out of the images we have created
    var newImage = UIGraphicsGetImageFromCurrentImageContext()

    // End the context now that we have the image we need
    UIGraphicsEndImageContext()

    //Pass the image back up to the caller
    return newImage

}

要调用它,只需传递一个图像:

textToImage("000", inImage: UIImage(named:"thisImage.png")!, atPoint: CGPointMake(20, 20))

以下链接帮助我理解了这一点:

Swift-使用drawInRect:withAttributes绘制文本:

如何在Objective-C(iOS)中在图像上写文字?

最初的目标是创建一个动态图像,以供在AnnotaionView地图上给定位置使用价格之类的动态图像,这对它非常有用。希望这对尝试做相同事情的人有所帮助。

对于Swift 3:

 func textToImage(drawText text: NSString, inImage image: UIImage, atPoint point: CGPoint) -> UIImage {
    let textColor = UIColor.white
    let textFont = UIFont(name: "Helvetica Bold", size: 12)!

    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(image.size, false, scale)

    let textFontAttributes = [
        NSFontAttributeName: textFont,
        NSForegroundColorAttributeName: textColor,
        ] as [String : Any]
    image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))

    let rect = CGRect(origin: point, size: image.size)
    text.draw(in: rect, withAttributes: textFontAttributes)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage!
 }

对于Swift 4:

 func textToImage(drawText text: String, inImage image: UIImage, atPoint point: CGPoint) -> UIImage {
    let textColor = UIColor.white
    let textFont = UIFont(name: "Helvetica Bold", size: 12)!

    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(image.size, false, scale)

    let textFontAttributes = [
        NSAttributedStringKey.font: textFont,
        NSAttributedStringKey.foregroundColor: textColor,
        ] as [NSAttributedStringKey : Any]
    image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))

    let rect = CGRect(origin: point, size: image.size)
    text.draw(in: rect, withAttributes: textFontAttributes)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage!
 }

对于Swift 5:

func textToImage(drawText text: String, inImage image: UIImage, atPoint point: CGPoint) -> UIImage {
    let textColor = UIColor.white
    let textFont = UIFont(name: "Helvetica Bold", size: 12)!

    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(image.size, false, scale)

    let textFontAttributes = [
        NSAttributedString.Key.font: textFont,
        NSAttributedString.Key.foregroundColor: textColor,
        ] as [NSAttributedString.Key : Any]
    image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))

    let rect = CGRect(origin: point, size: image.size)
    text.draw(in: rect, withAttributes: textFontAttributes)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage!
}

1
超级有帮助!感谢您发布代码。并受到好评。
阿斯彭2015年

这些文本或其容器可以对点击事件做出响应吗?
PPrasai

1
@JadeSync如果要导入图像的对象是可单击的,则为是。但是,不是可单击的文本,而是需要单击最终图像的容器。实际上,这就是我对这张图片所做的事情,因为我需要一种在地图上具有可点击标记的方法,并且该标记需要在图像中包含文本。该标记具有单击事件委托,因此不是它们正在单击的图像,而是包含它的标记。
Christopher Wade Cantley

2
如果我将点设置在图像的右下角,并且文本太长,它将超出图像。关于如何使文本在该点的左侧对齐而不是在图像的右侧扩展的任何建议?
chickenparm

坦率地说,我也遇到了这个问题,它取决于字体类型和大小以及图像的大小,因为您可能不想踩在PNG阴影上,因此您希望文本在图像中开始。这是一个反复试验的事情,需要我添加一个字符,找出要移动起点的像素数,然后根据字符数快速计算出滑动起点(向上视外观而定)。我不想变得太复杂,所以我提出了一个简单的解决方案。
Christopher Wade Cantley

20

我的简单解决方案:

func generateImageWithText(text: String) -> UIImage? {
    let image = UIImage(named: "imageWithoutText")!

    let imageView = UIImageView(image: image)
    imageView.backgroundColor = UIColor.clear
    imageView.frame = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)

    let label = UILabel(frame: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
    label.backgroundColor = UIColor.clear
    label.textAlignment = .center
    label.textColor = UIColor.white
    label.text = text

    UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0)
    imageView.layer.render(in: UIGraphicsGetCurrentContext()!)
    label.layer.render(in: UIGraphicsGetCurrentContext()!)
    let imageWithText = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageWithText
}

需要考虑代码,但如何调整字体大小,每个图像大小随文本长度的不同而不同。我怎样才能使它充满活力。
iPhoneDev

我认为您应该使用自动收缩。为标签的最大宽度设置最大字体大小,然后添加:label.adjustsFontSizeToFitWidth = true&label.minimumScaleFactor = 0.5
Darkngs

有没有一种方法可以将标签文本添加到任何角落?
Ashh

11

您也可以执行CATextLayer。

    // 1
let textLayer = CATextLayer()
textLayer.frame = someView.bounds

// 2
let string = String(
  repeating: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce auctor arcu quis velit congue dictum. ", 
  count: 20
)

textLayer.string = string

// 3
let fontName: CFStringRef = "Noteworthy-Light"
textLayer.font = CTFontCreateWithName(fontName, fontSize, nil)

// 4
textLayer.foregroundColor = UIColor.darkGray.cgColor
textLayer.isWrapped = true
textLayer.alignmentMode = kCAAlignmentLeft
textLayer.contentsScale = UIScreen.main.scale
someView.layer.addSublayer(textLayer)

https://www.raywenderlich.com/402-calayer-tutorial-for-ios-getting-started


1
爱雷的东西。感谢您使用其他方法!
Christopher Wade Cantley

1
您将文本层添加到此处的视图中,而不是图像中
brainray 2015年

1
值得一提的,如果一个正在寻求垂直对齐文见stackoverflow.com/questions/4765461/...
JKRT

5

我已经创建了一个扩展,可以在任何地方使用它:

import Foundation
import UIKit
extension UIImage {

    class func createImageWithLabelOverlay(label: UILabel,imageSize: CGSize, image: UIImage) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(CGSize(width: imageSize.width, height: imageSize.height), false, 2.0)
        let currentView = UIView.init(frame: CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height))
        let currentImage = UIImageView.init(image: image)
        currentImage.frame = CGRect(x: 0, y: 0, width: imageSize.width, height: imageSize.height)
        currentView.addSubview(currentImage)
        currentView.addSubview(label)
        currentView.layer.render(in: UIGraphicsGetCurrentContext()!)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return img!
    }

}

用法:在ViewController上您要添加大小和标签的任何地方,请按以下方式使用它-

let newImageWithOverlay = UIImage.createImageWithLabelOverlay(label: labelToAdd, imageSize: size, image: editedImage)

1
太棒了!感谢您的贡献。
克里斯托弗·韦德·坎特利

即使我使用透明图像,它也会显示白色背景
EI队长v2.0

您正在做什么将其放在视图上或上传到服务器?
Ankit Kumar Gupta,

只需拍摄图像并在图像视图中显示它即可。它显示白色背景
EI队长v2.0

您的图像视图及其超级视图必须具有清晰的背景。如果您将其以png格式发布到服务器,那么它将是您想要的。这样做并检查。或者尝试一次将其保存在本地。
Ankit Kumar Gupta,

2

快速4:

func textToImage(drawText text: NSString, inImage image: UIImage, atPoint point: CGPoint) -> UIImage {


    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(image.size, false, scale)

    image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))

    let rect = CGRect(origin: point, size: image.size)

    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.alignment = .center



    let attrs = [NSAttributedStringKey.font: UIFont(name: "Helvetica Bold", size: 12)!,NSAttributedStringKey.foregroundColor : UIColor.white , NSAttributedStringKey.paragraphStyle: paragraphStyle]


    text.draw(with: rect, options: .usesLineFragmentOrigin, attributes: attrs, context: nil)



    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage!
}

1

我在您的最初问题中看不到任何暗示建议仅在代码中完成的内容-为什么不在接口构建器中简单地添加UILabel,并添加约束使其具有与图像相同的长度和宽度,垂直居中并水平(或按需放置),删除标签文本,根据需要设置文本字体,大小,颜色等(包括使用所需的最小尺寸或比例对Autoshrink进行勾选),并确保其背景是透明的。

然后,只需将其连接到IBOutlet,并根据需要在代码中设置文本(例如,在viewWillAppear中,或使用ViewModel方法并在初始化视图/视图控制器时进行设置)。


0

我已经尝试过此基本组件。希望它能工作。

func imageWithText(image : UIImage, text : String) -> UIImage {

        let outerView = UIView(frame: CGRect(x: 0, y: 0, width: image.size.width / 2, height: image.size.height / 2))
        let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: outerView.frame.width, height: outerView.frame.height))
        imgView.image = image
        outerView.addSubview(imgView)

        let lbl = UILabel(frame: CGRect(x: 5, y: 5, width: outerView.frame.width, height: 200))
        lbl.font = UIFont(name: "HelveticaNeue-Bold", size: 70)
        lbl.text = text
        lbl.textAlignment = .left
        lbl.textColor = UIColor.blue

        outerView.addSubview(lbl)

        let renderer = UIGraphicsImageRenderer(size: outerView.bounds.size)
        let convertedImage = renderer.image { ctx in
            outerView.drawHierarchy(in: outerView.bounds, afterScreenUpdates: true)

        }
        return convertedImage
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.