【问题标题】:How to convert Text into Emoji?如何将文本转换为表情符号?
【发布时间】:2015-04-23 07:19:51
【问题描述】:

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

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

【问题讨论】:

    标签: ios dictionary text emoji


    【解决方案1】:

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

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

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

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

    最后的想法

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

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

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

    示例代码

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

    您可以完成将文本字段和图像视图添加到主窗口的应用程序,并将值绑定到插座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
        }
    }
    

    【讨论】:

    • 感谢您提供如此详细的答案。我可以看到您上述想法的粗略代码吗?这样我就可以看到结果了。
    • 我使用不同的方法得到了类似pasteboard.co/Twp1wLs.png 的结果,但根据结果看起来不太好。这就是我问你代码的原因。
    • 干得好。但我仍然面临在目标 c 中更改此代码的一些问题。因为我还没有接触 swift。如果您发布此代码的目标 c 版本会更好。谢谢。
    • 将其视为学习新事物的绝佳机会。这是免费的专家交流。如果您需要专业帮助来完成您的项目,您最好聘请软件开发人员。
    猜你喜欢
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 2019-09-03
    • 2015-10-18
    • 2015-01-15
    • 1970-01-01
    相关资源
    最近更新 更多