2015-04-20 6 views
5

Sto provando a caricare un array di byte contenente i dati di un file bitmap a 24 bit in un oggetto Bitmap in Android, ma ho problemi dal Bitmap supporta solo i formati a 32 e 16 bit. Ecco cosa mi è venuta al fine di convertire i dati a 24 bit in 32 bit:Caricare correttamente i dati bitmap a 24 bit in un oggetto bitmap a 32 bit

byte[] file = new byte[is.available()]; 
is.read(file); 
is.close(); 
byte[] paddedFile = new byte[file.length + file.length/3]; //we will be adding 1 more byte (alpha value) for each RGB triplet 
for (int i = 0; i < file.length/3; i++) { 
    paddedFile[i * 4] = file[i * 3]; 
    paddedFile[i * 4 + 1] = file[i * 3 + 1]; 
    paddedFile[i * 4 + 2] = file[i * 3 + 2]; 
    paddedFile[i * 4 + 3] = -1; //manually added alpha channel 
} 
Bitmap screen = Bitmap.createBitmap(479, 616, Bitmap.Config.ARGB_8888); //exact dimensions of the 24-bit bitmap file 
screen.copyPixelsFromBuffer(ByteBuffer.wrap(paddedFile)); 
iv.setImageBitmap(screen); 

E 'sorta di/quasi funziona. Ecco la bitmap con cui sto lavorando:

bmp

ed ecco cosa si presenta dopo il codice di cui sopra:

paddedbmp

Perché è distorto? Qualsiasi vantaggio su come risolvere questo problema è molto apprezzato.

+0

mostrare l'immagine si prega di – CoderNeji

+0

ho provate ad aggiungere il valore alfa per paddedFile [i * 4] prima ma ho preso dei colori strani. Infatti, ho provato i valori -1/0/1 per paddedFile [i * 4] e paddedFile [i * 4 + 3] individualmente, e la combinazione che ho postato nella mia domanda sembra la più ragionevole. – user1112789

+1

Sembra che ogni linea di scansione (del file) sia riempita. Se il file è un BMP, viene riempito al limite di 4 byte (32 bit) più vicino. Prova a utilizzare uno dei metodi 'createBitmap' che accetta un parametro' stride'. – haraldK

risposta

2

Se ho ragione circa l'imbottitura, si dovrebbe essere in grado di fare questo:

int w = 479; 
int h = 616; 

byte[] file = /* as before */; 

// Convert interleaved byte RGB to packed int ARGB 
int[] paddedFile = new int[file.length/3]; 
for (int i = 0; i < file.length/3; i++) { 
    paddedFile[i] = 0xff << 24 // Alpha (all opaque) 
        | ((file[i * 3] & 0xff) << 16) 
        | ((file[i * 3 + 1] & 0xff) << 8) 
        | ((file[i * 3 + 2] & 0xff)) 
} 

int stride = w + (w % 4 == 0 ? 0 : 4 - (w % 4)); 
Bitmap screen = Bitmap.createBitmap(paddedFile, 0, stride, w, h, Bitmap.Config.ARGB_8888); 
+1

Incredibile quanto più breve è stato fatto per essere comparato a quello che mi è venuto in mente proprio come 10 minuti fa! Fondamentalmente mi sono perso in una serie di ricerche e calcoli di passi/pad di bitmap dopo il tuo commento iniziale. Pubblicherò anche quello che ho, solo per completezza. Inoltre, usando 'Bitmap screen = Bitmap.createBitmap (paddedFile, 0, stride, w, h, Bitmap.Config.ARGB_8888)' è più breve, non richiede il livello API 17 e ulteriori definizioni delle metriche. Ottima risposta, grazie. – user1112789

+0

@ user1112789: risolto il problema come suggerito. – haraldK

0

Dopo il commento di haraldK, ho atterrato sul Wikipedia page per quanto riguarda il formato bitmap in cui ho imparato che una l'array di byte bitmap è fondamentalmente row * height. La quantità di byte una riga contiene viene calcolata con la seguente formula:

int paddedRow = (int) Math.floor((24 * w + 31)/32) * 4; //1440 bytes 

Considerando questo è un bitmap 24 bit (3 byte), la quantità effettiva di dati per riga è:

int actualRow = 3 * w; //1437 bytes 

quindi la quantità di imbottitura per riga è:

int padding = paddedRow - actualRow; //3 bytes 

Questo significa ogni ultimi 3 byte di righe 1440 sono imbottitura (ci sono 616 di loro). Conoscendo questi valori, siamo in grado di estrarre i dati del colore vero dal array di byte, quindi accodare correttamente il canale alfa in seguito:

byte[] file = new byte[is.available()]; 
is.read(file); 
is.close(); 
int w = 479; 
int h = 616; 
int paddedRow = (int) Math.floor((24 * w + 31)/32) * 4; 
int actualRow = 3 * w; 
int padding = paddedRow - actualRow; 
byte[] removedPadding = new byte[file.length - padding * h]; 

for (int j = 0, k = 0; j < h; j++) { 
    int tmp = j * paddedRow; 
    for (int i = 0 + tmp; i < actualRow + tmp; i++, k++) { 
     removedPadding[k] = file[i]; 
    } 
} 

byte[] rgbaFile = new byte[removedPadding.length + removedPadding.length/3]; 
for (int i = 0; i < removedPadding.length/3; i++) { 
    rgbaFile[i * 4] = removedPadding[i * 3]; 
    rgbaFile[i * 4 + 1] = removedPadding[i * 3 + 1]; 
    rgbaFile[i * 4 + 2] = removedPadding[i * 3 + 2]; 
    rgbaFile[i * 4 + 3] = -1; 
} 

Bitmap screen = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
screen.copyPixelsFromBuffer(ByteBuffer.wrap(rgbaFile)); 
iv.setImageBitmap(screen);