11 Stimmen

Vorschaubild in Bitmap umwandeln

Ich weiß, dass das Thema schon oft im Forum behandelt wurde, aber ich bekomme es trotzdem nicht hin... Ich möchte Einzelbilder aus der Vorschau in jpeg-Dateien speichern. Es sieht mehr oder weniger (Code ist vereinfacht - ohne zusätzliche Logik, Ausnahme etc) wie folgt aus...

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;

 }

Hier ist eine der Methoden, die ich versucht habe, um Farben zu konvertieren (aus diesem Forum, glaube ich)

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

Das Problem ist, dass das Bild immer wie drei "seltsame grüne Bilder" aussieht... Ich bin ein neuer Benutzer, also kann ich es nicht posten:(

Ich weiß nicht, ob es etwas mit der Größe zu tun hat oder was, aber ich komme nicht weiter... Können Sie mir dabei helfen?

20voto

Tim Punkte 855

Alternativ, wenn Sie DO aus irgendeinem Grund eine Bitmap benötigen und/oder dies tun wollen, ohne ein YUVImage zu erstellen und zu JPEG zu komprimieren, können Sie das praktische RenderScript 'ScriptIntrinsicYuvToRGB' (API 17+) verwenden:

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

public Allocation renderScriptNV21ToRGBA8888(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;
}

12voto

weston Punkte 52445

Das Speichern in ein JPEG ist einfacher als die Konvertierung in eine Bitmap, da der YUV-Dekodierungscode dank der YuvImage Klasse.

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

1voto

sschrass Punkte 6657

Wenn ich mich nicht irre, wollen Sie die Breite und Höhe des zu dekodierenden Bildes, nicht die Breite und Höhe des Vorschaubildes.

1voto

Marko Punkte 121

Um eine Verschlechterung des JPEG-Bildes bei der Ausgabe zu vermeiden (z. B. mit sich überlagernden grünen/roten Flecken), müssen Sie Spülen y schließen FileOutputStream

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

0voto

androdevo Punkte 742

Wie ich herausgefunden habe, waren die von PreviewSize gelesene Breite und Höhe falsch.... Mit anderen Worten: Die Konvertierung ging schief, weil sie auf falschen Werten basierte. Nach der Verwendung einer neuen Art der Einstellung der Vorschau-Einstellungen (von Beispiel deleivered von Google) alles funktioniert gut.

EDITAR:

Entschuldigung für die schnelle Antwort oben und die lange Verzögerung.

Es war vor einiger Zeit und ich kann nicht graben den Code jetzt, aber ich denke, dass ich verwendet:

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

und nahm das erste Element aus der Liste und setzte die Werte mit

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

Ich habe die Breite und Höhe gespeichert und sie zum Transformieren des Bildes verwendet.

Ich weiß nicht, ob es die beste Lösung war, aber es hat funktioniert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X