Get the FULL version

Android: Bitmap to Integer array

Android: Bitmap to Integer array thumbnail

As stated in the title, this post explains how to generate an Integer pixel array from a Bitmap object, that will hold the color information from each pixel of the image. This post also explains the opposite: creating a Bitmap object from an Integer array. This can be useful when one needs to apply effects to Bitmap instances. As usual, an example Eclipse project is available for download at the end of this post. It works both on the emulator and on physical devices running Android 2.0.

So, let’s get to the code. Putting it in a simplified manner, the below Activity decodes a PNG image into a Bitmap object, then, an array is created with the same number of pixels as the image. After that, a method from the Bitmap instance puts the pixel color information in the array. The array is later processed and encoded into the same Bitmap object, creating a new image that gets displayed on the screen. Here’s the code:

package fortyonepost.com.btia;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;

public class BitmapToIntArrayActivity extends Activity
{
	//a Bitmap object
	private Bitmap bmp;

	//an array that stores the pixel values
	private int intArray[];

	//an ImageView, to render the original image
	private ImageView iv_originalImage;
	//an ImageView, to render the modified image
	private ImageView iv_imageFromArray;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //initialize the ImageView objects using data from the 'layout.xml' file
        iv_originalImage = (ImageView) findViewById(R.id.iv_originalImage);
        iv_imageFromArray = (ImageView) findViewById(R.id.iv_imageFromArray); 

        //initialize the Bitmap Object
        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.four_colors);
        //Guarantees that the image is decoded in the ARGB8888 format
        bmp = bmp.copy(Bitmap.Config.ARGB_8888, true);

        //draw the Bitmap, unchanged, in the ImageView
        iv_originalImage.setImageBitmap(bmp);

        //Initialize the intArray with the same size as the number of pixels on the image
        intArray = new int[bmp.getWidth()*bmp.getHeight()];

        //copy pixel data from the Bitmap into the 'intArray' array
        bmp.getPixels(intArray, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());

        //replace the red pixels with yellow ones
        for (int i=0; i < intArray.length; i++)
        {
        	if(intArray[i] == 0xFFFF0000)
        	{
        		intArray[i] =  0xFFFFFF00;
        	}
        }

        //Initialize the bitmap, with the replaced color
        bmp = Bitmap.createBitmap(intArray, bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);

        //Draw the bitmap with the replaced color
        iv_imageFromArray.setImageBitmap(bmp);
    }
}

There are a few assumptions made by the above Activity: the first is that a PNG image named ‘four_colors’ is placed at one of the project’s drawable folders. Also, there are two ImageView objects declared at the ‘main.xml‘ file.

That said, at the beginning of the code, two member variables are being declared. They are, respectively, a Bitmap object and an Integer array. The former is the object that the PNG will be decoded into and the latter is the intArray that will hold the pixel information (lines 12 and 15).

Next, there are two ImageView objects being declared (line 18 and 19). Their purpose is to render the image onto the screen. Then, there’s the onCreate() method, which is executed when the BitmapToIntArrayActivity is just created.

At this method, the two ImageView instances are initialized with the data contained at the main.xml file (line 30 and 31). Following that, the bmp object is initialized by the BitmapFactory which decodes the four_colors image (line 34). To avoid headaches regarding the pixel format, the bmp is copied to itself, by calling the copy method which sets it to the ARGB8888 (alpha, red, green, blue, 8 bits per pixel) encoding format (line 36).

Moving on to line 39, the bmp is set to be displayed at the screen using the ImageView named iv_originalImage. Finally, the intArray is initialized with the same length as the number of pixels on the Bitmap (line 42).

Since there’s an array to copy the pixel data into, the getPixels() from the bmp object is called (line 45). It takes seven parameters. The first one is the array where the pixels will be copied to. The second parameter defines the index of the array where the pixel data should start being copied to. The pixels are going to be copied from the beginning, so the argument 0 is being passed. The third parameter defines the number of pixels of each row of the image. The forth and fifth parameters are the X and Y pixel coordinates in the image where the data should start being copied from. The sixth and seven parameters are the number of rows and columns to read from the image.

Now, after the getPixels() method, the pixel color information from the image is going to be stored at a position in the array with four hexadecimal pairs, in the ARGB8888 (alpha, red, green, blue, 8 bits per pixel) format. The first pair is the alpha channel. The second third and forth pairs, are respectively the red, green and blue channels. For example, a pixel with a value of 0XFF0000FF, has an opaque blue color. And a pixel with a value of 0X99FF0000 is a translucent red color.

Case the image just needs to be read as a pixel array, there’s nothing left to be done. However, chances are that some sort of operation or algorithm must be applied to the array of pixels, and the results must be later decoded into the bmp object again. For the above example, a simple for loop tries to find all opaque red pixels (0XFFFF0000). If it does, the red color is replaced by a yellow one (lines 48 through 54). To encode the array into the Bitmap, the static method CreateBitmap() is called, which takes four parameters: the byte array, the width and height of the image, and the pixel format (line 57).

Lastly, the last piece of code inside the OnCreate() method displays this newly initialized bmp object in the screen. This is achieved by calling the setImageBitmap() method from the iv_imageFromArray object, passing the bmp as a parameter (line 60).

Here’s a screenshot of the application:

Bitmap to Integer Array Screenshot

A screenshot of the above Activity.

On a side note: for this example project, one copy of the four_colors image had been added to the three drawable folders (drawable-hdpi, drawable-mdpi, drawable-ldpi). It was necessary because, if the image gets scaled, the color replacement code could add some artifacts on the resulting image, since it’s testing for a specific color.

To avoid that, try to initialize the Bitmap object using a BitmapFactory.Options object with the inScaled flag set to false.

Downloads

2 Comments to “Android: Bitmap to Integer array”

  1. Chiuan says:

    good job! 3q!

  2. Bee says:

    Extremely helpful. Thank you.

Leave a Comment

Post Comments RSS