【问题标题】:How do I add text to an image in iOS Swift?如何在 iOS Swift 中向图像添加文本?
【发布时间】:2015-05-08 12:54:29
【问题描述】:

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

我已经用我能想到的搜索词用尽了谷歌,所以如果有人有解决方案或至少有他们可以指出的提示,我将不胜感激。

【问题讨论】:

    标签: ios swift uiimage


    【解决方案1】:

    好的...我想通了:

    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 - Drawing text with drawInRect:withAttributes:

    How to write text on image in 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!
    }
    

    【讨论】:

    • 超级有用!感谢您发布您的代码。评论很好。
    • 这些文本或它们的容器能否对点击事件做出响应?
    • @JadeSync 如果您要导入图像的对象是可点击的,那么是的。但不是文本是可点击的,它是最终图像在其中使用的容器需要是可点击的。事实上,这就是我对这张图片所做的,因为我需要一种在地图上具有可点击标记的方法,并且该标记需要在图像中包含文本。标记有一个点击事件委托,所以它不是他们点击的图像,而是包含它的标记。
    • 如果我将点设置在图像的右下角并且文本太长,它会超出图像。关于如何让文本与点的左侧对齐而不是从图像向右延伸的任何建议?
    • 我也遇到过这个问题,坦率地说,这取决于字体类型和大小,以及图像的大小,您希望文本在图像中开始的位置,因为您可能不想踩在PNG阴影上。这是一个反复试验的事情,需要我添加一个字符,计算出移动起始点需要多少像素才能进入,然后根据字符数进行快速计算以计算滑动起始点(向上根据它的外观达到最大值)。我不想变得太复杂,所以我解决了我的问题的简单解决方案。
    【解决方案2】:

    我的简单解决方案:

    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
    }
    

    【讨论】:

    • 感谢代码,但如何调整字体大小,每个图像大小因文本长度不同而不同。我怎样才能使这个动态。
    • 我认为你应该使用 Autoshrink。设置标签最大宽度的最大字体大小并添加:label.adjustsFontSizeToFitWidth = true & label.minimumScaleFactor = 0.5
    • 有没有办法添加与任何角对齐的标签文本?
    【解决方案3】:

    你也可以做一个 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

    【讨论】:

    • 爱雷的东西。感谢您提供替代方法!
    • 您在此处将文本层添加到视图中,而不是图像中
    • 值得一提的是,如果您希望垂直对齐文本,请参阅stackoverflow.com/questions/4765461/…
    【解决方案4】:

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

    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)
    

    【讨论】:

    • 太棒了!感谢您的贡献。
    • 即使我使用透明图片,它也会显示白色背景
    • 你在把它放在视图上或上传到服务器上做什么?
    • 只需拍摄图像并在图像视图中显示。它显示白色背景
    • 您的图像视图及其父视图必须具有清晰的背景。如果您以 png 格式将其发布到服务器,那么它将如您所愿。这样做并检查。或者尝试在本地保存一次。
    【解决方案5】:

    对于 Swift 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!
    }
    

    【讨论】:

      【解决方案6】:

      我在您最初的问题中看不到任何暗示这必须仅在代码中完成的任何内容 - 那么为什么不简单地在界面生成器中添加一个 UILabel ,并添加约束以使其具有与您的图像相同的长度和宽度,中心它垂直和水平(或者您需要放置它),删除标签文本,根据需要设置文本字体、大小、颜色等(包括使用您需要的任何最小大小或比例勾选 Autoshrink),并确保它的背景是透明的。

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

      【讨论】:

        【解决方案7】:

        我已经尝试过这个基本组件。希望它会起作用。

        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
            }
        

        【讨论】:

          【解决方案8】:

          也可以使用 QLPreviewController。只需将 imageFile 保存到 .userDomainMask 下的 applicationsDocuments 目录之类的 url 中,然后打开苹果的编辑器。您可以绘制、添加形状、箭头甚至是您的签名。 我在下面的帖子中详细解释了实现: https://stackoverflow.com/a/68743098/12035498

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多