Pixel Playground using Renderscript Compute API

The following post will show you how easy it is to perform some simple image processing without writing complex C codes and JNI bindings.

We will use the existing HelloCompute example as our base code and we will just modify it a little bit to give us more control on the pixels of the image.

In our main activity, HelloCompute.java:

Here, after loading the input bitmap and the output bitmap, we then retrieve handles to our controls. Basically we will have a checkbox to reset our image back to its original state and 3 sliders to control the RGB values of the image. The OnCheckedChangedListener on the checkbox simply sets the flag on the renderscript code to render the original image, then update the output bitmap and invalidate our imageview to refresh the display.

Damn it I accidentally deleted the images!

Now, the juiciest part is the createScript method.

First, we need to allocate our input bitmap and the output bitmap which will give us easy access to the bitmaps from our renderscript code. Then we need to load our renderscript code stored in mono.rs. The class ScriptC_mono is actually an auto-generated class created by the LLVM front-end compiler. Renderscript API uses two compilers, one in the front-end that generates the support classes and the runtime compiler that is actually being shipped inside the Android devices (Honeycomb 3.0+). The methods set_width, set_height, invoke_filter, etc. are also generated based on the variables and methods declared inside mono.rs. Now let’s take a look at mono.rs

First line declares the Renderscript version that we want to use. Use 1 for now. Then line 2 declares the packagename where this script is going to be used. Then we declare all our variables. The generated code will have accessors and mutators for the variables and then invoke_methodName for methods. Next, the root method is like the main method in C or in Java. In this example, the root function will be called for every pixel of the bitmap. This is because we used the renderscript function rsForEach which simply loops through the allocated bitmap’s pixels and call the root function for each one of it. One thing to take note is that, according to Romain Guy and Chet Haase, this function (rsForEach) can take advantage of multiple cores which means that it can process the bitmap’s pixels in parallel and this obviously means a significant boost in terms of speed.

Although there’s a steep learning curve, the possibility of writing your own photo filters (your app can be the next Instagram :D) and the performance boost that you can gain from using Renderscript in your app are just worth it.