const int BYTES_PER_RGB_PIX = 3; // byts per pixel /** * Generate a direct RGB {@link ByteBuffer} from a YUV420_888 {@link Image}. */ static ByteBuffer ConvertToRGB(Image yuvImage) { // TODO: Optimize this with renderscript intrinsic. int width = yuvImage.Width; int height = yuvImage.Height; ByteBuffer buf = ByteBuffer.AllocateDirect(BYTES_PER_RGB_PIX * width * height); Image.Plane yPlane = yuvImage.GetPlanes()[0]; Image.Plane uPlane = yuvImage.GetPlanes()[1]; Image.Plane vPlane = yuvImage.GetPlanes()[2]; ByteBuffer yBuf = yPlane.Buffer; ByteBuffer uBuf = uPlane.Buffer; ByteBuffer vBuf = vPlane.Buffer; yBuf.Rewind(); uBuf.Rewind(); vBuf.Rewind(); int yRowStride = yPlane.RowStride; int vRowStride = vPlane.RowStride; int uRowStride = uPlane.RowStride; int yPixStride = yPlane.PixelStride; int vPixStride = vPlane.PixelStride; int uPixStride = uPlane.PixelStride; byte[] yuvPixel = { 0, 0, 0 }; byte[] yFullRow = new byte[yPixStride * (width - 1) + 1]; byte[] uFullRow = new byte[uPixStride * (width / 2 - 1) + 1]; byte[] vFullRow = new byte[vPixStride * (width / 2 - 1) + 1]; byte[] finalRow = new byte[BYTES_PER_RGB_PIX * width]; for (int i = 0; i < height; i++) { int halfH = i / 2; yBuf.Position(yRowStride * i); yBuf.Get(yFullRow); uBuf.Position(uRowStride * halfH); uBuf.Get(uFullRow); vBuf.Position(vRowStride * halfH); vBuf.Get(vFullRow); for (int j = 0; j < width; j++) { int halfW = j / 2; yuvPixel[0] = yFullRow[yPixStride * j]; yuvPixel[1] = uFullRow[uPixStride * halfW]; yuvPixel[2] = vFullRow[vPixStride * halfW]; YuvToRgb(yuvPixel, j * BYTES_PER_RGB_PIX, /*out*/ finalRow); } buf.Put(finalRow); } yBuf.Rewind(); uBuf.Rewind(); vBuf.Rewind(); buf.Rewind(); return(buf); }
private byte[] YUV_420_888_toRGBIntrinsics(Image image) { if (image == null) { return(null); } long starttime = DateTime.Now.Millisecond; int W = image.Width; int H = image.Height; Image.Plane Y = image.GetPlanes()[0]; Image.Plane U = image.GetPlanes()[1]; Image.Plane V = image.GetPlanes()[2]; int Yb = Y.Buffer.Remaining(); int Ub = U.Buffer.Remaining(); int Vb = V.Buffer.Remaining(); byte[] data = new byte[Yb + Ub + Vb]; Y.Buffer.Get(data, 0, Yb); V.Buffer.Get(data, Yb, Vb); U.Buffer.Get(data, Yb + Vb, Ub); // 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(data.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.copyFromUnchecked(data); // // yuvToRgbIntrinsic.setInput(in); // yuvToRgbIntrinsic.forEach(out); // int[] argb = new int[data.length]; // byte[] argb = new byte[image.Width *image.Height * 4 ]; // out.copyTo(argb); Log.Error("wtf", "YUV_420_888_toRGBIntrinsics->" + (DateTime.Now.Millisecond - starttime)); return(data); }