在Android NDK中,通过JNI从OpenGL ES Framebuffer创建位图图像

3
我正在尝试从OpenGL ES中捕获帧缓冲数据,并从中创建图像,基本上是为了捕获屏幕截图。 我正试图通过JNI使用BitmapFactory类进行转换。这是我的当前代码:
size_t size = w * h;
uint8_t *pixels = new uint8_t[size];
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
jobject jbitmap = 0;

if(pixels != 0) {
  JNIEnv * env = GetEnv(state_->activity->vm);

  //create the jbyte array and fill in with the pixel data
  int byte_array_length = w * h;
  jbyteArray byte_array = env->NewByteArray(byte_array_length);
  env->SetByteArrayRegion(byte_array, 0, byte_array_length, (jbyte *)pixels);

  //get the BitmapFactory class
  jclass bitmap_factory_class = loadExternalClass("android/graphics/BitmapFactory");
  jmethodID decode_byte_array_method = env->GetStaticMethodID(bitmap_factory_class,
    "decodeByteArray", "([BII)Landroid/graphics/Bitmap;");

  //get the bitmap itself
  jbitmap = env->CallStaticObjectMethod(bitmap_factory_class, decode_byte_array_method,
    byte_array, 0, byte_array_length);

  env->DeleteLocalRef(byte_array);
}

if(jbitmap == 0) {
  Log("Could not create image from framebuffer to share");
}

基本上,代码的目的是:
  • 捕获OpenGL帧缓冲区到像素数组中
  • 创建大小为W * H的jbyteArray
  • 填充jbytearray
  • 获取BitmapFactory类
  • 使用jbytearray调用decodeByteArray方法
然而,jbitmap对象持续设置为0,这让我认为BitmapFactory调用失败了,我不知道为什么。
相同的代码用于将帧缓冲区捕获到像素数组中(即glReadPixels调用),在iOS和MacOSX上没有问题,因此我不认为问题出在那里。
所以,任何关于我可能遗漏的内容的帮助?

最初发布在android-ndk谷歌小组 - codemonkey
@AndonM.Coleman 我已经记录了所有三个参数(w,h和pixels)。W和H确实与我的屏幕尺寸匹配,而pixels不为空且也不全是零。对于我来说有点难以确定里面的数据是否有效,但我猜应该是有效的,因为这只是一个直接的glReadPixels调用。 - codemonkey
1个回答

3
为什么要对glReadPixels (...)返回的数据调用decode方法呢?在大多数情况下,这些数据是原始的RGB[A]格式,更合理的做法应该是进行编码。我不确定这是否正确,但谷歌将一个将原始像素缓冲区编码为更专业像素集合的函数称为“解码”实在是太愚蠢了。
从直觉上来看,decodeByteArray (...)应该是用于将表示某种标准图像文件格式的字节数组解码为通用位图。
既然如此,那么类似以下内容是否更为合适:
Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888); // Yes, ARGB
bm.copyPixelsFromBuffer (pixels);

我不确定这个JNI绑定应该是什么样子的,但它会从原始像素数据创建一个位图,而不是尝试解码一些未被编码的东西。我猜想当Android在数据的前几个字节中找不到可识别的文件标志时,你所尝试的事情几乎立即失败。

非常有道理。谢谢,伙计。我会相应地调整代码。 - codemonkey

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