In the Android NDK there is a library named JNI Graphics. What is that? Can I use that to load Images for OpenGL ES with C/C++?
JNI is the Java Native Interface. It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++).
jni/libs folder is where your shared library files are built from the C/C++ sources. Your native code gets compiled and depending on the value you had set in your application.mk file for the parameter APP_ABI: = <all | x86 | armv7a | armeabi-v7 | mips>
JNI is just the way that Java handles calling into native/C++ code, and calling back into Java from there. It has nothing to say about Android - it is a Java language feature. The Android NDK is a way to write Android applications using code called by JNI.
JNIEXPORT is used to make native functions appear in the dynamic table of the built binary (*. so file). They can be set to "hidden" or "default" (more info here). If these functions are not in the dynamic table, JNI will not be able to find the functions to call them so the RegisterNatives call will fail at runtime.
The jnigraphics
library can be used to access bitmap buffers in C/C++ from the android.bitmap.Graphics
class (in Java, of course).
It's briefly mentioned in the NDK documentation, as well as the bitmap.h
header docs.
It can be used to load images for e.g. OpenGL ES in C/C++, but you have to do some work to hand a jobject
to that library so it can give you direct access to a buffer. You can pass that buffer to OpenGL via glTexImage2D()
.
First, you need a Java Bitmap
object, which you can acquire and pass to your native method like this:
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
...
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
R.drawable.myimage, options);
MyJniMethod(bitmap); // Should be static in this example
That native method can look something like this:
#include <android/bitmap.h>
void MyJniMethod(JNIEnv *env, jobject obj, jobject bitmap) {
AndroidBitmapInfo info;
uint32_t *pixels;
int ret;
AndroidBitmap_getInfo(env, bitmap, &info);
if(info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
LOGE("Bitmap format is not RGBA_8888!");
return false;
}
AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void **>(&pixels));
// Now you can use the pixel array 'pixels', which is in RGBA format
}
Keep in mind you should call AndroidBitmap_unlockPixels()
when you are done with the pixel buffer, and that this example doesn't check for errors at all.
Update for Sid Datta's question: You can ensure that the output image format is what you're expecting by adding this to options above:
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
There is one case where the output image will still end up with an unknown format in JNI. This seems to happen only with GIFs. After calling BitmapFactory.decodeResource()
, you can convert the image to the proper format if necessary:
if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
Bitmap reformatted_bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
bitmap.recycle(); /* reduce memory load in app w/o waiting for GC */
bitmap = reformatted_bitmap;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With