Question

I have a grayscale image as a byte array in JNI, and I need to pass it to Android to be displayed on screen. At the moment my code is as follows: I copy the byte array to an int array in JNI, and then I set the pixels of the Bitmap with that array:

JNI side:

jintArray frame = g_env->NewIntArray(frameSize);
int tempFrame[frameSize];
for(int pix = 0; pix < frameSize; pix++){
    //convert every byte to int
    jint greyValue = 0xff000000 | (( byteArray[pix] << 16) & 0xffff0000) | ((byteArray[pix] << 8) & 0xff00ff00) | (byteArray[pix] & 0xff0000ff);
    tempFrame[pix] = greyValue;
}
g_env->SetIntArrayRegion(frame, 0, frameSize, tempFrame);

//return the array setting a variable in java
g_env->SetObjectField(g_o, g_env->GetFieldID(g_class, "mFrame", "[I"), frame);

then, Java side:

//Somewhere in SurfaceView.surfaceCreated method
if(mBitmap == null)
    mBitmap = Bitmap.createBitmap(mImageWidth, mImageHeight, Bitmap.Config.ARGB_8888);

//Somewhere in View.onDraw method
if(mBitmap != null && nativeClass.mFrame != null){
    mBitmap.setPixels(nativeClass.mFrame, 0, mImageWidth, 0, 0, mImageWidth, mImageHeight);

    //Do some operations on the bitmap with mBitmap.setPixel()

    canvas.drawBitmap(mBitmap, srcRect, dstRect, null);
}

I was wondering if there was a way to speedup the process, avoiding to copy the arrays two times (first from jintArray to int[] and then fromo int[] to Bitmap), for example by writing directly in the Bitmap, or by creating a Bitmap in JNI and passing it to Android. (I know that canvas has a drawBitmap method that accepts int[] instead of Bitmap, but that method does not accept Rects for rescaling, so it is not feasible)

Was it helpful?

Solution

Easy way:

Create bitmap in Java code. Pass bitmap ref in native code. Use AndroidBitmap_lockPixels to get pixel values array. Fill the array with data. Call AndroidBitmap_unlockPixels at the end.

Hard way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top