2010-07-26 12 views
18

Estoy usando la previewCallback de la cámara para intentar capturar imágenes. Aquí está el código que estoy utilizandoBitmapFactory.decodeByteArray() devuelve 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 longitud de los datos siempre viene OTU lo mismo que 576000.

También he intentado cambiar los parámetros de la cámara para que la imagen se vuelve tan diferentes formatos. Esto es lo que parece cuando hago eso.

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

Sin embargo, tanto cuando se cambia el formato de la vista y cuando lo dejo como su valor predeterminado de NV21, BitmapFactory.decodeByteArray vuelve nula. También intenté cambiar el formato de vista previa al tipo de JPEG. Incluso consigo una declaración de depuración en las DDM, esto es lo que me pasa

"D/skia (14391): --- SkImageDecoder :: fábrica devuelve null"

+0

Volví y hice clic en las marcas de verificación nex a algunas de las respuestas que he obtenido aquí. Gracias por la información – RyoxSinfar

+0

Posible duplicado de [Obtener marcos de la imagen de video en Android] (http://stackoverflow.com/questions/1893072/getting-frames-from-video-image-in-android) – Tim

Respuesta

3

que estoy tratando de hacer lo mismo . Basado en las discusiones here y here, parece que la gente no tuvo suerte al obtener decodeByteArray() para manejar el formato NV21 desde Android 2.1/2.2. Definitivamente no funciona en mi emulador o en mi Droid Incredible, aunque creo que esto llama al código nativo, por lo que puede funcionar en algunos teléfonos dependiendo de los controladores.

Como alternativa, puede intentar decodificar el NV21 usted mismo en Java (consulte el enlace anterior para ver un ejemplo), aunque aparentemente es demasiado lento para ser útil en la mayoría de los casos. No he tenido demasiada suerte tratando de obtener CameraPreview para enviar un formato diferente, y espero que esto sea problemático para tratar de escribir código que sea portable a través de hardware diferente. Si escribiste los métodos de decodificación NV21 en NDK, es posible que obtengas un poco la tasa de fotogramas.

Aparentemente hay problemas de estabilidad debido a las condiciones de carrera al intentar procesar el CameraPreview también, aunque no he confirmado este problema yo mismo. Creo que puede evitar esto y también obtener su framerate un poco utilizando el método de devolución de llamada en memoria intermedia setPreviewCallbackWithBuffer() que se agregó en Android 2.1/2.2. Esto se agregó en 2.1 pero se mantuvo oculto hasta 2.2. To use it in 2.1 you need to hack around the hiding.

Algunas personas han sugerido usar MediaRecorder en lugar de CameraPreview. Desafortunadamente, MediaRecorder parece haber proporcionado menos para obtener marcos de vista previa que CameraPreview, por lo que no puedo recomendar esa ruta.

+0

Usando la decodificación NV21 en el enlace de arriba, pude obtener los píxeles pero con una velocidad de cuadro de aproximadamente 1 fotograma/10 segundos en un HTC Droid Incredible. Sin embargo, creo que la reducción de la resolución de los píxeles puede hacer que esta velocidad de fotogramas alcance velocidades que pueden ser útiles para algunas aplicaciones. – Chinasaur

37

Muy bien, espero que esto ayude.

Busqué en Internet buscando una solución rápida, y encontré la solución perfecta.

Esto funciona como del androide 2,1

Gracias a 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); 

Solo una pequeña modificación al código de off3nsiv3 y listo. El FPS sigue siendo increíblemente alto en comparación con la decodificación manual.

Para el código anterior, el 80 es la calidad jpeg (0 de 100, 100 es el mejor).

+0

Interesante; podrías publicar una comparación de framerates? – Chinasaur

+0

Pude, pero en un LG Optimus C el FPS era prácticamente el mismo. En un HTC, el FPS era el mismo. No hay retraso notable. – Qix

+1

Bueno saber; Gracias. Lo probaré. – Chinasaur

1

actualización de mi respuesta anterior, pero tenga en cuenta la respuesta de Qix, que se parece más simple

De hecho, he tenido resultados aceptables con la decodificación en Java puro. Framera alrededor de 10-15 fps siempre que el tamaño de vista previa no sea demasiado grande. Lamentablemente, la actualización de Android 2.3 a mi Droid Inc parece haber eliminado algunas de las opciones de tamaño de vista previa más pequeñas :(. También traté de hacerlo en código nativo que saqué de otro proyecto, pero esto era un error y no parecía ser más rápido para el procesamiento relativamente simple que estaba haciendo, así que no proseguirla Ver my Github para la fuente (Java y nativo)

-1

probarlo como sigue:..

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

¿Podría explicar su enfoque con más detalles? –

+0

¿Por qué tragas excepciones? No hagas eso. – Qix

9

se puede probar esto y está funcionando ...

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