【问题标题】:Creating Bitmap image from OpenGL ES Framebuffer through JNI on Android NDK在 Android NDK 上通过 JNI 从 OpenGL ES Framebuffer 创建位图图像
【发布时间】:2013-09-29 02:39:18
【问题描述】:

我正在尝试从 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 上使用没有问题,所以我认为问题不在于那里

那么,对我可能遗漏的内容有什么帮助吗?

【问题讨论】:

  • @AndonM.Coleman 我已经记录了所有三个(宽、高和像素)。 W & H 确实与我的屏幕尺寸匹配,并且像素不是空的,也不是全零。我有点难以弄清楚它是否确实是有效的数据,但我猜应该是,因为它只是一个直接的 glReadPixels 调用

标签: android c++ opengl-es android-ndk java-native-interface


【解决方案1】:

你为什么要对glReadPixels (...)返回的数据调用decode?在大多数情况下,数据是原始 RGB[A]; 编码会更有意义。据我所知,这可能是正确的,但对于谷歌来说,调用一个将原始像素缓冲区编码为更专业的像素集合的函数是一件非常愚蠢的事情。

我不得不从直观的角度来想象,decodeByteArray (...) 实际上是要获取一个代表某种标准图像文件格式的字节数组并将其解码为通用位图。

既然如此,就不会是这样的:

Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888); // Yes, ARGB
bm.copyPixelsFromBuffer (pixels);

更有意义?

我不确定 JNI 绑定应该是什么样子,但这会从 RAW 像素数据创建一个位图,而不是尝试解码一开始没有编码的东西。我想当 Android 在前几个字节的数据中找不到可识别的文件签名时,您尝试执行的操作几乎会立即失败。

【讨论】:

  • 很有意义。谢了哥们。我会相应地调整代码
猜你喜欢
  • 1970-01-01
  • 2016-06-07
  • 2011-08-25
  • 1970-01-01
  • 2014-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多