2013-08-27 6 views
5

Chciałbym przekazać bitmapę z systemu Android do C++ za pomocą JNI dla systemu Android.Jak przekazać bitmapę z Java do C++ z JNI w Android Development?

W Javie, wzywam tę funkcję, aby wysłać Bitmap z Java do C++:

public native int sendMyBitmap(Bitmap bitmap); 

w JNI, zrobiłem to tak:

JNIEXPORT void JNICALL sendMyBitmap(JNIEnv * env, 
     jobject obj, jobject bitmap) 
{ 
    AndroidBitmapInfo androidBitmapInfo ; 
    void* pixels; 
    AndroidBitmap_getInfo(env, bitmap, &androidBitmapInfo); 
    AndroidBitmap_lockPixels(env, bitmap, &pixels); 
    unsigned char* pixelsChar = (unsigned char*) pixels; 
    saveImage(pixelsChar); 
} 

void saveImage(unsigned char* img) 
{ 
    FILE *f; 
    int w = 640, h = 480; 

    int filesize = 54 + 3*w*h; //w is your image width, h is image height, both int 

    unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0}; 
    unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0}; 
    unsigned char bmppad[3] = {0,0,0}; 

    bmpfileheader[ 2] = (unsigned char)(filesize ); 
    bmpfileheader[ 3] = (unsigned char)(filesize>> 8); 
    bmpfileheader[ 4] = (unsigned char)(filesize>>16); 
    bmpfileheader[ 5] = (unsigned char)(filesize>>24); 

    bmpinfoheader[ 4] = (unsigned char)(  w ); 
    bmpinfoheader[ 5] = (unsigned char)(  w>> 8); 
    bmpinfoheader[ 6] = (unsigned char)(  w>>16); 
    bmpinfoheader[ 7] = (unsigned char)(  w>>24); 
    bmpinfoheader[ 8] = (unsigned char)(  h ); 
    bmpinfoheader[ 9] = (unsigned char)(  h>> 8); 
    bmpinfoheader[10] = (unsigned char)(  h>>16); 
    bmpinfoheader[11] = (unsigned char)(  h>>24); 

    f = fopen("/storage/test.png","wb"); 
    fwrite(bmpfileheader,1,14,f); 
    fwrite(bmpinfoheader,1,40,f); 
    for(int i=0; i<h; i++) 
    { 
     fwrite(img+(w*(h-i-1)*3),3,w,f); 
     fwrite(bmppad,1,(4-(w*3)%4)%4,f); 
    } 
    fflush(f); 
    fclose(f); 
} 

Po zapisaniu bitmapy w C++ JNI, bitmapy w Javie i C++ są różne. Walczę, aby dowiedzieć się, jaki jest problem i jak mogę znaleźć problem.

+0

Proszę opisać oczekiwane wyniki a rzeczywiste wyniki – krsteeve

Odpowiedz

3

Linia:

fwrite(img + (w * (h - i - 1)*3), 3, w, f); 

Jesteś zakładając bitmapy wejściowy posiada 24 ukąszeń (3 bajty) na piksel. Ale nie ma takiego formatu pikseli w systemie Android.

Przyjmuje się również, że szerokość wynosi dokładnie 640 pikseli, a wysokość to dokładnie 480 pikseli. Może to być prawda w twoim przypadku, ale powinieneś przeczytać te informacje, a nie kodować wartości.

Wszystkie te wartości są dostarczane przez funkcję AndroidBitmap_getInfo(). Dlaczego ich nie używasz? Wystarczy sprawdzić strukturę AndroidBitmapInfo:

typedef struct { 
    uint32_t width; 
    uint32_t height; 
    uint32_t stride; 
    int32_t  format; 
    uint32_t flags;  // 0 for now 
} AndroidBitmapInfo; 

można bezpośrednio odczytać wymiary swojej bitmapy. Dodatkowo należy sprawdzić parametr format, który może być jedną z następujących wartości:

enum AndroidBitmapFormat { 
    ANDROID_BITMAP_FORMAT_NONE  = 0, 
    ANDROID_BITMAP_FORMAT_RGBA_8888 = 1, 
    ANDROID_BITMAP_FORMAT_RGB_565 = 4, 
    ANDROID_BITMAP_FORMAT_RGBA_4444 = 7, 
    ANDROID_BITMAP_FORMAT_A_8  = 8, 
}; 

Widzisz? Nie ma formatu RGB_888. Powinieneś upewnić się, że wysyłasz bitmapę z formatu Java co C++ w formacie RGBA_8888 i odpowiednio zmodyfikuj swój algorytm. Myślę, że łatwiej byłoby zmienić wyjściowy format pikseli na 32 bity (zamiast 24 bitów).