JNI图形是什么,如何使用它?

11

在Android NDK中有一个名为JNI Graphics的库。那是什么?我可以用它来用C/C++加载OpenGL ES的图像吗?

1个回答

21

jnigraphics库可以用于从Java中的android.bitmap.Graphics类(当然是在Java中)访问C/C++中的位图缓冲区。

它在NDK documentation以及bitmap.hheader docs中简要提到。

它可以用于在C/C++中加载图像,例如OpenGL ES,但您需要做一些工作将jobject传递给该库,以便它可以直接访问缓冲区。您可以通过glTexImage2D()将该缓冲区传递给OpenGL。

首先,您需要一个Java Bitmap对象,您可以获取并像这样将其传递给本机方法:

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

那个本地方法可能看起来像这样:

#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

}

记住,在使用像素缓冲区完成后,应该调用AndroidBitmap_unlockPixels(),而且这个例子根本没有检查错误。


更新 Sid Datta 的问题:您可以通过在上面的选项中添加以下内容来确保输出图像格式符合您的预期:

options.inPreferredConfig = Bitmap.Config.ARGB_8888;

有一种情况是JNI输出图像仍然以未知格式结束。这似乎只会发生在GIF的情况下。调用BitmapFactory.decodeResource()后,如果需要,您可以将图像转换为适当的格式:

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;
}

在所有版本的Android中,Pixel是否保证以RGBA格式打包? - Sid Datta
Java代码是否可以在原生代码锁定Bitmap的情况下读取它? - bk138
1
@bk138 - 是的,这里的锁定确保了Java垃圾回收器不会在没有看到更多的Java引用时释放这个内存。它应该被命名为increaseReferenceCount或类似的名称。 - Daniel Schuler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接