2014-11-02 2 views
0

비트 맵에서 픽셀 데이터를 보유하고있는 자바 측 다이렉트 nio 버퍼를 사용 중이며 NDK 측에서 gl 텍스처로 사용하고 있습니다. 기본적으로 나는 c/C++ gl 그리기 호출에서 Java nio 버퍼 픽셀을 올바르게 읽을 수 없습니다.안드로이드 NDK gl 텍스처 이미지에 Java nio bytebuffer 사용

이는 자바의 픽셀로 채워지는 Java.ByteBuffer 부호없는 바이트가 필요 NDK 측 GL과 직접 호환되지 않는 것으로 나타나는 자바

그래서 단일 백 화소 (자바 바이트 명백하게 32 비트이다) 측면 :

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 
... // 

은 검은 색 픽셀로 그려집니다.

이 버퍼의 실제 부호없는 바이트 값이 음수 일 수 있다는 것을 알고 있습니다.이를 어떻게 수정해야합니까? 또한 -이 문제를 해결하면 자바 측의 비트 맵에서 파생 된 이미지 데이터 인 byte []를 NDK 측면 텍스처에 사용하도록 변환해야합니다.

미리 감사드립니다.

+0

네이티브 코드에서 버퍼의 16 진 덤프를 수행하여 픽셀 데이터가 실제로 도착하는지 확인하십시오. – fadden

답변

0

Java의 첫 번째 "바이트"는 32 비트가 아니라 8 비트 (부호가있는)입니다. 나는 nio.ByteBufffer를 사용하지 않는다. byte [] 배열이 훨씬 더 간단하고 간단하게 작동합니다. 희망

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

AndroidBitmap.c

에서 AndroidBitmap.java

public class AndroidBitmap { 

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

} 

에서

이 도움이됩니다.

+0

자바 8 비트 32 비트에 대한 설명을 해주셔서 감사합니다. 내가 제공 한 샘플을 추적하면 - 모든 값은 -1입니다. 나는 실제 픽셀이 아닌 nio 버퍼의 메모리 주소 만 전달해야한다. 버퍼는 자바 측에서 즉시 업데이트되며 NDK 측에서 직접 액세스 할 수 있어야합니다. 나는 자바 측 (float, int 등)에서 매우 빠르게 데이터를 공유하기 위해 동일한 메커니즘을 사용하지만 바이트 이미지 데이터는 사용하지 않습니다. – narkis

+0

byte [], ByteBuffer 및 direct ByteBuffer의 성능 특성이 다를 수 있습니다. http://developer.android.com/training/articles/perf-jni.html#faq_sharing – fadden

+0

을 참조하십시오. 1. 실제 환경에서 byte []는 VM에 의해 복사되지 않습니다. Android의 nio.ByteBuffer.put()은 [i] = v와 비교할 때 매우 비쌉니다. (대량 작업으로 완화 될 수 있음) 2. 실용적인 프로젝트에서 바이트 배열을 마샬링하지 않습니다. 내가 64 비트 자바로 jni 측면 반환 주소 malloc() 할 memset, memget, memcpy jni 운영 자바 측면에 노출 된 데이터를 조작 할 수 있습니다. malloc()에 의해 할당 된 메모리는 제자리에 머무르고 (GC에 의해 이동되지 않고) 빠른 액세스가 보장됩니다. 프로세스간에 해당 메모리를 공유 할 수도 있습니다. 3. 최근 측정 결과에 따르면 Java 호출은 C 호출보다 15 배 더 비쌉니다. – Leo