2010-07-26 20 views
18

Sto utilizzando l'anteprima della fotocamera dalla fotocamera per provare ad acquisire immagini. Ecco il codice che sto usandoBitmapFactory.decodeByteArray() restituisce NULL

private Camera.PreviewCallback mPrevCallback = new Camera.PreviewCallback() 
{ 
     public void onPreviewFrame(byte[] data, Camera Cam) { 
       Log.d("CombineTestActivity", "Preview started"); 
       Log.d("CombineTestActivity", "Data length = " 
         + data.length); 
       currentprev = BitmapFactory.decodeByteArray(data, 0, 
         data.length); 

       if(currentprev == null) 
        Log.d("CombineTestActivity", "currentprev is null"); 

       Log.d("CombineTestActivity", "Preview Finished"); 

     } 
}; 

la lunghezza dei dati viene sempre otu lo stesso 576000.

Inoltre ho provato a cambiare i parametri della fotocamera in modo l'immagine ritorna formati come differenti. Ecco come appare quando lo faccio.

mCamera = Camera.open(); 
camParam = mCamera.getParameters(); 
camParam.setPreviewFormat(ImageFormat.RGB_565); 
mCamera.setParameters(camParam); 
    mCamera.setPreviewCallback(mPrevCallback); 

Comunque sia quando cambio il formato di anteprima e quando lo lascio come il suo predefinito di NV21, BitmapFactory.decodeByteArray ritorna come nullo. Ho anche provato a cambiare il formato di anteprima in tipo JPEG. Ho anche ottenere una dichiarazione di debug nelle DDMS, questo è ciò che ottengo

"D/skia (14391): --- SkImageDecoder :: fabbrica restituito null"

+0

Sono tornato indietro e ho fatto clic sui segni di spunta t ad alcune delle risposte che ho ottenuto qui. Grazie per le informazioni – RyoxSinfar

+0

Possibile duplicato di [Ottenere frame da Immagine video in Android] (http://stackoverflow.com/questions/1893072/getting-frames-from-video-image-in-android) – Tim

risposta

3

sto cercando di fare la stessa cosa . Sulla base delle discussioni here e here, suona come le persone non hanno avuto la fortuna di ottenere decodeByteArray() per gestire il formato NV21 come di Android 2.1/2.2. Sicuramente non funziona nel mio emulatore o sul mio Droid Incredible, anche se penso che questo chiami il codice nativo in modo che possa funzionare su alcuni telefoni a seconda dei driver?

In alternativa, si può provare a decodificare il NV21 te stesso in Java (vedi link sopra per un esempio), anche se questo è apparentemente troppo lento per essere utile per la maggior parte dei casi. Non ho avuto molta fortuna cercando di ottenere CameraPreview per inviare un formato diverso sia, e mi aspetto che questo sia problematico per cercare di scrivere il codice che è portabile su hardware differente. Se hai scritto i metodi di decodifica NV21 in NDK potresti aumentare un po 'il framerate.

Apparentemente ci sono problemi di stabilità dovuti alle condizioni di gara nel tentativo di processare lo CameraPreview anche se non ho confermato il problema da solo. Penso che potresti evitarlo e ottenere un po 'di framerate usando il metodo di callback dell'anteprima in buffer setPreviewCallbackWithBuffer() aggiunto in Android 2.1/2.2. Questo è stato aggiunto in 2.1 ma è rimasto nascosto fino al 2.2. To use it in 2.1 you need to hack around the hiding.

Alcune persone hanno suggerito di utilizzare MediaRecorder anziché CameraPreview. Purtroppo, MediaRecorder sembra avere ancora meno previsto per ottenere i frame di anteprima di CameraPreview, quindi non posso raccomandare quella rotta.

+0

Utilizzo della decodifica NV21 in il link sopra, sono riuscito ad ottenere i pixel ma con un frame rate di circa 1 frame/10 secondi su un HTC Droid Incredible. Tuttavia, ritengo che il downsampling dei pixel possa ottenere questo frame rate fino a velocità che potrebbero essere utilizzabili per alcune applicazioni. – Chinasaur

37

OK, spero che questo possa essere d'aiuto.

Perlustrato Internet alla ricerca di una soluzione rapida, e ho trovato la cosa perfetta.

Questo funziona come di Android 2,1

Grazie alla off3nsiv3 da this page.

// Convert to JPG 
Size previewSize = camera.getParameters().getPreviewSize(); 
YuvImage yuvimage=new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 80, baos); 
byte[] jdata = baos.toByteArray(); 

