2011-01-22 21 views
8

Sé que el tema estaba en el tablero muchas veces, pero no puedo hacer que funcione de todos modos ... Quiero guardar marcos de vista desde la vista previa a archivos jpeg. Se parece más o menos (código es simplified- sin lógica adicional, a excepción etc) así ...Conversión de marco de vista previa a mapa de bits

public void onPreviewFrame(byte[] data, Camera camera) { 
    int width = camera.getParameters().getPreviewSize().width; 
    int height = camera.getParameters().getPreviewSize().height; 


    final int[] rgb = decodeYUV420SP(data, width, height); 

    Bitmap bmp = Bitmap.createBitmap(rgb, width, height,Bitmap.Config.ARGB_8888); 

    String filename="/sdcard/file" + (index++)+ ".jpg"; 
    FileOutputStream out; 
    out = new FileOutputStream(filename); 
    bmp.compress(Bitmap.CompressFormat.JPEG, 90, out); 
    out.flush(); 
    out.close(); 
    out=null; 

} 

Aquí es el uno de los métodos i trató de convertir los colores (de este tablero creo)

public int[] decodeYUV420SP(byte[] yuv420sp, int width, int height) { 

    final int frameSize = width * height; 

    int rgb[]=new int[width*height]; 
    for (int j = 0, yp = 0; j < height; j++) { 
     int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; 
     for (int i = 0; i < width; i++, yp++) { 
      int y = (0xff & ((int) yuv420sp[yp])) - 16; 
      if (y < 0) y = 0; 
      if ((i & 1) == 0) { 
       v = (0xff & yuv420sp[uvp++]) - 128; 
       u = (0xff & yuv420sp[uvp++]) - 128; 
      } 

      int y1192 = 1192 * y; 
      int r = (y1192 + 1634 * v); 
      int g = (y1192 - 833 * v - 400 * u); 
      int b = (y1192 + 2066 * u); 

      if (r < 0) r = 0; else if (r > 262143) r = 262143; 
      if (g < 0) g = 0; else if (g > 262143) g = 262143; 
      if (b < 0) b = 0; else if (b > 262143) b = 262143; 

      rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) &  
    0xff00) | ((b >> 10) & 0xff); 


     } 
    } 
    return rgb; 
    } 

el problema es que la imagen siempre se ve como tres imágenes extrañas 'verdes' ... me Ama nuevo usuario, así que no puedo publicarlo :(

no sé si tiene algo que ver con el tamaño o qué, pero estoy atascado ... Ca n me ayudas con eso?

+0

En caso de que ayude, hay un debate sobre esto en http: // stackoverflow.com/questions/12345415/android-decodeyuv420sp-results-in-green-images/26566778 y http://stackoverflow.com/questions/9325861/converting-yuv-rgbimage-processing-yuv-during-onpreviewframe-in-android –

Respuesta

0

como me enteré de que el ancho y alto leídos de PreviewSize eran incorrectos .... En otras palabras, la conversión fue incorrecta porque estaba basada en valores falsos. Después de usar una nueva forma de configurar la vista previa (del ejemplo cedido por google) todo funciona bien.

EDIT:

Lo siento por la respuesta rápida arriba y larga demora.

fue mientras hace y no puedo cavar el código ahora, pero creo que he utilizado:

http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getSupportedPreviewSizes()

y tomó el primer elemento de la lista y establezca los valores con

http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewSize(int, int)

almacené el ancho y alto y lo usé para transformar la imagen.

No sé si fue la mejor solución, pero funcionó.

+2

¿Cuál fue la nueva forma? –

+0

¿Cuál fue el otro método? – Shyam

+0

Esta es una respuesta no informativa – Badal

0

Si no me equivoco, quiere que se descodifiquen el ancho y el alto de la imagen, no el ancho y el alto de la vista previa.

9

Simplemente guardar en un jpeg es una tarea más fácil que la conversión a mapa de bits, sin necesidad de ese código de decodificación YUV gracias a la clase YuvImage.

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(), "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(); 
    } 
} 
0

Con el fin de evitar la imagen JPEG degradada en la salida (por ejemplo, con intercalación de manchas verde/rojo), es necesario ras y cercaFileOutputStream

FileOutputStream filecon = new FileOutputStream(file); 
image.compressToJpeg( 
      new Rect(0, 0, image.getWidth(), image.getHeight()), 90, 
     filecon); 
filecon.flush(); 
filecon.close(); 
12

Alternativamente, si usted DO necesita un mapa de bits por algún motivo, y/o desea hacer esto sin crear un YUVImagema y comprimir a JPEG, puede utilizar el práctico RenderScript 'ScriptIntrinsicYuvToRGB' (API 17+):

@Override 
public void onPreviewFrame(byte[] data, Camera camera) { 
    Bitmap bitmap = Bitmap.createBitmap(r.width(), r.height(), Bitmap.Config.ARGB_8888); 
    Allocation bmData = renderScriptNV21ToRGBA888(
     mContext, 
     r.width(), 
     r.height(), 
     data); 
    bmData.copyTo(bitmap); 
} 

public Allocation renderScriptNV21ToRGBA888(Context context, int width, int height, byte[] nv21) { 
    RenderScript rs = RenderScript.create(context); 
    ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs)); 

    Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length); 
    Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT); 

    Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height); 
    Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT); 

    in.copyFrom(nv21); 

    yuvToRgbIntrinsic.setInput(in); 
    yuvToRgbIntrinsic.forEach(out); 
    return out; 
} 
+1

¿Cuál es el argumento 'r' en la llamada a createBitmap? – Nativ

+0

Supongo que 'r' es el ancho/alto que puede obtener al llamar a 'camera.getParameters(). GetPreviewSize(). Width', etc. –

Cuestiones relacionadas