[This post is by R. Jason Sams, an Android Framework engineer who specializes in graphics, performance tuning, and software architecture. —Tim Bray]
For ICS, Renderscript (RS) has been updated with several new features to simplify adding compute acceleration to your application. RS is interesting for compute acceleration when you have large buffers of data on which you need to do significant processing. In this example we will look at applying a levels/saturation operation on a bitmap.
In this case, saturation is implemented by multiplying every pixel by a color matrix Levels are typically implemented with several operations.
  1. Input levels are adjusted.
  2. Gamma correction.
  3. Output levels are adjusted.
  4. Clamp to the valid range.
A simple implementation of this might look like:

for (int i=0; i < mInPixels.length; i++) { float r = (float)(mInPixels[i] & 0xff); float g = (float)((mInPixels[i] >> 8) & 0xff); float b = (float)((mInPixels[i] >> 16) & 0xff); float tr = r * m[0] + g * m[3] + b * m[6]; float tg = r * m[1] + g * m[4] + b * m[7]; float tb = r * m[2] + g * m[5] + b * m[8]; r = tr; g = tg; b = tb; if (r < 0.f) r = 0.f; if (r > 255.f) r = 255.f; if (g < 0.f) g = 0.f; if (g > 255.f) g = 255.f; if (b < 0.f) b = 0.f; if (b > 255.f) b = 255.f; r = (r - mInBlack) * mOverInWMinInB; g = (g - mInBlack) * mOverInWMinInB; b = (b - mInBlack) * mOverInWMinInB; if (mGamma != 1.0f) { r = (float)java.lang.Math.pow(r, mGamma); g = (float)java.lang.Math.pow(g, mGamma); b = (float)java.lang.Math.pow(b, mGamma); } r = (r * mOutWMinOutB) + mOutBlack; g = (g * mOutWMinOutB) + mOutBlack; b = (b * mOutWMinOutB) + mOutBlack; if (r < 0.f) r = 0.f; if (r > 255.f) r = 255.f; if (g < 0.f) g = 0.f; if (g > 255.f) g = 255.f; if (b < 0.f) b = 0.f; if (b > 255.f) b = 255.f; mOutPixels[i] = ((int)r) + (((int)g)