I am testing performance for managing raster pixels at the JNI level using OpenCv.
Two options:
1. Skip an array of integers, manipulate pixels and write pixels back to the bitmap. [41ms]
2. Skip the entire bitmap. [35ms]
I noticed that it transmits a bitmap about 5 ms faster than it transmits an array of pixels and assigns an array to a bitmap.
The problem is that using option 2, I lose the blue color and get an orange color instead of the blue that I expect. The image is ARGB, and it looks like it's changed to RGBA? What could be the problem?
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) {
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); }
Decision 05/23:
The problem was that when using an array of integers and passing it to the JNI, the byte order changes from ARGB (java) to BGRA (native). It was great for working with pixels. However, passing the actual Bitmap object when blocking the pixels did not change the byte order, so it needed to be changed after changing the pixel data.
cvtColor(mbgra, mbgra, COLOR_BGR2RGBA, 4);