We make awesome stuff for the internet, this is our blog!
Saving Images with HTML5 Canvas and App Engine’s Blobstore API
So while we’re busy making the best hands-free, sound-activated drawing tool ever we figured saving your creations to share with your friends would be pretty important. I took some time yesterday morning to set our App Engine instance up with some image saving capabilites which I’ll share in this post. We’re doing some cool stuff here like sending an encoded image from an HTML5 canvas cross-domain and then saving it to the App Engine Blobstore (an experimental feature).
Let’s start with our face drawing tool. The high-level mechanics of the tool are quite simple: we take data from the Hangouts API about face position and apply that data to a HTML5 ‹canvas› element about five times a second. You can draw to your heart’s content but that data will never get saved unless we do something about it. So here’s what we did about it: Once a drawing is complete, we stop the canvas from updating and save it with the native toDataUrl() method. Finally, we send it off to our Google App Engine instance for safe keeping.
The below JavaScript is pretty simple. We’re just grabbing a canvas element, encoding it to a base64 PNG, and then sending that off to a server with the help of jQuery.
What’s happening on our App Engine instance is a little more interesting. We use the Blobstore API, which allows us to create and serve data objects, called blobs. The Blobstore creates a blob from a file’s contents and returns a reference to the blob, called a blob_key, which can be used to serve the blob. Check out the UploadHandler class in the code snippet below, this is where everything gets blobby.
You’ll note that we’ve set cross origin resource sharing header to accept data from wherever. This is potentially hazardous, although is suitable for our testing in development. On line 27 to 29 you’ll see we take the “imgdata” parameter from our JavaScript post request, parse it so we grab just the image data, and finally decode the encoded string.
The next few lines (32 to 42) are where all the Blobstore API stuff happens. On line 32 we create a PNG and then in the following “with” statement we open the Blob that was just created and pipe in our decode image data. When that is complete, we finalize the file. I don’t really know what is happening here at a lower level, although I can take a guess. My guess is that a Google engineer takes a look at my code and laughs at my Python literacy with his buddies. After the file has been finalized we are safe to get the file’s blob key and save it to our App Engine datastore. We do this by creating a new Drawing object with our image’s blob key. In the very last bit of code in this method (lines 45 and 46) we simply respond to our JavaScript with the location of the image.
I hope this sheds some light on how to use base64 data from a canvas and save it to an App Engine instance. All in all, I found the Blobstore API pretty easy to work with once I understood what was going on conceptually and technically. Its flexibility is pretty cool and could address a bunch of usecases, including drawing with your face.
Jonathan Vingiano — @jgv
Yesterday I worked on transforming my Photoshop mockup of Draw With Your Face into CSS. Used a lot of utility classes for just about everything, which helps a lot for having less bloated CSS. I combine IDs and classes to keep element unique styles separate from those global - I find this really helps organize/structure a page. Stuff like this -
Design is inspired by the Mac System 7 Calculator
The original font I wanted to use is owned by Adobe, but I found an alternative font in Google Webfonts. http://www.google.com/webfonts
Ryder Ripps — @RYDER_RIPPS
Where’s the Pixel now available in the App Store for iPads and iPhones! Bigups to App Jester! - http://itunes.apple.com/us/app/wheres-the-pixel/id519896406?mt=8
Jonathan’s post about the setup for the Google Hangouts project. It touches on our thoughts about making stuff in general at the beginning.
Geting Up and Running With
Google+ Hangouts APIOptimizing for Developer Happiness
At OKFocus, we think a lot about optimizing for developer happiness. It’s important to us that when we work we have the flexibility to experiment with different ideas without having to worry about the project at hand going up in flames or something terrible happening to the codebase. Since this is at the core of our philosophy around creating digital experiences, all of our code is tracked using Git. For those who aren’t familiar with Git, it is a very popular version control system that allows developers to work together without having to worry about stepping on each other’s toes. Furthermore, it’s important that developers can have the freedom to use their own tools (everyone on this project uses a different text editor) and work locally on their own machines.
Our workflow goes something like this:
- Write some code
- Commit the code to the Git repository
- Push the code to Github
- All team members are notified in HipChat
- Team pulls changes
- Repeat!
If you want a closer look at the tools we use at OKFocus, check out this project on Github.
Working with the Google+ API and the Hangouts API is new for us. Going into this project we knew we wanted to bring our development methodologies with us to help us get the boring stuff out of the way and make something cool. Even better, we didn’t want to have to deploy to a server every time we committed a bit of code. Let’s look at how to make an awesome development environment that will get you hacking on a Google+ Hangout in no time.
Hacking on a Google Hangout Locally
To get started you will have to have the following installed:
Most OKFocus projects happen using Rails or Express.js. Both of these frameworks have a very simliar workflow and let developers work in a test, development, or production environment. Running a local web server with both of these frameworks is quite simple. For Draw With Your Face, we knew we’d be hosting our application with Google’s App Engine which is new to us, so we created a development environment that feels similar to what we’re used to.
Setting Up Your App Engine
Our use of App Engine for this project is simply to serve static files, theres a good chance your Hangout App will only require this functionality from a web server. To set up an App Engine instance, log into App Engine and create a new application. Take a note of your application identifier.
In your Hangouts API console, set your application URL to point to a path like http://[your-application-identifier].appspot.com/static/app.xml. This XML file tells your Hangouts App where to look for your app’s JavaScripts. Let’s worry about configuring it in a later section. Right now lets just configure your app.yaml for your App Engine instance to look like this:
Note that we have set our Python runtime to use Python 2.7.x. When doing so, you must also set “threadsafe” to be either true or false. This also tells our app to serve all files in the “static” directory coupled with a little bit of Python from our main.py file.
Stunnel
Once we had our App Engine instance deployed and running, we were still running into an issue where Hangouts wouldn’t let us serve our JavaScripts from localhost. It looks like almost all Google products have switched over to HTTPS (which is a good thing!); however, the development version of App Engine only allows HTTP locally. Thankfully, the open source community has a tool called stunnel that allows developers to tunnel HTTP connections through a secure layer as if the web server supported HTTPS.
After you’ve installed and built stunnel, you can set “accept” to 8001 and “connect” to 8080 for HTTPS. You’ll find this setting at the bottom of stunnel.conf. We keep a copy of stunnel.conf in our Git repository for this project. To start our servers, we simply type:
sudo stunnel stunnel.confWe run this command from the root of our project directory, referencing our customized stunnel.conf file as the first argument to the stunnel command from the command line.
Serving the App
Now let’s configure our Hangout App’s main XML so we are referencing our new stunnel configuration. Once everything is configured and looks okay, you can deploy to App Engine using the App Engine Launcher.
Note that we are serving from port 8001 per our stunnel configuration. You’ll also note the link to the commented out path for production. Once we’re ready to start serving from App Engine, it just a matter of uncommenting that, removing our references to localhost, and deploying.
Hacking Locally
Now that your XML is referencing files that are being served from your localhost through stunnel, you are free to work locally and see changes immediately. This means you wont have to deploy to Google App Engine over and over. This also means that you can share code quickly with team members through Github and merge in changes with ease. Simply work with the JavaScript referenced in your main XML file, and visit the test hangout. You’ll see your changes immediately!
One thing to note is that this setup allows for only one participant in a Hangout at a time. This isn’t a problem during early development stages but we will have to alter our environment next week to make multiple participants work. Look for a blog post early next week from Jules that will explore that and more.
Happy hacking :)
Jonathan Vingiano — @jgv
Today we worked on some core design elements. Getting the logo figured out was fun. We wanted to exploit the fact that all the words in the title are four letters as well as figure out a way to incorporate a face. A face mesh taken from a pic found on google image search (http://www.lysator.liu.se/~eru/research/) was traced and simplified, and then overlaid on top of a heavily modified uppercase version of DIN font. The outcome is sort of old meets new, which we like.
Hello and welcome to our development blog. We’re going on a two week journey developing Draw With Your Face, an experiment using the Google+ Hangouts API and you’re invited to join us…
Draw With Your Face is a fast-paced drawing game where you’ll compete with friends to guess each other’s drawings the fastest. The twist is, using the facial tracking features of the Hangouts API, you’ll be creating those drawings using YOUR FACE!
On this blog, you’ll be able to keep track of our development over the course of Google’s Hangouts Hackathon. We’ll give you a peek into our process and share some technical code snippety stuff.
To get things started let’s introduce the team:
OKFocus + Aaron Meyers just began working with a company called Google on a Hangouts API Experiment! See Google’s Blog Post about it. We’ll be posting updates on http://drawwithyourface.com
Checkout the new OKFocus jQuery plugin, OKFocus Video, allowing for fullscreen video backgrounds! http://okfoc.us/okvideo
Website launched for Nicola @Formichetti’s company, Two Hustlers, http://twohustlers.com/
“Flat File” (on right) by OKFocus for Eric Wrenn - http://ericwrennoffice.com
we like that GitHub makes their cease and disists public
drawing app in works
emoji is beautiful!
Science Near You - a new site built on Google Maps we launched with Liberty Science Center