Cómo utilizar ScriptIntrinsicYuvToRGB (convertir byte yuv a byte rgba)

Tengo byte[] yuvByteArray (540×360 imagen capturada de Camera.PreviewCallback.onPreviewFrame método y se vierte en los assets/yuv.bin archivo assets/yuv.bin ). Quiero convertir byte[] yuv a byte[] rgba array, utilizando el siguiente código (basado en LivePreview android ejemplo).

Pero recibo outBytes rgba array llena de ceros después de forEach y copiando out asignación a outBytes. ¿Qué tiene de malo mi código?


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

Yuv.bin archivo está definitivamente en formato NV21, ya que captura aquí http://developer.android.com/reference/android/hardware/Camera.PreviewCallback.html#onPreviewFrame

El método setYuvFormat es del nivel API 18, lo he eliminado

Así que este código funciona bien:

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

Nuestra aplicación de prueba interna utiliza la siguiente secuencia para crear la asignación 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); 

A continuación, dentro de la devolución de llamada que están disponibles nuevos datos YUV

  mAllocationIn.copyFrom(theYuvByteArray); 

El uso de la respuesta de API18 + wilddev puede mejorarse ligeramente, ya que no necesita los objetos Type.Builder. Haga todo esto en el método 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 

Ahora puede continuar con estas líneas o ponerlas en el método 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 

Cambie el tipo de salida pasado al constructor de ScriptIntrinsicYubToRGB para que sea Element.U8_4 lugar de Element.RGBA_8888 . Necesitará lo mismo para Type.Builder utiliza para crear la Allocation salida.

  • No se puede ejecutar Renderscript HelloCompute ejemplo en Android GB 2.3.5
  • Script de procesamiento de Android
  • ¿Por qué no funciona rsDebug?
  • RenderScript: El uso de ScriptGroup para el proceso de imagen causa rayas horizontales
  • ¿Cuándo deberíamos (realmente) usar RenderScript?
  • Invocación de la función de bloqueo de RenderScript
  • ¿Se puede usar el rsForEach de RenderScript en un kernel no root?
  • Allocation.copyTo (Bitmap) que daña valores de píxeles
  • La adición de Renderscript en el estudio de Android 1.0.1 con API @ 21 y SDKTools @ 21.1.2 causa errores de compilación
  • RenderScript Bound Pointers vs. Asignaciones
  • Lista de dispositivos en los que Renderscript no funciona
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.