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

时间:2015-04-23 07:19:51

标签: ios dictionary text emoji

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

enter image description here enter image description here

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

1 个答案:

答案 0 :(得分:4)

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

enter image description here

在第二步中,您将此图像“划分”为光栅,例如比最终的表情符号字符小20%,以创建重叠效果。

enter image description here

在每个栅格矩形中,您可以计算黑色像素。你得到0-100%黑色像素的百分比。如果这个百分比例如超过40%,则在该矩形的中心放置一个随机表情符号。

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

最后的想法

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

  • 对于每个> 40%黑色的矩形,我将此矩形划分为四个区域(左上角,右上角,左下角,右下角)。
  • 如果其中一个区域中有黑色像素,我将区域计为1,否则为0.
  • 这会创建16种不同的模式。对于这些模式中的一些,我移动表情符号甚至更多地从矩形的中心移位。

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

示例代码

以下示例代码演示了所示的方法,没有“最终思考”部分中的调整。它是用Swift编写的Cocoa应用程序。您将看到一个简单应用程序的应用程序委托,该应用程序在主窗口中提供文本字段和图像视图。

您可以完成将文本字段和图片视图添加到主窗口的应用程序,并将值绑定到出口textFieldimageView。您还必须将文本字段值绑定到parameterText属性。

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

enter image description here

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