I've done a major refactoring which will make Amino easier to maintain and, eventually, better performance and portability. Part of this work involved moving the platform specific parts to their own node modules. This means you should no longer install aminogfx directly. Instead, install the appropriate platform specific module. Currently there is one for GL and one for Canvas. I've also added stage transparency support to Raspberry Pi!


My hatred of C and C++ is world renown, or at least it should be. It's not that I hate the languages themselves, but the ancient build chain. A hack of compilers and #defines that have to be modified for every platform. Oh, and segfaults and memory leaks. The usual. Unfortunately, if you want to write fast graphics code you're pretty much going to be stuck with C or C++, and that's where Amino comes in.


I recently added the ability to set individual pixels in Amino, my Node JS based OpenGL scene graph for the Raspberry Pi. To test it out I thought I'd write a simple Mandlebrot generator. The challenge with CPU intensive work is that Node only has one thread. If you block that thread your UI stops. Dead. To solve this we need a background processing solution.


This is part 3 of a series on Amino, a JavaScript graphics library for OpenGL on the Raspberry PI. You can also read part 1 and part 2.

For today’s demo we will build a nice rotating display of news headlines that could run in the lobby of an office using a flatscreen TV on the wall. It will look like this:


This week we will build a digital photo frame. A Raspberry PI is perfect for this task because it plugs directly into the back of a flat screen TV through HDMI. Just give it power and network and you are ready to go.


I’ve been working on Amino, my graphics library, for several years now. I’ve ported it from pures Java, to JavaScript, to a complex custom-language generator system (I was really into code-gen two years ago), and back to JS. It has accreted features and bloat. And yet, through all that time, even with blog posts and the goamino.org website, I don’t think anyone but me has ever used it. I had accepted this fact and continued tweaking it to meet my personal needs; satisfied that I was creating something that lets me build other useful things. Until earlier this year.


I'm finally back from OSCON, and what a trip it was. Friend of the show wxl came with me to assist and experience the awesomeness that is OSCON. Over the next few days I'll be posting about the three sessions we taught and many, many sessions we attended. A splendid time is guaranteed for all. To kick things off, here is the code from my Amino talk.

Amino is my JavaScript graphics library I've been working on for a few years. Last year I started a big refactor to make it work nicely on the Raspberry Pi. Once we get X windows out of the way we can talk to the Pi's GPU using OpenGL ES. This makes things which were previously impossible, like 3d spinning globes, trivial on the Raspberry Pi.

For the talk I started by explaining how Node and Amino work on the Raspberry Pi, then shows some simple code to make a photo slideshow. (in this case, Beatles album covers).


Next we showed a 3D rotating text RSS headline viewer.

rss viewer

And finally, using the same GeoJSON code from the D3/Canvas workshop, a proper rotating 3D globe.


Hmm... Did you ever notice that the earth with just countries and no water looks a lot like the half constructed Death Start in Return of the Jedi?

Of course, my dream has always been to create those cool crazy computer interfaces you see in sci-fi movies. You know, the ones with translucent graphs full of nonsense data and spinning globes. And even better, we made one run on the Raspberry Pi. Now you can always know the critical Awesomonium levels of your mining colony.


Source for the demos on DropBox.


I am happy to announce the 1.1 release of Amino, my open source JavaScript graphics library, is ready today. All tests are passing. The new site and docs are up. (Generated by a new tool that I'll describe later). Downloads activate! With the iPad 3 coming any day now I thought it would be good to take a look at what I've done to make Amino Retina Ready (™). Even if you don't have a retina screen it will improve your apps.

The Problem

But first, let's back track and talk for a second about how Canvas works. Canvas isn't really a part of the DOM. To the web browser it just looks like a rectangular image that can be updated. It's just pixels. This low level access is powerful but comes with some tradeoffs. Since the rest of the browser just sees a Canvas element as an image it will scale the canvas as an image as well. If the user zooms the page then the canvas 'image' will be scaled up, resulting in pixelation. This is also a problem with Apple's hi-dpi retina screens. Though they have double the resolution of their non-retina counterparts they still report the same screen sizes. Essentially everything on the page is given a 2x zoom, so your canvas isn't taking advantage of the full pixel density. (This isn't strictly true, but bear with me for a second). Finally, if you scale the canvas area directly using CSS transforms or a proportional size (like width:50%) then the canvas may change size over the lifetime of the page, again giving the user zoomed in pixels. So how can we deal with this?

