2011-01-22 3 views
8

Я знаю, что тема была на доске много раз, но я не могу заставить ее работать так или иначе ... Я хочу сохранить кадры просмотра из предварительного просмотра в файлы jpeg. Это выглядит более или менее (код simplified- без дополнительной логики, исключения и т.д.), как это ...Преобразование рамки предварительного просмотра в растровое изображение

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; 

} 

Вот один из методов, я попытался преобразовать цвета (от этой платы я верю)

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

проблема заключается в том, что картина всегда выглядит как три «странных зеленых картин» ... Я AMA нового пользователя, так что я не могу разместить его :(

я не знаю, если это что-то делать с размером или тем, но я застрял ... Ca Ты меня поддерживаешь?

+0

В случае, если это помогает, обсуждается это по адресу http: // stackoverflow.com/questions/12345415/android-decodeyuv420sp-results-in-green-images/26566778 и http://stackoverflow.com/questions/9325861/converting-yuv-rgbimage-processing-yuv-during-onpreviewframe-in-android –

ответ

0

Как я узнал, ширина и высота чтения из PreviewSize были неправильными .... Другими словами, преобразование пошло не так, потому что оно было основано на ложных значениях. После использования нового способа настройки параметров предварительного просмотра (из примера, удаляемого Google) все работает нормально.

EDIT:

Извините за быстрый ответ выше и длительной задержки.

Это было давно, и я не могу копать код сейчас, но я думаю, что я использовал:

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

и взял первый элемент из списка и установите значения с

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

Я сохранил ширину и высоту и использовал его для преобразования изображения.

Он не знает, было ли это лучшее решение, но оно получилось.

+2

Каким был новый способ? –

+0

Какой был другой метод? – Shyam

+0

Это неинформативный ответ – Badal

0

Если я не ошибаюсь, вы хотите, чтобы ширина и высота изображения были декодированы, а не ширина и высота предварительного просмотра.

9

Простое сохранение в jpeg - это более простая задача, чем преобразование в растровое изображение, отсутствие необходимости в этом коде декодирования YUV благодаря классу 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

Во избежание деградированных JPEG изображения на выходе (например, с чередованием зеленых/красных пятен), вам нужно флеш и близкоFileOutputStream

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

С другой стороны, если вам DO по какой-то причине нужно растровое изображение и/или хотите сделать это без создания YUVImage и сжатия в JPEG, вы можете использовать удобный 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

Что такое аргумент «r» в вызове createBitmap? – Nativ

+0

Мое предположение для 'r' - это ширина/высота, которую вы можете получить, вызывая 'camera.getParameters(). GetPreviewSize(). Width' и т. Д. –

Смежные вопросы