3

I get the pixel data of my ARGB_8888 bitmap by doing this:

public void getImagePixels(byte[] pixels, Bitmap image) {
    // calculate how many bytes our image consists of
    int bytes = image.getByteCount();

    ByteBuffer buffer = ByteBuffer.allocate(bytes); // Create a new buffer
    image.copyPixelsToBuffer(buffer); // Move the byte data to the buffer

    pixels = buffer.array(); // Get the underlying array containing the data.
}

But, I would like to convert this data, in which each pixel is stored on four bytes (ARGB), to where each pixel is stored on 3 bytes (BGR).
Any help is appreciated!

Harald K
  • 26,314
  • 7
  • 65
  • 111

3 Answers3

6

Disclaimer: There could be better/easier/faster ways of doing this, using the Android Bitmap API, but I'm not familiar with it. If you want to go down the direction you started, here's your code modified to convert 4 byte ARGB to 3 byte BGR

public byte[] getImagePixels(Bitmap image) {
    // calculate how many bytes our image consists of
    int bytes = image.getByteCount();

    ByteBuffer buffer = ByteBuffer.allocate(bytes); // Create a new buffer
    image.copyPixelsToBuffer(buffer); // Move the byte data to the buffer

    byte[] temp = buffer.array(); // Get the underlying array containing the data.

    byte[] pixels = new byte[(temp.length / 4) * 3]; // Allocate for 3 byte BGR

    // Copy pixels into place
    for (int i = 0; i < (temp.length / 4); i++) {
       pixels[i * 3] = temp[i * 4 + 3];     // B
       pixels[i * 3 + 1] = temp[i * 4 + 2]; // G
       pixels[i * 3 + 2] = temp[i * 4 + 1]; // R

       // Alpha is discarded
    }

    return pixels;
}
Harald K
  • 26,314
  • 7
  • 65
  • 111
  • It seam to be correct this answer, but in my case I convert a JPEG to ARGB_8888 with BitmapFactory.decodeByteArray and then I convert this ARGB to RGB doing the following: pixels[i * 3] = temp[i * 4 + 2]; // B pixels[i * 3 + 1] = temp[i * 4 + 1]; // G pixels[i * 3 + 2] = temp[i * 4 + 0]; // R Subtracting one position for each channel. – flaviussn Mar 03 '16 at 09:22
  • @Flayn Sound like your data has RGBA order, rather than ARGB. That's odd. – Harald K Mar 03 '16 at 09:32
0

You can try your skills with a powerful library called OpenCV - and it is free. It allows you to change from BGR to RGB and reverse. It also allows you to add or remove the alpha channel ("A").

OpenCV has a dedicated Android version to download here (OpenCV for Android v 2.4.6).

In this library, check out cvtColor() from this documentation, which states the following:

The function can do the following transformations: Transformations within RGB space like adding/removing the alpha channel, reversing the channel order, conversion to/from 16-bit RGB color (R5:G6:B5 or R5:G5:B5), as well as conversion to/from grayscale [...etc]

I have an app in the Google Play store (UnCanny) that uses OpenCV for Android. It took some time to get up to speed, but has tons of features.

MiStr
  • 1,193
  • 10
  • 17
0

With OpenCV library and you getting pixels via different method (see below) you can replace java function with native calls and it is ~4x more fastest:

In summary:

// reading bitmap from java side:
Mat mFrame = Mat(height,width,CV_8UC4,pFrameData).clone();
Mat mout;
cvtColor(mFrame, mout,CV_RGB2GRAY); // or CV_RGB2XXX (3BGR)

Complete example:

Java side:

    Bitmap bitmap = mTextureView.getBitmap(mWidth, mHeight);
    int[] argb = new int[mWidth * mHeight];
    // get ARGB pixels and then proccess it with 8UC4 opencv convertion
    bitmap.getPixels(argb, 0, mWidth, 0, 0, mWidth, mHeight);
    // native method (NDK or CMake)
    processFrame8UC4(argb, mWidth, mHeight);

Native side (NDK):

JNIEXPORT jint JNICALL com_native_detector_Utils_processFrame8UC4
    (JNIEnv *env, jobject object, jint width, jint height, jintArray frame) {

    jint *pFrameData = env->GetIntArrayElements(frame, 0);
    // it is the line:
    Mat mFrame = Mat(height,width,CV_8UC4,pFrameData).clone();
    // the next only is a extra example to gray convertion:
    Mat mout;
    cvtColor(mFrame, mout,CV_RGB2GRAY); // or CV_RGB2XXX
    // your code from here, the next is a example:
    int objects = face_detection(env, mout);
    // release object
    env->ReleaseIntArrayElements(frame, pFrameData, 0);
    return objects;
}
Hpsaturn
  • 2,702
  • 31
  • 38