The Solution

Simple: we check if the real size of the canvas is different than the specified size. If it is then we can update the canvas size directly to match what is really on screen. The code looks like this:
if(canvas.width != canvas.clientWidth) { canvas.width = canvas.clientWidth; }
To deal with a retina display we just scale an extra 2x by checking for window.devicePixelRatio == 2. To tell when the user has changed the page by zooming or resizing we could hook up all sorts of event listeners, but I prefer to simply check on repaints since most things I do are animated. Of course we have to set the canvas height as well, which brings up the question: how should we scale things? If the canvas is uniformly scaled then you can calculate a ratio and multiply the height by that. If the canvas is *not* uniformly scaled, say because the width is set to a percentage but the height is not, then you can automatically scale to fit, or stretch it to fill the new size. In the end I found only a few combinations to actually be useful:
  • Do nothing. Don't adjust the canvas size or scaling at all.
  • Resize the canvas but don't mess with scaling. This essentially turns the canvas into a resizable rectangle, leaving it up to the content to adjust as desired.
  • Uniformly scale the content to fit.
To handle all of this I gave Amino two properties: Canvas.autoSize and Canvas.autoScale. autoSize controls whether the canvas should adapt at all. autoScale controls if it will rescale the content. Amino will handle all of the math and detect retina displays. All you have to do is choose which option you want. I haven't tested this on IE yet (I still need to get the new Win 8 preview) but I have tested this on FireFox, Chrome, Safari and Mobile Safari on an iPhone 4S. Check out the tests here to see it in action. Be sure to check out the new Amino site and download 1.1 here.


Amino 1.1 is on it's way, and despite the small version number difference the changes will be big. We are dropping Java support and heavily refactoring the JavaScript version.

First things first. I'm dropping support for Java. I have gotten essentially no downloads or feature requests for the Java version of Amino which tells me that almost no one is using it. If you want to do desktop Java graphics then I suggest moving to JavaFX. It is well supported and received many excellent updates in the past six months; and it's open source now. If I had known JavaFX was going to reboot with a pure Java version with great hardware acceleration then I probably wouldn't have started Amino to begin with. Leo itself will stay on the older version of Amino until I can get it ported, but no new features will go into the Java port. I highly suggest you check out JavaFX 2.1, now in beta. It even has WebKit integration.

Second, I have done a big refactor to the JavaScript port. The API will change only slightly. The big changes are under the hood in the way it handles animation and multiple canvases (canvii?). Now you can have a single core Amino engine per page that supports multiple canvases. They will all repaint quickly with minimal tearing while being as efficient as possible. This is a must on mobile devices, and in ebooks where multiple canvases per page are common.

Other stuff of note:

  • Bitmap Text: support the custom styled font output of Leonardo Sketch using dynamic bitmap sprites.
  • Animate DOM elements as well as shapes on the canvas.
  • Improvements to the animation api to support chaining, parallel animations, callbacks, and before/after actions.
  • Split into three files: core, shapes, and bitmap effects. Now you can do cool animation without including the scripts you don't need.
  • New API documentation.
  • Simple integration with Three.js for 3D objects with 2D canvas
  • Touch events for mobile devices.

Not everything is in the beta build yet, but it will be coming soon. Please try it out and give me feedback.


Over the past few weeks I've done more experiments and improvements to my ebook prototype. I'm still not sure what I'm going to do with it once I'm all done, but it's been an educational exercise nonetheless. Here's what I've done so far:

I've reorganized the code and put it into a github repo. Everything I'm going to show you is available to use and fork from right here. Click on any screenshot below to see a live example.


If we are going to call this stuff books then we need good typography. Fortunately 2011 saw the widespread adoption of web fonts. We can now use any custom font we want in any webpage, which includes the iPad with the release of iOS 5. To that end I tried searching for some custom fonts that add a bit a flavor while still remaining readable. After this font test I mocked up a full page with better typography for reading. This included bigger font size contrast, looser line height, a narrower column, auto-captializing the subheading at the top, and some inline images. Overall I'm happy with what can be done in pure CSS after just a few minutes work.

