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

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

4

1 回答 1

3

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

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

在这种情况下,不会是这样的:

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

更有意义?

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

于 2013-09-29T03:34:49.807 回答