如何将文本转换为表情符号?

How to convert Text into Emoji?

我有一个将文本转换为表情符号的计划。但是,我不知道如何开始。这是我正在寻找的一些屏幕截图。

我的想法是,要实现上述结果,我们应该为每个字符保存字典,但问题是该字典将如何根据字符结构保存表情符号。

我建议您使用简单的位图技术。在第一步中,您构建一个黑白位图,其中包含与最终图像相同尺寸的书面文本。

在第二步中,您 "divide" 将此图像转换为光栅,例如比最终表情符号字符小 20% 以创建重叠效果。

在每个光栅矩形中计算黑色像素。在那里你得到一个介于 0-100% 黑色像素之间的百分比。例如,如果此百分比超过 40%,则会在该矩形的中心放置一个随机表情符号。

您可以通过添加少量随机位移来改善效果。

最后的想法

我实现了这个并且效果很好。我可以通过一些小的优化进一步改善图像:

  • 对于每个大于 40% 黑色的矩形,我将这个矩形分成四个区域(左上、右上、左下、右下)。
  • 如果其中一个区域中有一个黑色像素,我将该区域记为 1,否则记为 0。
  • 这将创建 16 种不同的模式。对于这些模式中的一些,我将表情符号从矩形的中心移开更多。

例如,如果我得到 1000,我将它移到左上角。如果我得到 1010 到左边。

示例代码

以下示例代码演示了所示方法,没有 "final thought" 部分中的调整。它是用 Swift 编写的,用于 Cocoa 应用程序。您会看到一个简单应用程序的应用程序委托,它在主 window.

中提供了一个文本字段和一个图像视图

您可以完成将文本字段和图像视图添加到主 window 并将值绑定到插座 textFieldimageView 的应用程序。您还必须将文本字段值绑定到 parameterText 属性.