Google ChromeScreenSnapz036



When we talk about typography we also have to consider how the reader should view long form text. The world seems roughly split between scrolling and swiping between pages. I honestly hate page swiping unless the content really needs to be paginated (like a children's book). I did try some pagination experiments using CSS multi-columns but I'm not happy with the results. Perhaps with some more work they would be usable.

Google ChromeScreenSnapz038


Instead I've worked on scrolling. Scrolling feels very natural on a touch screen device, but you still need some static navigation to know where you are, switch pages, and view the table of contents. Fortunately CSS fixed positioning is pretty well supported these days, with IFRAMES as a useful backup, so it wasn't too hard.


Interactive Chart

I cooked up a simple bubble chart using Amino and some real data from the World Data Bank. You can use the slider to move time from 1960 to the present and see how the data changes. I think this type of interactive visualization will be very useful in ebooks.

Google ChromeScreenSnapz034


Interactive Code

To teach how to use a visual API like Canvas we should have a visual tool. We should be able to see what happens when we change variables, and actually see the code and canvas example change in real time. In my research I came across an amazing toolkit by Bret Victor called Tangle. Using that as a base I prototyped a simple tool for interactive text snippets. It rewrites any canvas javascript function you give it into a live example with formatted source. When you drag on one of the interactive variables (indicated in red) a popup appears to show you the value. As you drag left and right the value changes and the canvas updates to show the new result. This is the most direct way to learn what a function does.

Google ChromeScreenSnapz035

Code Wrapping

Another problem with code snippets is that they often are too long to fit on a single line. I could configure a PRE tag to wrap the long lines, but whitespace is usually significant in code. I don't want to create a situation where the reader thinks something is two lines when it is really one, such as a command line example they are trying to type in. Still, we need a way to view long lines. I played with various scrolling techniques but ultimately found they added more problems than they solved. Instead I found this great technique by [name] to creatively wrap lines. A wrapped line is shown indented with an arrow symbol to indicate it is wrapped from the previous line. This removes any ambiguity.


Google ChromeScreenSnapz037


Three Dee

The canonical example of what a digital book can do that a paper book can't is spinning an object around in 3D. I don't know how useful this will be in practice, but I wanted to prove it was possible. Using the amazing Three.js library I embedded a simple block that you can rotate using mouse drags or touch events. Three.js is really designed to use with WebGL, which isn't supported yet on most mobile platforms, but it can also render with plain canvas. It's not as fast, of course, but for simple flat shaded models it works well enough.

Google ChromeScreenSnapz039


Putting it all together

To really show off what this can do I put together a book demo using some real content from my HTML Canvas Deep Dive presentation last summer. It has a title page, table of contents (generated with a simple nodejs script), and two full chapters with code snippets, examples, and photo slideshows. I think the results speak for themselves.


Next Steps

I don't really know what the next steps are. I'm going to finish up the canvas book (probably eight chapters by the time I'm done) and use PhoneGap to put it in the iPad, webOS, and Android app stores. After I've proven it's possible I'm not sure what to do next. I did this as an experiment to research the state of the art. I think what I've put together could become a great set of tools for building interactive ebooks since the markup you actually have to write is rather minimal. Let me know if you have a use for this code if I fully developed it.






Vacation and travel is over and I'm happy to say things are moving again. I'm feeling refreshed and I have a lot to share with you in 2012; starting with the new book I'm writing for O'Reilly! Read on, MacDuff.

The Book

I've been working on a new book for O'Reilly, tentatively titled Building Mobile Apps in Java. I mentioned it briefly on Twitter but haven't gone into the details before. It will show you how to use GWT and PhoneGap to build mobile apps. With these two open source technologies you can code in Java but target pretty much any mobile platform such as iOS, Android, and webOS.

The book will cover the technical aspects of using GWT & PhoneGap. It will also dive into how to design for mobile. Navigation and performance varies greatly across devices, so it's an important topic. Oh, and the last chapter will show you how to make a mobile platform game with real physics. Tons of fun.

Building Mobile Apps in Java will be an eBook about 60 pages long, available every where O'Reilly publishes their ebooks. Look for it in February or early March.

Open Source and Speaking

For 2012 I want to spend some time doing more actual design work. I'm planning a new hand built wordpress theme for my blog, including proper phone and tablet support. I also have a few art side projects that you'll get to see later in the year.

And speaking of design, I have new significant releases of Amino and Leonardo Sketch coming. If you are in the Portland area come to the January PDX-UX meeting. I will be presenting how to do wire framing with Leonardo Sketch. I'll give a brief overview of Leo and show off some of the great export and collaboration features.

I will also be doing a 5 minute Ignite talk in Portland on February 9th about the future of ebooks and what a Hogwarts Textbook would look like.


Finally, I plan to post both more and less on this blog. I used to do short posts on small topics or collections of links. I found social networks better for that thing so I'll do that on Twitter and Google Plus from now on. From now on I want to use the blog for more long form content such as my well read HTML Canvas Deep dive. Look for more long essays on canvas, app stores, and technology trends this year.

2012 is finally here!




When working on big projects I often create little projects to support the larger effort. Sometimes these little projects turn into something great on their own. It's time for me to tell you about one of them: AppBundler.

AppBundler is a small tool which packages up Java (client side) apps with a minimum of fuss. From a single app description it can generate Mac OSX .app bundles, Windows .EXE files, JNLPs (Java Web Start), double clickable jars; and as of yesterday evening: webOS apps! I started the project to support Leonardo Sketch but I think it's time for AppBundler to stand on it's own.

Packaging Java apps has historically been an exercise in creative swearing. The JVM provides no packaging mechanism other than double clickable jars, which are limited and feel nothing like native apps. Mac and Windows have their own executable formats that involve native code, and Sun has never provided tools to support them. Java Web Start was supposed to solve this, but it never took off the way the creators hoped and has it's own idiosyncrasies. Long term we will have more a more environments with Java available but with different native package systems. Add in native libs, file extension registration, and other metadata; and now you've got a real problem. After hacking Ant files for years to deal with the issue I decided it was finally time to encode my build scripts and Java lore into a new tool that will solve the issue once and for all. Thus AppBundler was born.

How it works

You create a simple XML descriptor file for your application. It lists the jars that make up your app along with some metadata like the App name and main class. It can optionally include icons, file extensions, and links to native libraries.

<?xml version="1.0" encoding="UTF-8"?>
<app name="Amino Particles"> 
   <jar name="Amino2.jar"/> 
   <jar name="amino_sdl.jar"/> 
   <jar name="examples.jar" 
   <property name="com.joshondesign.amino.impl" value="sdl"/> 
   <native name="sdl"/> 

Then you run AppBundler on this file from the command line along with a list of directories where the jars can be found. In most apps you have a single directory with all of your jars, plus the app jar itself, so you usually only need to list two directories. You also specify which output format you want or --all for all of them. Here's what it looks like called from an ant script (command line would be the same).

 <java classpath="lib/AppBundler.jar;lib/XMLLib.jar" classname="com.joshondesign.appbundler.Bundler" fork="true"> 
<arg value="--file=myapp.xml"/> <arg value="--target=mac"/> <arg value="--outdir=dist/"/> <arg value="--jardir=lib/"/> <arg value="--jardir=build/jars/"/> </java> 
AppBundler will then generate the executable for each output format.

What it does

For Mac it will create a .APP bundle containing your jars, then include a copy of the JavaApplicationStub and generate the correct Info.plist files (Mac specific metadata files), and finally zip up the bundle. For Windows it uses JSmooth to generate a .EXE file with an icon and class path. For Java WebStart it will generate the JNLP file and copy over the jars. For double click jar files it will actually squish all of your jars together into a single jar with the right META-INF files. And all of the above works with native libraries like JOGL too. For each target it will set the correct library paths and do tricky things like decompress native libs into temp directories. Registering for file extensions and requesting JREs mostly works.

What about webOS?

All of the platforms except webOS ship with a JVM or one can be auto-installed on demand (the Windows EXEs do this). There is no such option for webOS, however. webOS has a high level HTML 5 based SDK and a low level C based PDK. To run Java on webOS you'd have to provide your own JVM and class libraries, so that's exactly what I've done. The full OpenJDK would be too big to run on a lightweight tablet, and a port would take a team of people months to do. Instead I cross compiled the amazing open source JVM Avian to ARM. Avian was meant to be embedded and already has an ARM port, so compiling it was a snap. Avian can use the full OpenJDK runtime, but it also comes with it's own minimal classpath.jar that provides the bare minimum needed to run Java code. Using the smaller runtime meant we wouldn't have a GUI like Swing, but using Swing would require months of AWT porting anyway, which I wasn't interested in doing. Instead I created a new set of Java bindings to SDL (Simple DirectMedia Layer), a low level graphics API available on pretty much every platform. Then I created a port of Amino (my 2D scene graph library) to run on top of SDL. It sounds complicated (and it was, actually), but the scripts hide the complexity. The end result is a set of tools to let you write graphical apps with Java on webOS. Amino already has ports to Java2D and HTML 5 Canvas (and OpenGL is in the works), so you can easily create cross platform graphics apps. And now with AppBundler you can easily package them as well. Interestingly, Avian runs on desktops nicely, so putting Java apps into the Mac App Store might now be possible. There's already some enterprising developers trying to get Avian working on iOS.

How you can help.

While functional, I consider AppBundler to be in an alpha state. There's lots of things that need work. In particular it needs Linux support (generate rpms or debs?) and a real Ant task instead of the Java exec commands you see above. I would also like to have it be included in Maven and any other useful repo. And as a final request (as long as I have you here), I need some servers to run builds tests on. I have already have Hudson running on a Linux server. I'd love it if someone could run a Hudson slave for me on their Windows or Mac server. And of course we need lots of testing and bug fixes. If you are interested please join the mailing list.

Client Java Freedom

AppBundler is another facet of my efforts to let help Java provide a good user experience everywhere. Apps should always feel native, and that includes the installation and start experience. I've used AppBundler to provide native installs of Leonardo Sketch on every desktop platform. I hope AppBundler will help you do the same. Enjoy! -Josh  




After several months of work, nestled in between getting webOS 3.0 out the door and prepping the nursery for the pending arrival of my first child, I am happy to announce the release of Amino 1.0. I have been eagerly following the development of HTML 5 Canvas support in the major browsers as well as ensuring the HP TouchPad will have great support for it. Amino is a great way to use the power of Canvas is modern mobile and web applications.


What is Amino?

Amino is a small scene graph library for both JavaScript and Java, letting you embed smooth animated graphics in webpages with the Canvas tag and in desktop Java applications with a custom JComponent. Amino provides a simple API to do common tasks, while still being extensible. For example, to create a rectangle that loops back and forth in a webpage, just do this:

var runner = new Runner();
runner.setCanvas(document.getElementById('canvas')); //create a rect filled with red and a black 5px border
var r = new Rect() .set(10,20,50,50) .setFill("red) .setStroke("black") .setStrokeWidth(5);
runner.setRoot(r); //animate r.x from 0 -> 300 over 5.5 seconds, and repeat
runner.addAnim(new PropAnim(r, "x", 0, 300, 5.5).setLoop(true)); //kick off the animation

See the results on the Amino homepage here

What can it do?

Amino can draw basic shapes (rects, circles, paths) and animate them using properties (width goes from 10 to 20 over 3.2 seconds) and callbacks. It also can buffer images to speed up common operations, manage varying framerates on different devices, and do Photoshop like image filtering (brightness, contrast, adjustment). And finally, Amino supports keyboard and mouse events on nodes within the scene, not just for DOM elements. In short, it's a portable scene graph for making interactive applications. Amino handles the hard work of processing input and scheduling the drawing to ensure a fast consistent framerate.

How about some examples?

I'm glad you asked. I've put together a couple of examples to show the variety of things you could do with Amino.

PlanetRover is a simple multilevel sidescroller game with jumping and collision detection.


Big Fish, Little Fish is a page from a hypothetical children's ebook, showing how text can be enriched with animation, images, and custom fonts.


This LineChart component is a super easy way to render graphical data in the browser with a minimal api.


These examples and more are available on the Amino Gallery Page.

How do I get it? What's the License

Amino is fully open source with the BSD license. You can download the source and binaries from here, or link directly to amino-1.0b.js from here in your app with a script tag.

If you'd like to contribute, or just want to let us know the cool stuff you are doing with Amino, please join the developer list or send an email to joshua at marinacci dot org


Another month has gone by with no update to Leonardo, or a real release of Amino. It's interesting how life changes. When I started this projects last summer I had no idea Jen and I would be having a baby in a month, nor did I truly have any notion how much my life would change. Everyone always says having children will change your life, but you never really understand it until you do it yourself, and our journey has just begun.

So, the upshot of all this rambling is that kids take time, and when you have to distribute a finite resource between multiple buckets, something has to get less. Sadly this time the short straw goes to my open source projects. It doesn't mean I won't work on them anymore, just at a slower pace. However, in order to feel at peace with myself I need to leave them in a state where they can still progress without my large time commitment. That's what this post is about.

I've spent the last year working on two main open source projects called Leonardo and Amino. Quick recap: Amino is a scene graph library for Java and JavaScript. Leonardo is a vector drawing program built on top of Amino. I want to get them both to a state where they are stable, useful, and can live on their own. Hopefully more of my job will be driving the community and integrating patches rather than directly coding everything. Every project reaches a point where it should stop being driven by a singular vision, and instead be driven by needs of actual users (the good projects anyway). Now is the that time. Time to focus on gaining adoption, growing a community, and making these projects rock-freaking-solid.

Concrete Plans


Amino basically works. Shapes are animated and drawn on screen, input events are properly transformed, and it's got pixel effects on both the Java and JavaScript sides. Speed, efficiency and features driven by actual use.

Amino finally has it's own website at GoAmino.org and I've set up auto-builds for both the Java and JavaScript versions. They also have a redesigned API doc template that you can see here. Last steps before a 1.0 release: bug fixes for Mobile Safari and FireFox, more demos, and a tutorial for integrating with Swing apps. (Oh, and if someone has a nice spring easing function, that would be swell). Target: next weekend.


It's basically done. It lets you draw vector art of shapes, images, and paths; and also create attractive presentations (which is just multiple pages of vector art). Now comes polish and adoption and export features. I suspect the value will really be in the export features so I need to know from you guys: what do you want?

In concrete terms I have a bunch of old bugs to fix and will finish the redesigned fill picker (colors, swatches, gradients, patterns, etc.) I also need your help updating the translations. Once that's done I'll clean up the website and cut a 1.0 release. Target: end of April.

Next Steps

In short, a lot of work for the next few weeks, but with luck (and hopefully some great feedback from you) , both Amino and Leonardo will be just fine.


In today's post I'll dive into Amino's new buffering support. At then end we'll talk about new API docs for Amino, the roadmap, and request for help on a domain name.

A big part of making a scenegraph fast is using lots of little tricks to do as little work as possible. Most of these tricks are decades old, but they still work. What makes a scenegraph good is letting developers easily use these tricks without having to code up anything special.

Dirty rect tracking is one such trick, but I haven't implemented it in Amino yet so I'll cover that in a few weeks. Another common trick is using intermediate buffers to store effects that are expensive to compute, such as blurs, shadows, and Photoshop style adjustments. The beauty of buffers is that if you can pretty much do any crazy thing you can think of, as long as you can figure out how to draw it into a buffer first. A good third of Swing Hacks, the book Chris Adamson and I wrote, is just different clever ways of using buffers.

Given the importance of buffers I made this a central feature of Amino. But before I go any further, how about a demo!

Zoom Effect

First, an MP3 style Visualizer. I say MP3 style because it's not actually working with audio. I'm just generating random data then pushing it through a simple buffer effect: draw into buffer1, copy buffer1 into buffer2 with stretching, flip buffers and repeat. It's a simple technique but if you do it over and over the results are very cool.

Google ChromeScreenSnapz020.png
MP3 Visualizer. Click to view

On a modern browser you should get a solid 60fps. BTW, a quick shout out to Internet Explorer 9. The guys at MS have done a top notch job. Amino runs beautifully there, no matter what I threw at it.

The Buffer API

Buffering is broken up into two parts. First is the actual Buffer object, which is a bitmap with a fixed width and height that you can draw into and can be drawn into other buffers or the screen. In the Java version of Amino this is a wrapper around BufferedImage. In the JavaScript version Amino creates an offscreen canvas object to use as a buffer.

The simplest use for a Buffer is in the BufferNode, which just draws its only child into the internal buffer for safe keeping. If the child hasn't changed on the next drawing pass then it will draw using the buffer instead. This is the simplest use case, but very important because you can draw a bunch of complex stuff and save it by simply wrapping it in a buffer. Here's a quick example:

//create a group with 100 child rects
var g = new Group();
for(var i=0; i<1000; i++) { g.add(new Rect().set(i,i,50,50));
} //wrap the group in a BufferNode
var b = new BufferNode(g);

The code above creates a group with a thousand rectangles. This will probably be slow to draw, but by wrapping it in a buffer it's only drawn once and then saved for later. Now the rest of your scene can draw at full speed.

Real Time Photo Adjustments

The next big use of buffers is for special effects like Photoshop filters. As of today Amino now has effects for blur, shadow, and photo adjustment (saturation, brightness, contrast). Each of these effects uses one or more buffers internally to manipulate the pixels before drawing to the screen. Blurring is a big topic, so I'll cover that in it's own blog later. Today I'll cover the photo adjustment.

Adjusting the saturation, brightness, and contrast of an image is actually pretty simple. It's just basic math and a lot of copying:

  • create two buffers.
  • draw your photo into the buffer 1
  • loop over every pixel in buffer 1
  • pull out the red, green, and blue components of that pixel's color.
  • calculate a new red, green, and blue using some math
  • Set the same pixel in buffer 2 using the new calculated color

For brightness, saturation, and contrast the equations are:

new color = old color + brightness
new color = (old color - 0.5)*contrast + 0.5
new color = old.red*0.21 + old.green*0.71 + old.blue*0.07

I won't bore you with the details of actually extracting the components with hex math and stuffing it back into the new pixels (well, maybe I will in a later blog on canvas performance). The point is you can do lots of effects with simple math.

The challenge with code like above is that it still may be too slow for real time work. Remember, the goal of Amino is a rock solid 60fps on a desktop browser and 30fps on a mobile device. To keep our framerate promise we need a way to do some work without blocking the UI. That means background threads.

Background Threads, Sorta

On the Java side we can use real background threads to do compute intensive effects; though honestly Java is fast enough for most cases that it hasn't been necessary yet. Canvas is most browsers is slow enough that we can't process an entire large picture (say 512x512) in a single frame. Unfortunately, JavaScript doesn't really have threads, or at least not until the forthcoming Worker API is released. So on to our backup plan: cheat.

We are allowed to do some work on the GUI thread as long as we don't take too much time. The solution: break up the work into small chunks and distribute them across multiple frames. It won't be quite as 'realtime' but it still allows us to do these effects in browser without slowing down the UI.

Amino now has an internal class called WorkTile which defines a subset of the full image to be processed. Right now it's set to 32x32 pixels. Once the effect starts it will process one WorkTile at a time until it runs out of time for this frame (currently set to 1000/40 ms). When the next frame arrives it will draw a few more WorkTiles until it runs out of time. After enough frames the image will be completely processed and saved into the final buffer, and work is terminated. Volia, 'background' processing of images in a browser without blocking the UI.

Currently only BackgroundSaturationNode uses this new worker system but eventually all effects will use it. Here's a demo to change the saturation, brightness, and contrast of a satellite image from Venus. Click the image to go to the demo page.

Google ChromeScreenSnapz021.png
Photo Adjustment. Click to run.

API Docs, Website, and Roadmap

Along with the buffering work I've recently written a new doc tool for Amino. I wanted something that would work on both Java and JavaScript code and didn't have the ugly legacy of classic javadoc. It's still a work in progress but I'm happy with the results so far. It's a new design where classes are grouped by category instead of package. Feedback is very welcome.

I think Amino is getting close to a real beta release. It's pretty stable in the major browsers and on mobile devices that support canvas (I haven't tested Android yet, but TouchPad and iPad work great). I have a bit more work to do on events, fills, and animation but once those are done we'll be ready for a 1.0 release.

Now the big question: where to put all of this? I think Amino deserves it's own domain so I'd like your help picking one. Please tweet your suggestions to @joshmarinacci.

That's it for this week. Thanks guys. I think Amino is shaping up be a rockin' scenegraph library.