Reputation: 2437
I have a plan to convert Text into Emoji. But, I don't know how to start. Here are some screen shots for what I am looking for.
I have the idea in my mind that to achieve the above result we should save dictionary for each character but the question is how that dictionary will save the emoji according to character structure.
Upvotes: 2
Views: 1482
Reputation: 3095
I would suggest you are using a simple bitmap technique. In a first step you build a black and white bitmap with the written text in the same dimensions as you like to have the final image.
In a second step you "divide" this image into a raster which is e.g. 20% smaller than the final emoji character to create the overlapping effect.
In each raster rectangle you calculate the black pixels. There you get a percentage between 0-100% black pixels. If this percentage e.g is over 40%, a random emoji is placed at the center of this rectangle.
You can improve the effect by adding a small amount of random displacement.
I implemented this and it worked great. I could improve the image even further by some small optimization:
For example if I get 1000
, I move it to the top left. If i get 1010
to the left.
The following example code demonstrates the shown approach, without the tweaks in the "final thought" section. It is written in Swift for a Cocoa application. You see the application delegate of a simple application which provides a text field and an image view in the main window.
You can complete the application adding the text field and image view to the main window and bind the values to the outlets textField
and imageView
. Also you have to bind the text field value to the parameterText
property.
The output of the application looks like this:
@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
}
}
Upvotes: 4