4

I am trying to write a method that will take a Bitmap and force it to a strict black and white image (no shades of grey).

I first pass the bitmap to a method that makes it greyscale using colormatrix:

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

    Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
    Canvas c = new Canvas(bmpGrayscale);
    Paint paint = new Paint();
    ColorMatrix cm = new ColorMatrix();
    cm.setSaturation(0);

    ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
    paint.setColorFilter(f);

    c.drawBitmap(bmpOriginal, 0, 0, paint);
    return bmpGrayscale;
}

that works nice and fast..

then i pass it to another method to force the greyscaled image to a 2 color image (black and white) this method works but obviously it is going through each pixel and that takes a long time:

public Bitmap toStrictBlackWhite(Bitmap bmp){
        Bitmap imageOut = bmp;
        int tempColorRed;
        for(int y=0; y<bmp.getHeight(); y++){
            for(int x=0; x<bmp.getWidth(); x++){
                tempColorRed = Color.red(imageOut.getPixel(x,y));
                Log.v(TAG, "COLOR: "+tempColorRed);

                if(imageOut.getPixel(x,y) < 127){
                    imageOut.setPixel(x, y, 0xffffff);
                }
                else{
                    imageOut.setPixel(x, y, 0x000000);
                }               
            }
        } 
        return imageOut;
    }

anyone know a faster more efficient way to do this?

erik
  • 4,946
  • 13
  • 70
  • 120
  • 1
    In addition to kcoppock's answer below(which will be much faster), you'll normally get a better quality threshold if you use the image median, rather than a constant `< 127`. It's a popular method because it works with just about any image, no matter what the ratio of light/dark, and gives a pretty clear picture in almost any circumstances. There's a link [here](http://stackoverflow.com/a/8959828/752320) that shows one method, along with an additional step for threshold noise, which cleans up the image even further. The whole thing works great for me, and it's fast, too. – Geobits Feb 15 '13 at 01:35

2 Answers2

3

Don't use getPixel() and setPixel().

Use getPixels() which will return a multidimensional array of all pixels. Do your operations locally on this array, then use setPixels() to set back the modified array. This will be significantly faster.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
1

Have you tried something like converting it into a byte array (see the answer here)?

And, as I look into this, the Android reference for developers about Bitmap processing might help you as well.

Community
  • 1
  • 1
DigCamara
  • 5,540
  • 4
  • 36
  • 47