2013-08-27 32 views
5

Tôi muốn chuyển một bitmap từ Android sang C++ bằng cách sử dụng JNI để phát triển Android.Làm cách nào để chuyển một bitmap từ Java sang C++ với JNI trong Phát triển Android?

Trong Java, tôi gọi chức năng này để gửi một Bitmap từ Java đến C++:

public native int sendMyBitmap(Bitmap bitmap); 

trong JNI, tôi đã thực hiện nó như thế này:

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

Sau khi lưu bitmap trong C++ JNI, các bitmap trong Java và trong C++ là khác nhau. Tôi đang đấu tranh để tìm ra vấn đề là gì và tôi có thể tìm ra vấn đề như thế nào.

+0

Vui lòng mô tả kết quả mong đợi so với kết quả thực tế – krsteeve

Trả lời

3

dòng này:

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

Bạn đang giả định BITMAP đầu vào có 24 cắn (3 byte) cho mỗi pixel. Nhưng không có định dạng pixel như vậy trong android.

Bạn cũng giả sử chiều rộng chính xác là 640 pixel và chiều cao chính xác là 480 pixel. Điều này có thể là sự thật trong trường hợp của bạn, nhưng bạn nên đọc thông tin này, không mã hóa các giá trị.

Tất cả các giá trị này được cung cấp bởi hàm AndroidBitmap_getInfo(). Tại sao bạn không sử dụng chúng? Chỉ cần kiểm tra cấu trúc AndroidBitmapInfo:

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

Bạn có thể đọc trực tiếp kích thước của bitmap của mình. Ngoài ra bạn nên kiểm tra các thông số format, mà có thể là một trong các giá trị:

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

Bạn thấy không? Không có định dạng RGB_888. Bạn nên đảm bảo rằng bạn đang gửi bitmap ở định dạng RGBA_8888 pixel từ Java co C++ và sửa đổi thuật toán của bạn cho phù hợp. Tôi nghĩ rằng sẽ dễ dàng hơn để thay đổi định dạng pixel đầu ra thành 32 bit (thay vì 24 bit).

Các vấn đề liên quan