2011-03-06 3 views
15

Lorsque vous essayez de convertir le byte[] de Camera.onPreviewFrame-Bitamp en utilisant BitmapFactory.decodeByteArray me donne une erreur SkImageDecoder::Factory returned nullAndroid octet [] à l'image dans Camera.onPreviewFrame

Après mon code:

public void onPreviewFrame(byte[] data, Camera camera) { 
    Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length); 
} 
+0

Meybe il sera utile à quelqu'un. Regardez ma solution ici: http://stackoverflow.com/questions/20298699/onpreviewframe-data-image-to-imageview/34438806#34438806 –

Répondre

3

J'ai trouvé la réponse après un long moment. Ici, c'est ...

Au lieu d'utiliser BitmapFactory, j'ai utilisé ma méthode personnalisée pour décoder ce byte[] data en un format d'image valide. Pour décoder l'image dans un format d'image valide, il est nécessaire de connaître le format d'image utilisé par la caméra en appelant le camera.getParameters().getPictureFormat(). Cela renvoie une constante définie par ImageFormat. Après avoir pris connaissance du format, utilisez l'encodeur approprié pour encoder l'image.

Dans mon cas, le byte[] data était dans le format YUV, donc j'ai cherché YUV-BMP conversion et qui a résolu mon problème.

+0

Pouvez-vous s'il vous plaît me dire comment interrogez-vous le ** camera.getParametrs() * *, comment puis-je vérifier mon format d'image? – Numair

+0

@Numair http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getPictureFormat() –

+0

Il est également possible d'appeler http://developer.android.com/reference/android/hardware/ Camera.Parameters.html # setPreviewFormat (int) mais toutes les caméras ne prennent pas en charge tous les formats. 'NV21' ou' YV12' sont apparemment supportés universellement et la valeur par défaut est 'NV21'. –

31

Cela a été difficile à trouver! Mais depuis l'API 8, il existe une classe YuvImage dans android.graphics. Ce n'est pas un descendant d'image, donc tout ce que vous pouvez faire avec c'est de l'enregistrer en Jpeg, mais vous pouvez l'enregistrer dans un flux mémoire et ensuite charger dans Bitmap Image si c'est ce dont vous avez besoin.

import android.graphics.YuvImage; 

@Override 
public void onPreviewFrame(byte[] data, Camera camera) { 
    try { 
     Camera.Parameters parameters = camera.getParameters(); 
     Size size = parameters.getPreviewSize(); 
     YuvImage image = new YuvImage(data, parameters.getPreviewFormat(), 
       size.width, size.height, null); 
     File file = new File(Environment.getExternalStorageDirectory() 
       .getPath() + "/out.jpg"); 
     FileOutputStream filecon = new FileOutputStream(file); 
     image.compressToJpeg(
       new Rect(0, 0, image.getWidth(), image.getHeight()), 90, 
       filecon); 
    } catch (FileNotFoundException e) { 
     Toast toast = Toast 
       .makeText(getBaseContext(), e.getMessage(), 1000); 
     toast.show(); 
    } 
} 
+1

Ceci est une solution très hacky. Sauvegarde sur un jpeg et décodage immédiat? Je pense que je préfère utiliser une fonction YUV personnalisée. – Timmmm

+1

@Timmmm Je suis d'accord pour dire qu'une fonction YUV personnalisée, qui n'est pas difficile à trouver, serait meilleure que l'enregistrement et le chargement via jpeg. Mais c'est encore mieux si l'enregistrement en jpeg est tout ce que vous voulez faire. Je pense que c'est dommage que YuvImage ne soit pas un descendant de 'Image', alors il n'aurait pas besoin de piratage ou d'auto-codage YUV. – weston

6

Depuis Android 3.0, vous pouvez utiliser un TextureView et TextureSurface pour afficher la caméra, puis utilisez mTextureView.getBitmap() pour récupérer un cadre de prévisualisation RVB convivial.

Un exemple très squelettique de la façon de procéder est donné dans the TextureView docs. Notez que vous devrez définir l'accélération matérielle de votre application ou activité en mettant android:hardwareAccelerated="true" dans le manifeste.

1

vous pouvez essayer ceci: Cet exemple envoyer des cadres de la caméra au serveur

@Override 
     public void onPreviewFrame(byte[] data, Camera camera) { 
     try { 
      byte[] baos = convertYuvToJpeg(data, camera); 
      StringBuilder dataBuilder = new StringBuilder(); 
      dataBuilder.append("data:image/jpeg;base64,").append(Base64.encodeToString(baos, Base64.DEFAULT)); 
      mSocket.emit("newFrame", dataBuilder.toString()); 
     } catch (Exception e) { 
      Log.d("########", "ERROR"); 
     } 
    } 

}; 


public byte[] convertYuvToJpeg(byte[] data, Camera camera) { 

    YuvImage image = new YuvImage(data, ImageFormat.NV21, 
      camera.getParameters().getPreviewSize().width, camera.getParameters().getPreviewSize().height, null); 

    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    int quality = 20; //set quality 
    image.compressToJpeg(new Rect(0, 0, camera.getParameters().getPreviewSize().width, camera.getParameters().getPreviewSize().height), quality, baos);//this line decreases the image quality 


    return baos.toByteArray(); 
}