问题
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!
回答1:
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;
}
回答2:
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.
回答3:
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;
}
来源:https://stackoverflow.com/questions/18086568/android-convert-argb-8888-bitmap-to-3byte-bgr