// Convert to Bitmap 
Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length); 

Solo una piccola modifica al codice di off3nsiv3 e sei pronto. L'FPS è ancora incredibilmente alto rispetto alla decodifica manuale.

Per il codice precedente, 80 è la qualità jpeg (0 da 100, 100 è il migliore).

+0

Interessante; potresti postare un confronto di framerate? – Chinasaur

+0

Potrei, ma su un LG Optimus C l'FPS era praticamente lo stesso. Su un HTC, l'FPS era lo stesso. Non c'è lag evidente. – Qix

+1

Buono a sapersi; Grazie. Lo proverò. – Chinasaur

1

Aggiornamento dalla mia precedente risposta, ma nota la risposta di Qix, che sembra più semplice

realtà ho avuto risultati decenti con decodifica in puro Java. Fanno da cornice a circa 10-15 fps purché la dimensione dell'anteprima non sia troppo grande. Purtroppo l'aggiornamento di Android 2.3 al mio Droid Inc sembra aver portato via alcune delle opzioni di dimensioni di anteprima più piccole :(. Ho anche provato a farlo in codice nativo che ho tirato da un altro progetto, ma questo era bug e non sembrava più veloce per l'elaborazione relativamente semplice che stavo facendo, quindi non ho perseguire ulteriormente Vedere my Github per la sorgente (sia Java e nativi)

-1

provare come segue:..

public Bitmap stringtoBitmap(String string) { 
    Bitmap bitmap = null; 
    try { 
     YuvImage yuvimage = new YuvImage(base64.getBytes(),ImageFormat.YUY2, 120, 30, null); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     yuvimage.compressToJpeg(new Rect(0, 0, 20, 20), 100, baos); 
     byte[] jdata = baos.toByteArray(); 
     bitmap = BitmapFactory.decodeByteArray(jdata, 0, jdata.length); 
    } catch (Exception e) { 

    } 
    return bitmap; 
} 
+1

Vuoi spiegare il tuo approccio in maggiori dettagli? –

+0

Perché stai ingoiando le eccezioni? Non farlo. – Qix

9

si può provare questo e sta funzionando ...

mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() { 
       @Override 
       public void onPreviewFrame(byte[] data, Camera camera) { 
        Camera.Parameters parameters = camera.getParameters(); 
        int format = parameters.getPreviewFormat(); 
        //YUV formats require more conversion 
        if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) { 
         int w = parameters.getPreviewSize().width; 
         int h = parameters.getPreviewSize().height; 
         // Get the YuV image 
         YuvImage yuv_image = new YuvImage(data, format, w, h, null); 
         // Convert YuV to Jpeg 
         Rect rect = new Rect(0, 0, w, h); 
         ByteArrayOutputStream output_stream = new ByteArrayOutputStream(); 
         yuv_image.compressToJpeg(rect, 100, output_stream); 
         byte[] byt = output_stream.toByteArray(); 
         FileOutputStream outStream = null; 
         try { 
          // Write to SD Card 
          File file = createFileInSDCard(FOLDER_PATH, "Image_"+System.currentTimeMillis()+".jpg"); 
          //Uri uriSavedImage = Uri.fromFile(file); 
          outStream = new FileOutputStream(file); 
          outStream.write(byt); 
          outStream.close(); 
         } catch (FileNotFoundException e) { 
          e.printStackTrace(); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } finally { 
         } 
        } 
       } 
Problemi correlati