如何使用ScriptIntrinsicYuvToRGB(将byte yuv转换为byte rgba)

我有byte[] yuvByteArray (从Camera.PreviewCallback.onPreviewFrame方法捕获540×360图像,并转储到assets/yuv.bin文件)。 我想使用下面的代码(基于LivePreview android示例)将byte[] yuv转换为byte[] rgba数组。

但是我在forEach之后收到了outBytes rgba数组,填充为零,并将分配拷贝到outBytes。 我的代码有什么问题?


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

Solutions Collecting From Web of "如何使用ScriptIntrinsicYuvToRGB(将byte yuv转换为byte rgba)"

yuv.bin文件绝对是NV21格式,因为它捕获在这里http://developer.android.com/reference/android/hardware/Camera.PreviewCallback.html#onPreviewFrame

setYuvFormat方法是从API级别18,我删除它

所以这段代码工作正常:

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

我们的内部testing应用程序使用以下顺序创buildYUV分配。

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

然后在新的YUV数据可用的callback里面做

  mAllocationIn.copyFrom(theYuvByteArray); 

使用API​​18 + wilddev的答案可以稍微改进,因为你不需要Type.Builder对象。 在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 

现在你可以继续这些行, 或者把它们放到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 

将传递给ScriptIntrinsicYubToRGB的构造函数的输出types更改为Element.U8_4而不是Element.RGBA_8888 。 您将需要用于创build输出AllocationType.Builder相同。