Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is JNI Graphics or how to use it?

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++?

like image 808
dojordi Avatar asked Apr 09 '11 15:04

dojordi


People also ask

What is JNI and how it works?

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++).

What is JNI libs in Android?

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>

What is NDK and JNI?

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.

What is Jniexport?

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.


1 Answers

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;
}
like image 56
Daniel Schuler Avatar answered Nov 07 '22 22:11

Daniel Schuler