Android NDK gl使用Java nio bytebuffer作为纹理图像

时间:2014-11-02 22:23:45

标签: android android-ndk opengl-es-2.0

我正在使用Java端直接nio缓冲区,它从位图中保存像素数据,并在NDK侧将其用作gl纹理。基本上我无法在c / c ++ gl绘制调用中正确读取Java nio缓冲区像素。

看起来Java端填充像素的Java.ByteBuffer与NDK端gl不直接兼容,后者需要无符号字节(java字节显然是32位)

Java端的单个白色像素:

int size = 1;
ByteBuffer vv = ByteBuffer.allocateDirect(size_t*4);
vv.order(ByteOrder.nativeOrder());
vv.put((byte)255); // R
vv.put((byte)255); // G
vv.put((byte)255); // B
vv.put((byte)255); // A
vv.position(0);
... //code to send the buffer address to JNI/NDK gl side
... //

将在NDK侧绘制为黑色像素;

我意识到这个缓冲区的实际无符号字节值可能是负数 - 我该如何纠正这个问题。 另外 - 一旦我解决了这个问题,我需要转换byte [],它是从Java端的Bitmap派生的图像数据,用于NDK侧纹理。

提前致谢!

1 个答案:

答案 0 :(得分:0)

Java中的第一个“字节”是8位(有符号)而不是32位。 我不使用nio.ByteBufffer(尽管可以)。 byte []数组工作得更好更简单。

AndroidBitmap.java中的

public class AndroidBitmap {

    public static native void updateBitmap(android.graphics.Bitmap bitmap, byte[] data, int w, int h, int bpp);

}
AndroidBitmap.c中的

jboolean Java_jni_AndroidBitmap_updateBitmap(JNIEnv* env, jobject that, jobject bitmap, jbyteArray data, jint w, jint h, jint bpp) {

    jbyte* a = (*env)->GetByteArrayElements(env, data, NULL);
    jsize  bytes = (*env)->GetArrayLength(env, data);

    AndroidBitmapInfo info = {0};
    int r = AndroidBitmap_getInfo(env, bitmap, &info);
    if (r != 0) {
        // … "AndroidBitmap_getInfo() failed ! error=%d", r
        return false;
    }
    int width = info.width;
    int height = info.height;
    if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888 && info.format != ANDROID_BITMAP_FORMAT_A_8) {
        // "Bitmap format is not RGBA_8888 or A_8"
        return false;
    }
    int bytesPerPixel = info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ? 4 : 1;
    void* pixels = null;
    r = AndroidBitmap_lockPixels(env, bitmap, &pixels);
    if (r != 0) {
        // ..."AndroidBitmap_lockPixels() failed ! error=%d", r
        return false;
    }
    if (w == width && h == height && bytesPerPixel == bpp) {
        memcpy(pixels, a, width * height * bytesPerPixel);
    } else if (bytesPerPixel == 4 && bpp == 1) {
        grayscaleToRGBA(pixels, &info, data, w, h);
    } else {
        assertion(bytesPerPixel == 4 && bpp == 1, "only grayscale -> RGBA is supported bytesPerPixel=%d bpp=%d", bytesPerPixel, bpp);
    }
    AndroidBitmap_unlockPixels(env, bitmap);
    (*env)->ReleaseByteArrayElements(env, data, a, 0);
    return true;
}

希望这会有所帮助。