应用程序的输出如下所示:

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!
    @IBOutlet weak var textField: NSTextField!
    @IBOutlet weak var imageView: NSImageView!

    var updateTimer: NSTimer = NSTimer()

    let canvasSize = CGSize(width: 1024, height: 768)
    let canvasPadding: CGFloat = 32.0
    let emojiSize = 20.0
    let emojiSet: [NSString] = ["","","",""]
    let emojiJitter = 4.0

    var parameterText: NSString = "Hello!" {
        didSet {
            triggerImageUpdate()
        }
    }

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        triggerImageUpdate()
    }

    func applicationWillTerminate(aNotification: NSNotification) {
    }

    func triggerImageUpdate() {
        updateTimer.invalidate()
        updateTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("updateImage"), userInfo: nil, repeats: false);
    }

    func updateImage() {
        imageView.image = createEmojiImage(parameterText, size: canvasSize, padding: canvasPadding)
    }

    // This function creates a simple bitmap with the given text. The text
    // is centered in the bitmap and scaled to the maximum size.
    func createTextImage(text: NSString, size: CGSize, padding: CGFloat) -> NSImage {
        let canvasRect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
        let textRect = CGRectInset(canvasRect, padding, padding)
        var textBitmap = NSImage(size: size)
        textBitmap.lockFocus()
        NSColor.whiteColor().setFill()
        NSRectFill(canvasRect)
        let textFont = NSFont(name: "Helvetica Bold", size: 100)
        var textAttributes: [NSObject: AnyObject] = [
            NSFontAttributeName: textFont!,
            NSForegroundColorAttributeName: NSColor.blackColor()]
        let textSize = text.sizeWithAttributes(textAttributes);
        let scaleWidth = textRect.size.width/textSize.width
        let scaleHeight = textRect.size.height/textSize.height
        let scale: CGFloat
        if (scaleWidth < scaleHeight) {
            scale = scaleWidth
        } else {
            scale = scaleHeight
        }
        let scaledCanvasSize = CGSize(width: size.width/scale, height: size.height/scale)
        let offset = CGPoint(x: (scaledCanvasSize.width - textSize.width)/2.0,
            y: (scaledCanvasSize.height - textSize.height)/2.0)
        CGContextScaleCTM(NSGraphicsContext.currentContext()!.CGContext, scale, scale)
        text.drawAtPoint(offset, withAttributes: textAttributes)
        textBitmap.unlockFocus()
        return textBitmap
    }


    func createTextBitmap(text: NSString, size: CGSize, padding: CGFloat) -> NSBitmapImageRep {
        let textImage = createTextImage(text, size: size, padding: padding)
        let tiffImageData = textImage.TIFFRepresentation
        return NSBitmapImageRep(data: tiffImageData!)!
    }


    // This is a class which represents a single field.
    class Field {
        let center: CGPoint
        let black: Double
        init(center: CGPoint, black: Double) {
            self.center = center
            self.black = black
        }
    }

    // A function to get the black value from a certain rectangle in an image.
    func blackValue(image: NSBitmapImageRep, rect: CGRect) -> Double {
        let pixelInRect = Int(rect.size.width * rect.size.height)
        var blackCount = 0;
        for (var x = 0; x < Int(rect.size.width); ++x) {
            for (var y = 0; y < Int(rect.size.height); ++y) {
                var color = image.colorAtX(Int(rect.origin.x), y: Int(rect.origin.y))!
                if (color.redComponent < 0.1) {
                    blackCount++
                }
            }
        }
        return Double(blackCount) / Double(pixelInRect)
    }

    // A function to rasterize the bitmap into single fields.
    func rasterizeBitmap(image: NSBitmapImageRep, size: CGFloat) -> (width: Int, fields: [Field]) {
        let width = Int(image.size.width/size)
        let height = Int(image.size.height/size)
        var fields = [Field]()
        for (var x = 0; x < width; ++x) {
            for (var y = 0; y < height; ++y) {
                let rect = CGRect(x: CGFloat(x) * size, y: CGFloat(y) * size, width: size, height: size)
                let center = CGPoint(x: floor(CGFloat(x) * size + size/2.0), y: image.size.height - floor(CGFloat(y) * size + size/2.0))
                let black = blackValue(image, rect: rect)
                var field = Field(center: center, black: black)
                fields.append(field)
            }
        }
        return (width, fields)
    }

    // Function to create the emoji image.
    func createEmojiImage(text: NSString, size: CGSize, padding: CGFloat) -> NSImage {
        // Create and rasterize the bitmap.
        let textBitmap = self.createTextBitmap(text, size: size, padding: padding)
        let (fieldsWidth, fields) = self.rasterizeBitmap(textBitmap, size: CGFloat(emojiSize*0.75))
        // Create a new image
        var result = NSImage(size: size)
        result.lockFocus()
        NSColor.whiteColor().setFill()
        let canvasRect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
        NSRectFill(canvasRect)
        let textFont = NSFont(name: "Apple Color Emoji", size: CGFloat(self.emojiSize))
        var textAttributes: [NSObject: AnyObject] = [NSFontAttributeName: textFont!]
        NSColor.blackColor().setFill()
        for field in fields {
            let jitterX = CGFloat(Double(arc4random_uniform(101))/100.0*self.emojiJitter-self.emojiJitter/2.0)
            let jitterY = CGFloat(Double(arc4random_uniform(101))/100.0*self.emojiJitter-self.emojiJitter/2.0)
            if field.black > 0.4 {
                var randomEmoji = self.emojiSet[Int(arc4random_uniform(UInt32(self.emojiSet.count)))]
                var drawingPoint = CGPoint(x: field.center.x - CGFloat(self.emojiSize/2.0) + jitterX, y: field.center.y - CGFloat(self.emojiSize/2.0) + jitterY)
                randomEmoji.drawAtPoint(drawingPoint, withAttributes: textAttributes)
            }
        }
        result.unlockFocus()
        return result
    }
}