I am developing an aplication where I need to read large image files (6000×6000) ,then applying some filtering (like blurring and color effects) and then saving the image.
The filtering library is a 3rd party library that is programmed in Java and take something like this as a input :
/**
* rgbArray : is an Array of pixels
*/
public int[] ImageFiltering(int[] rgbArray,int Width,int Height);
The problem is that if I load the image in memory (6000 x 6000 x 4 = 137.33 MB) android throws OutOfMemory error.
After reading some documentation and knowing that the memory allocated from NDK is not part of the application heap ,I get an interesting idea:
-
Open the image from NDK Read it contents and save it in an array
-
Pass the array back to Java
-
Apply filter to the array data
-
Return the array to NDK
-
Save the data array into a new image and release the array memory
Here is an example of NDK function with returns the big,fat array:
jint*
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,jobject thiz,jint w,jint h)
{
int* pixels = (int*)malloc(w * h * 4);
read_image_into_array("image.jpg",pixels);
return pixels;
}
The goal is to reserve the memory in native in order to avoid getting OutOfMemory error,and pass the memory reference to Java in order to work with it.
Since I am have not C developer and have never touched JNI ,is all this making sense and how could it be implemented in NDK.
Use a direct ByteBuffer, using the allocated memory as its backing buffer. You can allocate a direct byte buffer from JNI (using
NewDirectByteBuffer()) and return it.You’ll need to provide a complementary method for disposing of the memory or otherwise indicating to the native side that it is no longer in use.