2013-12-03 13 views
8

Ho byte[] yuvByteArray (540x360 immagine catturata dalla Camera.PreviewCallback.onPreviewFrame metodo e scaricati in assets/yuv.bin file). Voglio convertire byte[] yuv a byte[] rgba array, utilizzando il seguente codice (in base a LivePreview esempio Android).Come usare ScriptIntrinsicYuvToRGB (conversione di byte [] YUV a byte [] RGBA)

Ma ricevo outBytes array rgba pieno di zeri dopo forEach e copia allocazione out in outBytes. Cosa c'è che non va nel mio codice?


package hellorender;   
import android.app.Activity; 
import android.content.res.AssetManager; 
import android.graphics.Bitmap; 
import android.os.Bundle; 
import android.support.v8.renderscript.Allocation; 
import android.support.v8.renderscript.Element; 
import android.support.v8.renderscript.RenderScript; 
import android.support.v8.renderscript.ScriptIntrinsicYuvToRGB; 
import android.support.v8.renderscript.Type; 
import android.widget.ImageView; 
import hellorender.R; 

import java.io.IOException; 
import java.io.InputStream; 

public class HelloRenderActivity extends Activity { 

    public static final int W = 540; 
    public static final int H = 360; 
    private RenderScript rs; 
    private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     AssetManager assets = getAssets(); 
     byte[] yuvByteArray = new byte[291600]; 
     byte[] outBytes = new byte[W * H * 4]; 

     InputStream is = null; 
     try { 
      is = assets.open("yuv.bin"); 
      System.out.println("read: " + is.read(yuvByteArray)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       is.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     ImageView iv = (ImageView) findViewById(R.id.image); 
     rs = RenderScript.create(this); 
     yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.RGBA_8888(rs)); 


     Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)) 
       .setX(W).setY(H) 
       .setYuvFormat(android.graphics.ImageFormat.NV21); 
     Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT); 


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

     in.copyFrom(yuvByteArray); 

     yuvToRgbIntrinsic.setInput(in); 
     yuvToRgbIntrinsic.forEach(out); 

     out.copyTo(outBytes); 

     Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888); 
     out.copyTo(bmpout); 

     iv.setImageBitmap(bmpout); 
    } 

} 

risposta

10

file di yuv.bin è sicuramente in formato NV21, come si coglie qui http://developer.android.com/reference/android/hardware/Camera.PreviewCallback.html#onPreviewFrame

metodo setYuvFormat è da API di livello 18, l'ho rimosso

Quindi, questo codice funziona bene:

rs = RenderScript.create(this); 
    yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs)); 

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

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

    in.copyFrom(yuvByteArray); 

    yuvToRgbIntrinsic.setInput(in); 
    yuvToRgbIntrinsic.forEach(out); 
+0

contento che sono stati in grado di farlo funzionare. Sfortunatamente, la parte intrinseca e la maggior parte di RenderScript non sono ben documentate, quindi è facile avere cose strane come questa. –

+0

Come si ottiene la matrice di byte RGB convertita? –

+0

Questo è pazzesco veloce rispetto al fatto che la routine sia stata eseguita in puro java !! – slott

0

modificare il tipo di output passato al costruttore di ScriptIntrinsicYubToRGB di essere Element.U8_4 invece di Element.RGBA_8888. È necessario lo stesso per lo Type.Builder utilizzato per creare l'output Allocation.

+0

outBytes piene di zeri ancora. – wilddev

+0

E c'è un incidente Causato da: android.support.v8.renderscript.RSIllegalArgumentException: Allocazione genere è USER, tipo UNSIGNED_8 di 4 byte, bitmap passato era ARGB_8888 dopo 'out.copyTo (bmpout);' – wilddev

+0

Change i '.setYuvFormat' di utilizzare' android.graphics.ImageFormat.YV21' piuttosto che 'android.graphics.ImageFormat.NV21', a meno che il binario non elaborato è multi-piano di YUV. In tal caso utilizzare 'android.graphics.ImageFormat.YUV_420_888'. –

1

La nostra app di test interna utilizza la seguente sequenza per creare l'allocazione YUV.

tb = new Type.Builder(mRS, Element.createPixel(mRS, 
       Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV)); 
    tb.setX(mWidth); 
    tb.setY(mHeight); 
    tb.setYuvFormat(android.graphics.ImageFormat.NV21); 
    mAllocationIn = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT); 

Poi all'interno della callback che nuovi dati YUV è disponibile fare

mAllocationIn.copyFrom(theYuvByteArray); 
1

Utilizzando API18 + wilddev di risposta può essere un po 'migliorata, come si Non tiratevi bisogno di oggetti Type.Builder. fare tutta questa roba nel metodo onCreate():

aIn = Allocation.createSized(rs, Element.U8(rs), H*W*3/2); // what the f**k ? This is 12 bit per pixel, giving the length of the camera data byte array ! 

bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888); // you will need this bitmap for output anyway 

aOut = Allocation.createFromBitmap(rs, bmpout); // tada ! 

// and set the script´s input 
yuvToRgbIntrinsic.setInput(aIn); 

// as pixel data are stored as int (one byte for red, green, blue, alpha), you first need an int[] array 
int rgba[] = new int[w*h]; // the rgba[] array 

Ora è possibile continuare con queste linee o metterli nel metodo onPreviewFrame():

aIn.copyFrom(data); // or aIn.copyFromUnchecked(data); // which is faster and safe for camera data 

yuvToRgbIntrinsic.forEach(aOut); // execute the script 

aOut.copyTo(bmpout); // copy result from aOut to bmpout 

// if you need the rgba-values, do 
bmpout.getPixels(rgba, 0, W, 0, 0, W, H); 

// now you may loop through the rgba[] array and extraxt the r,g,b,a values 
// and put them into a byte[] array(s), BUT this will surely have impact on the performance when doing in Java