My final ICM project – the emoji translator and mixer

For my final project, I made an emoji translator and mixer. The program converts user input into emojis instead of the user having to browse through tabs in order to find the right icon. It also lets the user create one animated icon to combine two emotions. Resources:

  • I used this list of 5000 words as a resource for the database to match words to icons.
  • After failing to use the Apple Color Emoji as a font, I got the icons as png files  from here and used that instead.

Libraries in use

  • Control P5 library for UI elements
  • gifAnimation library for gif animation
  • java.awt.Frame; to get a second  frame

video documentation emoji mixer from ziv schneider on Vimeo.     The code for translating user input into emojis in a 2nd window: import controlP5.*; import java.awt.Frame; import java.awt.BorderLayout; PFrame PFrame; secondApplet s; ControlP5 cp5; Table dataset; PImage img; PImage img2; float a; PFont f; PFont sf; public StringDict emojis; public String translated = “_______”; public String translated2 = “_______”; public String date = day() + “_” + hour() + “_” + minute(); void setup() { size(420, 370); frameRate(12); imageMode(CENTER); dataset = loadTable(“words_emoji.csv”, “header”); emojis = dataset.getStringDict(“WORD”, “EMOJI”); cp5 = new ControlP5(this); PFrame PFrame = new PFrame(); s = new secondApplet(); f = createFont(“Arial”, 16, true); sf = createFont(“Arial”, 10, true); ///textfield 1 cp5.addTextfield(“1”) .setPosition(20, 100) .setSize(190, 40) .setFont(createFont(“arial”, 20)) .setFocus(true); ///textfield 2 cp5.addTextfield(“2”) .setPosition(20, 180) .setSize(190, 40) .setFont(createFont(“arial”, 20)) .setAutoClear(true); ///clear button cp5.addBang(“clear”) .setPosition(20, 320) .setSize(40, 20) .getCaptionLabel().align(ControlP5.CENTER, ControlP5.CENTER); cp5.addSlider(“MIX”) .setId(1) .setPosition(20, 270) .setWidth(190) .setRange(2, 6) .setValue(3) .setNumberOfTickMarks(6) .setSliderMode(Slider.FIX); } void draw() { int indent = 20; textFont(f); fill(255); background(0); text(“Type two words.”, indent, 40); text(“Press return after each word.”, indent, 65); textFont(sf); text(translated, indent+13, 152); textFont(sf); text(translated2, indent+13, 232); } public void clear() { cp5.get(Textfield.class, “1”).clear(); cp5.get(Textfield.class, “2”).clear(); } void controlEvent(ControlEvent theEvent) { switch(theEvent.controller().id()){ case(1): a = (float)(theEvent.controller().value()); println(“a slider event A.”); break; } if (theEvent.isAssignableFrom(Textfield.class)) { if (theEvent.getName().equals(“1”)) { translated = theEvent.getStringValue(); } if (theEvent.getName().equals(“2”)) { translated2 = theEvent.getStringValue(); } } }   public class PFrame extends Frame { public PFrame() { setBounds(700, 320, 200, 200); s = new secondApplet(); add(s); s.init(); show(); } } import gifAnimation.*; public class secondApplet extends PApplet{ GifMaker gifExport; String path = “/Users/zivschnieder/Documents/Processing/two_frames/data/”; public void setup() { imageMode(CENTER); gifExport = new GifMaker(this, “emo”+date+”.gif”, 256); } void draw(){ background(0); images(); animateGif(); } public void images(){ float x = 0; float y = 0; float b = random(2, 8); if (emojis.hasKey(translated)) { String file = emojis.get(translated); PImage img = loadImage(path + file); img.loadPixels(); int dimension = img.width * img.height; for (int i = 0; i<dimension; i+=a) { img.pixels[i] = color(255, 0); } img.updatePixels(); image(img, width/2, height/2, img.width, img.height); } if (emojis.hasKey(translated2)) { String file = emojis.get(translated2); PImage img2 = loadImage(path+file); img2.loadPixels(); int dimension =img2.width * img2.height; for (int i = 0; i<dimension; i+=b) { img2.pixels[i] = color(255, 0);} // img2.updatePixels(); image(img2, width/2, height/2, img2.width, img2.height); } animateGif(); } public void animateGif(){ if (key == ‘1’) { gifExport.setRepeat(0); gifExport.setDelay(1); gifExport.addFrame(); println(“gifanimation”); } if (key == ‘0’) { gifExport.finish(); println(“stop”); } } }   Code for the mix and gif animation from two images: import gifAnimation.*; import controlP5.*; GifMaker gifExport; PImage img; PImage img2; PFont sf; ControlP5 cp5; public float a = 5; public float b = (random(3,6)); void setup() { String date = day() + “_” + hour() + “_” + minute(); println(date); gifExport = new GifMaker(this, “emo”+date+”.gif”); size(220, 220, P3D); frameRate(12); imageMode(CENTER); sf = createFont(“Arial”,8, true); cp5 = new ControlP5(this); cp5.addSlider(“MIX IT!”) .setId(1) .setPosition(20, 180) .setWidth(140) .setRange(2,6) .setValue(2) .setNumberOfTickMarks(6) .setSliderMode(Slider.FIX); } void draw() { background(0); float x = width/2; float y = height/2-20; float b = random(2, 8); loadPixels(); PImage img = loadImage(“emo419.png”); int dimension = img.width * img.height; for (int i = 0; i<dimension; i+=(b)) { img.pixels[i] = color(255, 0); } image(img, x, y, 128, 128); PImage img2 = loadImage(“emo408.png”); int dimension2 = img2.width * img2.height; for (int i = 0; i<dimension2; i+=(a)) { img2.pixels[i] = color(255, 0); } image(img2, x, y, 128, 128); updatePixels(); animateGif(); text(“press 1 for gif animation, 0 to stop.”, 3, 10); } void animateGif(){ if (key == ‘1’) { gifExport.setRepeat(0); // make it an “endless” animation // gifExport.setTransparent(0,0,0); // black is transparent gifExport.setDelay(0); gifExport.addFrame(); println(“gifanimation”); } if (key == ‘0’) { gifExport.finish(); println(“stop”); } } void controlEvent(ControlEvent theEvent) { switch(theEvent.controller().id()){ case(1): a = (float)(theEvent.controller().value()); println(“a slider event.”); break; } }

hourglass

hourglass

This is a sketch for an hourglass geometric movement that I am working on for physical computing.
It’s counting a minute with millis and there are two rectangles located behing a transparent png shape.
The rectangles are in corners mode and their Y is attached to millis and moving down or up with time.

I had a problem getting the bottom one to appear, but after seeing Shiffman for help, realised that it might be because of my screen size vs. the sketch size.

Final project progress

###

For my final project, I am making an emoji translator/mixer. One thing I find very annoying about using emojis, is that instead of them saving a little typing time, I waste a quarter of my day looking for the right one because there are so many of them and they are not organised clearly. I wish there was a way to simply type a word and have the emoji appear instead! I have collected a list of 5,000 words that are the most common ones in the english language, and I am matching them to emojis. Since there are only 450 emojis at the moment, images will match more than one word. Also, sometimes one emoji does not exactly match the way you are feeling at that moment. Which is why we get lines of icons to express one state. What if there were mixed emojis that we could make on our own? The second part of the project will be a mixer. The user will type in two words. Two images will appear, woven into each other. The user could then create an animated gif from the two. Iv’e already made some gifs, with random combinations of words, as you can see here:
http://mixedemojions.tumblr.com/

 

  I was hoping to use the Apple Color Emoji font, but after encoding issues chose to use png images instead. For the UI elements, I used the control P5 library and for the animation I used gifAnimation library. Right now, I have two separate parts of the project working, with some issues to resolve.

  1. Connecting the parts of the project: right now, I separated the animation because it didn’t work well with the translator. Right now, with the translator, I have one string and can’t control the images separately so that they would have different gaps within the pixels.
  2. The text fields need to create separate strings. Right now they are doing something weird together.
  3. Limiting each text field to one word.
  4. Moving from one field to the next with tab/space.
  5. Sending the animation into a new window – Iv’e started using two windows with some java library import, but still need to learn how to control it.
  6. Connecting to the web. right now I am manually uploading the gifs to tumblr.
  7. Getting png files for emoji2, which has some of the best ones.
  8. Designing a nicer interface.
  9. Saving each gif as a new one, right now they are overriding each other.
  10. Translating 5000 words to emojis!

This is how the translator looks right now:     Screen Shot 2013-11-16 at 9.24.30 PM

Data

Lou Reed tweets

This is my homework for the data assignment.
My idea was to show the change in the number of tweets about Lou Reed from during the week after his passing.
The dots representing each tweet would create Lou Reed’s name and fade with time, showing how a name appears and disappears in social media during a brief period of time.

Most of my time was spent on getting the data itself. I tried getting a Json from twitter and after struggling with it, opted for using scraperwiki.com  and got a CSV file with the tweets.

This is as far as I got with the sketch, which might be visually disappointing when comparing with the initial goal, but it involved a lot of learning about getting data and reading from it.

Lou Reed tweets

This is my code:

Table dataset;
StringList allTime= new StringList();
float a;
float b;
float c;
float d;
float e;
float f;
void setup() {
size(1280,720);
a= random(0,100);
b= random (0,720);
c= random (100,200);
d= random (0,720);
e= random (200,300);
f= random (0,720);
smooth();

//read the data from the table
dataset = loadTable(“lou_reed_tweets.csv”, “header”);

// add the column “time” to allTime stringlist
allTime.append(dataset.getStringColumn(“time”)); }

void draw(){
background(0);
if(allTime.hasValue(“10/30/13”) == true ) {
circle();
print(“yes”);

}

if(allTime.hasValue(“10/29/13”) == true ) {
circle2();
print(“29 “);

if(allTime.hasValue(“10/28/13”) == true ) {
circle3();
print(“28 “); }
}

}

void circle() {

ellipse(a,b,10,10);
fill(255);

}

void circle2(){
ellipse(c,d,10,10);
fill(255);

}

void circle3(){
ellipse(e,f,10,10);
fill(255);

}

Pixels & Data

This is serial date coming from a pulse sensor in Arduino affecting the image tint.
Iv’e also used this data with processing to set an alarm when the pulse gets too high, as part of a Pcomp project.

Screen Shot 2013-11-25 at 11.25.52 AM

 

 

 

 

 

 

 

 

 

 

 

Heartalarm


https://vimeo.com/77601603

 

 

 

This is the code (based on the original code that comes with the pulse sensor):

import processing.serial.*;
PFont font;
Serial port;
int Sensor; // HOLDS PULSE SENSOR DATA FROM ARDUINO
int IBI; // HOLDS TIME BETWEN HEARTBEATS FROM ARDUINO
int BPM; // HOLDS HEART RATE VALUE FROM ARDUINO
int[] rate; // USED TO POSITION BPM DATA WAVEFORM

//float zoom; // USED WHEN SCALING PULSE WAVEFORM TO PULSE WINDOW
float offset; // USED WHEN SCALING PULSE WAVEFORM TO PULSE WINDOW

boolean beat = false; //set when a heart beat is detected, then cleared when the BPM graph is advanced
float val = 0.0;
float r;

void setup() {
size(640, 480,P3D); //Stage size
frameRate(100);
font = loadFont(“Arial-BoldMT-24.vlw”);
textFont(font);
rectMode(CENTER);
textAlign(CENTER);

// GO FIND THE ARDUINO
println(Serial.list()); // print a list of available serial ports
// choose the number between the [] that is connected to the Arduino
port = new Serial(this, Serial.list()[8], 115200); // make sure Arduino is talking serial at this baud rate
port.clear(); // flush buffer
port.bufferUntil(‘\n’); // set buffer full flag on receipt of carriage return
}

void draw() {
background(0);
text(BPM + ” BPM”,100,50); // print the Beats Per Minute

fill(255);

if (beat){
sphere(r);
r= random(BPM*0.89, BPM*0.9);}
}
void serialEvent(Serial port) {

String inData = port.readStringUntil(‘\n’);
inData = trim(inData); // cut off white space (carriage return)

println(inData);

if (inData != null && inData.length() > 1) {

if (inData.charAt(0) == ‘S’) { // leading ‘S’ for sensor data
inData = inData.substring(1); // cut off the leading ‘S’
Sensor = int(inData); // convert the string to usable int
}
if (inData.charAt(0) == ‘B’) { // leading ‘B’ for BPM data
inData = inData.substring(1); // cut off the leading ‘B’
BPM = int(inData); // convert the string to usable int
beat = true; // set beat flag to advance heart rate graph
val = val + 0.02;
}
if (inData.charAt(0) == ‘Q’) { // leading ‘Q’ means IBI data
inData = inData.substring(1); // cut off the leading ‘Q’
IBI = int(inData); // convert the string to usable int
}
}
}

Homework – week #3 – Coffee on my mind

Screen Shot 2013-09-24 at 11.39.30 PM

For this weeks homework I made this coffee machine interface that allows you to get your coffee just the way you like it. I learned about buttons, variables and conditionals.

Things I couldn’t accomplish for this exercise:
– Getting the scroller to work.
– Embedding the code in WP, suspecting it has something to do with the theme I chose.

So here is a video and some screenshots.

Gimme Coffee from ziv schneider on Vimeo.

Screen Shot 2013-09-24 at 11.39.30 PM

Screen Shot 2013-09-24 at 11.39.37 PM

Screen Shot 2013-09-24 at 11.39.41 PM

Screen Shot 2013-09-24 at 11.41.42 PM

Screen Shot 2013-09-24 at 11.41.49 PM