首页 文章

使用OpenCv蓝色的NDK位图操作是橙色的吗?

提问于
浏览
4

我正在测试使用OpenCv操作JNI层上的位图像素的性能 .

Two options:
1.传递整数数组,操纵像素并将像素写回Bitmap . [41ms]
2.传递整个位图 . [35MS]

我注意到,传递Bitmap比传递像素数组并将数组分配给Bitmap快约5ms .

问题是使用选项2我失去了蓝色并获得橙色代替我期待的蓝色 . 图像是ARGB,它似乎改为RGBA?可能是什么问题?

Method 1:
Java的

Bitmap out = Bitmap.createBitmap(width, height, Config.ARGB_8888);

int[] rgba = new int[width*height];

mSmasher.loadImage(imagePath, rgba, 0);

out.setPixels(rgba, 0, width, 0, 0, width, height);

JNI

JNIEXPORT void JNICALL Java_com_vblast_smasher_Smasher_loadImage
    (JNIEnv *pEnv, jobject obj, jstring jFilePath, jintArray jbgra, jint options)
{
    jint*  _bgra = pEnv->GetIntArrayElements(jbgra, 0);
    const char *filePath = pEnv->GetStringUTFChars(jFilePath, 0);

    if (NULL != filePath)
    {
        // init our output image
        Mat bgra(outputHeight, outputWidth, CV_8UC4, (unsigned char *)_bgra);

                // bgra image manipulations
    }

    pEnv->ReleaseIntArrayElements(jbgra, _bgra, 0);
    pEnv->ReleaseStringUTFChars(jFilePath, filePath);
}

Method 2:

JNIEXPORT void JNICALL Java_com_vblast_smasher_Smasher_getLayersBitmap
    (JNIEnv *pEnv, jobject obj, jobject bitmap)
{
    int ret;
    AndroidBitmapInfo  info;
    void*              pixels = 0;

    if ((ret = AndroidBitmap_getInfo(pEnv, bitmap, &info)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }

    if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888 )
    {
        LOGE("Bitmap format is not RGBA_8888!");
        return;
    }

    if ((ret = AndroidBitmap_lockPixels(pEnv, bitmap, &pixels)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    // init our output image
    Mat mbgra(info.height, info.width, CV_8UC4, pixels);

    mLayers[0].copyTo(mbgra);

    AndroidBitmap_unlockPixels(pEnv, bitmap);
}

Solution 05/23:
问题是当使用整数数组并将其传递给JNI时,字节顺序从ARGB(java)更改为BGRA(本机) . 这对于处理像素来说很好 . 但是,在锁定像素时传递实际的Bitmap对象,字节顺序没有改变,所以在修改像素数据后需要更改它 .

cvtColor(mbgra, mbgra, COLOR_BGR2RGBA, 4);

2 回答

  • 1

    Opencv订单是BGR而不是RGB . 我猜猜A是在正确的位置(或者你会看到半透明的图像),但蓝色和红色会互换 .

  • 3

    在JNI中,颜色值作为ARGB返回,而在JAVA中它是RGBA试试这个

    alpha = (int) ((color & 0xFF000000) >> 24);
        blue = (int) ((color & 0xFF0000) >> 16);
        green = (int)((color & 0x00FF00) >> 8);
        red = (int) (color & 0x0000FF);
        blue = blue * alpha / 255;
        green = green * alpha / 255;
        red = red * alpha / 255;
    
        int tmp = 0;
        tmp = red;
        red = blue;
        blue = tmp;
    
        color =  ((alpha<< 24) & 0xFF000000) | ((blue<< 16) & 0xFF0000) |
                      ((green << 8) & 0x00FF00) |
                      (red & 0x0000FF);
    

相关问题