2010-07-26 16 views
18

J'utilise le previewCallback de l'appareil photo pour essayer de saisir des images. Voici le code que je utiliseBitmapFactory.decodeByteArray() renvoie 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 longueur des données vient toujours OTU les mêmes que 576000.

Aussi j'ai essayé de changer les paramètres de l'appareil afin que l'image revient sous différents formats. Voici à quoi ça ressemble quand je fais ça.

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

Toutefois, les deux quand je change le format de prévisualisation et quand je le laisse comme défaut de NV21, BitmapFactory.decodeByteArray revient comme nul. J'ai également essayé de changer le format d'aperçu en type JPEG. J'ai même une déclaration de débogage dans les DDMS, voici ce que je reçois

« D/skia (14391): --- SkImageDecoder :: usine retourné null »

+0

Je suis retourné et j'ai cliqué sur les coches nex t à certaines des réponses que j'ai obtenues ici. Merci pour l'information – RyoxSinfar

+0

duplication possible de [Obtenir des images de l'image vidéo dans Android] (http://stackoverflow.com/questions/1893072/getting-frames-from-video-image-in-android) – Tim

Répondre

3

Je suis en train de faire la même chose . Basé sur les discussions here et here, il semble que les gens n'ont pas eu la chance d'obtenir decodeByteArray() pour gérer le format NV21 à partir d'Android 2.1/2.2. Il ne fonctionne certainement pas dans mon émulateur ou sur mon Droid Incredible, bien que je pense que cela appelle le code natif afin qu'il puisse fonctionner sur certains téléphones en fonction des pilotes? Comme alternative, vous pouvez essayer de décoder le NV21 vous-même en Java (voir le lien ci-dessus pour un exemple), bien que cela soit apparemment trop lent pour être utile dans la plupart des cas. Je n'ai pas eu beaucoup de chance d'essayer d'obtenir CameraPreview pour envoyer un format différent non plus, et je m'attends à ce que cela soit problématique pour essayer d'écrire du code qui soit portable sur différents matériels. Si vous avez écrit les méthodes de décodage NV21 dans NDK, vous pourriez obtenir un peu plus de framerate.

Apparemment, il y a des problèmes de stabilité dus aux conditions de course en essayant de traiter le CameraPreview aussi, bien que je n'ai pas confirmé ce problème moi-même. Je pense que vous pourriez éviter cela et aussi obtenir votre framerate un peu en utilisant la méthode de rappel en mémoire tampon setPreviewCallbackWithBuffer() qui a été ajouté dans Android 2.1/2.2. Cela a été ajouté en 2.1 mais a été laissé caché jusqu'au 2.2. To use it in 2.1 you need to hack around the hiding.

Certaines personnes ont suggéré d'utiliser MediaRecorder au lieu de CameraPreview. Malheureusement, MediaRecorder semble avoir encore moins fourni pour obtenir des images d'aperçu que CameraPreview, donc je ne peux pas recommander cette route.

+0

Utilisation du décodeur NV21 dans le lien ci-dessus, j'ai pu obtenir les pixels mais avec une cadence d'environ 1 image/10 secondes sur un HTC Droid Incredible. Cependant, je crois que le downsampling des pixels peut obtenir cette fréquence d'images à des vitesses qui peuvent être utilisables pour certaines applications. – Chinasaur

37

Très bien, j'espère que cela aidera.

Récuré l'Internet à la recherche d'une solution rapide, et a trouvé la chose parfaite.

Cela fonctionne comme d'Android 2,1

Merci à off3nsiv3 de 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); 

Juste une petite modification du code de off3nsiv3 et vous êtes prêt. Le FPS est toujours incroyablement élevé par rapport au décodage manuel.

Pour le code ci-dessus, le 80 est la qualité jpeg (0 à partir de 100, 100 étant le meilleur).

+0

Intéressant; pourriez-vous poster une comparaison de framerates? – Chinasaur

+0

Je pourrais, mais sur un LG Optimus C le FPS était à peu près la même chose. Sur un HTC, le FPS était le même. Il n'y a pas de décalage notable. – Qix

+1

Bon à savoir; Merci. Je vais essayer. – Chinasaur

1

mise à jour de ma réponse précédente, mais notez la réponse de Qix, qui semble plus simple

J'ai en fait eu des résultats décents avec le décodage en Java. Framerates environ 10-15 fps tant que la taille de l'aperçu n'est pas trop grande. Malheureusement, la mise à jour Android 2.3 à mon Droid Inc semble avoir enlevé quelques-unes des plus petites options de taille de prévisualisation :(J'ai également essayé de le faire en code natif que j'ai tiré d'un autre projet, mais cela ne semblait pas plus rapide pour le traitement relativement simple que je faisais, donc je ne poursuis plus Voir my Github pour la source (Java et natif)

-1

essayer comme suit:..

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

Pourriez-vous expliquer votre approche en plus de détails? –

+0

Pourquoi avalez-vous des exceptions? Ne fais pas ça. – Qix

9

vous pouvez essayer et ça marche ...

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