2014-11-02 1 views
0

Я использую прямой буфер Nio для Java, который держит пиксельные данные из растрового изображения и использует его на стороне NDK как текстуру gl. В принципе, я не умею правильно читать пиксели буфера Java nio в вызове gl/C++ gl draw.Android NDK gl с использованием Java nio bytebuffer для текстуры image

Представляется, что Java.ByteBuffer, который заполняется пикселей на стороне Java не совместим с НДК боковой 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 как черный пиксель;

Я понимаю, что фактическое значение байта без знака этого буфера может быть отрицательным - как я могу исправить это. Кроме того, мне нужно будет преобразовать байт [], который представляет собой данные изображения, полученные из битмапа на стороне Java, которые будут использоваться в текстуре стороны NDK после решения этой проблемы.

Заранее благодарен!

+0

Сделайте шестнадцатеричный дамп буфера из вашего собственного кода, чтобы убедиться, что данные на нем фактически добираются. – fadden

ответ

0

Первый «байт» в Java 8 бит (подписанный) не 32 бит. Я не использую nio.ByteBufffer (хотя можно). байт [] массив работает намного лучше и проще.

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

Надеется, что это помогает.

+0

Спасибо за разъяснение 8-го и 32-битного байтов в Java. Если я прослежу образец, который я предоставил, все значения равны -1. Мне нужно передать адрес памяти только для nio-буфера, а не фактические пиксели. Буфер обновляется на стороне java на лету, и мне нужна сторона NDK, чтобы иметь доступ к ней напрямую. Я использую одну и ту же механику для обмена данными со стороны Java (float, int и т. Д.) Очень быстро, но не байт данных изображения. – narkis

+0

Характеристики производительности для байтов [], ByteBuffer и прямого ByteBuffer могут быть разными. См. Http://developer.android.com/training/articles/perf-jni.html#faq_sharing – fadden

+0

1. В реальной жизни байт [] никогда не копируется виртуальной машиной. И nio.ByteBuffer.put() на android очень дорогой относительно [i] = v; (могут быть уменьшены массовыми операциями) 2. В практических проектах я даже не маршал байтов [] массивов. Я делаю malloc() на обратном адресе jni side в виде 64-битного java long и имеет memset, memget, memcpy jni ops для управления данными, открытыми для java-стороны. Память, выделенная malloc(), гарантированно остается на месте (не перемещается GC) и быстро доступна. Вы также можете поделиться этой памятью между процессами. 3. Мои последние измерения показывают, что вызовы java примерно в 15 раз дороже, чем C-вызовы – Leo

Смежные вопросы