【问题标题】:Android- convert ARGB_8888 bitmap to 3BYTE_BGRAndroid- 将 ARGB_8888 位图转换为 3BYTE_BGR
【发布时间】:2013-08-07 20:05:05
【问题描述】:

我通过这样做获得了我的 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.
}

但是,我想将每个像素存储在四个字节 (ARGB) 上的数据转换为每个像素存储在 3 个字节上的数据 (BGR)。
任何帮助表示赞赏!

【问题讨论】:

  • 我不认为pixels = buffer.array() 能达到你的预期。您是要返回像素数组,还是将它们复制到预先分配的像素数组中?
  • "pixels" 是一个预分配的像素数组

标签: java android image bitmap bytebuffer


【解决方案1】:

使用OpenCV 库,您可以通过不同的方法获取像素(见下文),您可以用本机调用替换 java 函数,它的速度~4x 更快

总结:

// 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;
}

【讨论】:

    【解决方案2】:

    免责声明:使用 Android Bitmap 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,执行以下操作:像素 [i * 3] = temp [我 * 4 + 2]; // B 个像素[i * 3 + 1] = temp[i * 4 + 1]; // G 像素[i * 3 + 2] = temp[i * 4 + 0]; // R 每个通道减去一个位置。
    • @Flayn 听起来您的数据具有 RGBA 顺序,而不是 ARGB。这很奇怪。
    【解决方案3】:

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

    OpenCV 有专门的安卓版下载here (OpenCV for Android v 2.4.6)

    在这个库中,查看来自this documentationcvtColor(),它声明如下:

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

    我在 Google Play 商店 (UnCanny) 中有一个使用 OpenCV for Android 的应用程序。上手需要一些时间,但有很多功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 2021-09-18
      • 2013-12-15
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多