将Android中的ARGB_8888位图转换为3BYTE_BGR

3

我通过以下方式获取我的ARGB_8888位图的像素数据:

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.
}

但是,我想将这些数据转换为每个像素存储在3字节(BGR)的格式,而不是每个像素存储在四个字节(ARGB)的格式。
非常感谢您的帮助!


我认为 pixels = buffer.array() 不会按照你的期望执行。你是想要返回像素数组,还是将它们复制到预先分配的像素数组中? - Harald K
"pixels" 是一个预先分配的像素数组。 - Dylan Milligan
3个回答

6

免责声明:可能有更好/更简单/更快的方法来使用Android位图API进行操作,但我不熟悉。如果您想继续使用您开始的方法,请参考以下修改后的代码以将4字节ARGB转换为3字节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;
}

这个答案似乎是正确的,但在我的情况下,我使用BitmapFactory.decodeByteArray将JPEG转换为ARGB_8888,然后通过以下方式将此ARGB转换为RGB: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每个通道减去一个位置。 - flaviussn
@Flayn 听起来你的数据是RGBA顺序,而不是ARGB。这很奇怪。 - Harald K

0

您可以尝试使用一个强大的库OpenCV来测试您的技能 - 而且它是免费的。它允许您从BGR转换为RGB并反之。它还允许您添加或删除Alpha通道(“A”)。

OpenCV有一个专门的Android版本可以在这里(OpenCV for Android v 2.4.6)下载。

在这个库中,查看此文档中的cvtColor()函数,其中说明如下:

该函数可以执行以下转换:RGB空间内的转换,例如添加/删除Alpha通道,颜色通道顺序的反转,转换为/从16位RGB颜色(R5:G6:B5或R5:G5:B5),以及转换为/从灰度[...等]

我在Google Play商店(UnCanny)上有一个使用OpenCV for Android的应用程序。虽然花了一些时间来学习,但它具有大量的功能。

0

使用OpenCV 库和不同方法获取像素(见下文),您可以用本地调用替换Java函数,速度快~4倍:

总之:

// 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)

完整示例:

Java端:

    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);

本地端(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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接