I believe some Android & image algorithm developers have encountered this situation like me: they need to do some intensive calculations (such as pixel-by-pixel filtering), but it is obviously unrealistic to write loop code in the java layer to operate pixel-by-pixel, because the Java code runs too slowly, and a very small 240*320 image has 76,800 pixels. If you consider RGB three channels (or ARGB four channels), you must multiply this number by 3/4. Therefore, intensive image calculations are generally implemented using Jni interface and C++. So the question is, how to pass the pixel data in Bitmap from the Java layer to the C++ layer?
Method 1: The previous method
My previous approach was like this, because the Bitmap class does not support directly obtaining pixel data, so I use the copyPixelsToBuffer function to copy the pixel data into a buffer, and then pass the buffer data to the C++ layer for processing. After the processing is completed, I use the copyPixelsFromBuffer function to assign the processed pixel data to the Bitmap object. The disadvantage of this method is that it is necessary to apply an additional memory block that is almost as large as the current image as a buffer, and two additional copy operations are added. Originally, the purpose of using C++ to process pixels was to save time. Now the additional demand has increased the complexity of time and space. It can be seen that this method is not economical.
Method 2: What you do now
In fact, Android's NDK can process Bitmap objects passed from the Java layer to a certain extent, and can pass Bitmap objects to the C++ layer, directly obtain the pixel data pointer in it, and perform further processing. The steps are as follows:
a. Write JNI interface functions
//java interface functionprivate static native int processBitmap(Bitmap bitmap); // Corresponding to C++ functionsJNIEXPORT jint JNICALL Java_com_example_test_nativeprocess_processBitmap (JNIEnv *env, jclass,jobject bmpObj);
b. Add #include<android/> statement
#include<android/>
c. Obtain the pixel data pointer and perform operations
AndroidBitmapInfo bmpInfo={0}; if(AndroidBitmap_getInfo(env,bmpObj,&bmpInfo)<0) {return -1} int* dataFromBmp=NULL; if(AndroidBitmap_lockPixels(env,bmpObj,(void**)&dataFromBmp)) {return -1;}
AndroidBitmap_lockPixels is used to obtain data pointers. The parameter type of the data pointer is (void**), because Bitmap in Android generally stores ARGB format. If you need pixels, you can use int* pointers. If you need a channel, you can use unsigned char*.
d. After the operation is completed, release the pointer
AndroidBitmap_unlockPixels(env,bmpObj);
In this way, no copying operation is required, and the pixel data in the Bitmap can be directly manipulated.
3. Other issues
If you need to create a Bitmap object in the C++ layer and then return to the Java layer, I have not found a specific implementation method for this requirement. If anyone knows, please give me some advice.
The above implementation method of using C++ to process Bitmap objects in Android is all the content I have shared with you. I hope you can give you a reference and I hope you can support me more.