我有byte[] yuvByteArray
(从Camera.PreviewCallback.onPreviewFrame
方法捕获540x360图像并转储到assets/yuv.bin
文件中)。我想使用以下代码(基于LivePreview android示例)将byte[] yuv
转换为byte[] rgba
数组。
但是我收到outBytes
rgba数组,在forEach之后填充零,并将out
分配复制到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);
}
}
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);
}
}
答案 0 :(得分:11)
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);
答案 1 :(得分:2)
使用API18 + 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
答案 2 :(得分:1)
我们的内部测试应用程序使用以下序列创建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);
然后在回调中新的YUV数据可用吗
mAllocationIn.copyFrom(theYuvByteArray);
答案 3 :(得分:0)
将传递给ScriptIntrinsicYubToRGB
的构造函数的输出类型更改为Element.U8_4
而不是Element.RGBA_8888
。对于用于创建输出Type.Builder
的{{1}},您需要相同的内容。
答案 4 :(得分:0)
科特琳
val rs = RenderScript.create(CONTEXT_HERE)
val yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs))
val yuvType = Type.Builder(rs, Element.U8(rs)).setX(byteArray.size)
val inData = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT)
val rgbaType = Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height)
val outData = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT)
inData.copyFrom(byteArray)
yuvToRgbIntrinsic.setInput(inData)
yuvToRgbIntrinsic.forEach(outData)
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
outData.copyTo(bitmap)