Greyscale Views on Android

I recently had a requirement from my design team to make a particular View toggle between full colour and greyscale. Greyscale, in technical terms, means removing all saturation from an image. A quick Google search reveals the following code:

public Bitmap toGrayscale(Bitmap original) {        
    int height = original.getHeight();
    int width = original.getWidth();    

    Bitmap grayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(grayscale);
    Paint paint = new Paint();
    ColorMatrix cm = new ColorMatrix();
    cm.setSaturation(0); // <-- important line here
    ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
    paint.setColorFilter(f);
    c.drawBitmap(original, 0, 0, paint);
    return grayscale;
}

Pretty simple if all you want to do is de-saturate an image, but what if you want to de-saturate a View (and all of its children if it is a ViewGroup)?

This is actually really simple too, and can be done by applying a colour filter to a View layer.

If we look at the documentation for LAYER_TYPE_HARDWARE (or LAYER_TYPE_SOFTWARE), we can see the following:

"A hardware layer is useful to apply a specific color filter and/or blending mode and/or translucency to a view and all its children."

Nice! We can use this to apply our ColorMatrixColorFilter:

public void setGreyscale(View v, boolean greyscale) {
    if (greyscale) {
        // Create a paint object with 0 saturation (black and white)
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        Paint greyscalePaint = new Paint();
        greyscalePaint.setColorFilter(new ColorMatrixColorFilter(cm));
        // Create a hardware layer with the greyscale paint
        v.setLayerType(LAYER_TYPE_HARDWARE, greyscalePaint);
    } else {
        // Remove the hardware layer
        v.setLayerType(LAYER_TYPE_NONE, null);
    }
}

Here's a gif of the Cheesesquare app turning greyscale:

Side note: hardware layers are expensive! It's best to only temporarily have a hardware layer activated.

Brad Campbell

Android application developer, currently working as the lead on the ANZ goMoney NZ applications. All of the opinions and code on this blog are my own, and not that of ANZ.