我是Android新手,在我的应用程序中,我需要从摄像机接收视频并混合不同帧中的像素。我尝试使用mediaMetaDataRetriever从捕获的视频中获取帧,但是花费的时间太长。现在,我使用ImageReader来获取每个实时帧,创建一个位图并将其放入数组中。这将占用非常多的RAM空间。并且此数组具有三个周期的后续处理也很长。 那么,如何使用Camera2解决此问题?
混合位图数组:
val outputFrames = arrayOfNulls<Bitmap>(1080)
var videoDuration = frames.size
if(videoDuration%2 != 0) videoDuration--
var index = 0
while (index < videoDuration) {
var indexWidth = 1079
while (indexWidth >= 0) {
var indexHeight = 1919
while (indexHeight >= 0) {
if (outputFrames[indexWidth] == null) {
outputFrames[indexWidth] =
Bitmap.createBitmap(videoDuration, 1920, Bitmap.Config.ARGB_8888)
outputFrames[indexWidth]!![index, indexHeight] =
frames[0][indexWidth, indexHeight]
} else outputFrames[indexWidth]!![index, indexHeight] =
frames[0][indexWidth, indexHeight]
//Log.e("frame:", "$indexWidth $indexHeight /${outputFrames[indexWidth]}/")
indexHeight--
}
indexWidth--
}
frames.removeAt(0)
index++
}
我的图片阅读器:
mImageReader = ImageReader.newInstance(mWidth,mHeight, PixelFormat.RGBA_8888,1)
mImageReader.setOnImageAvailableListener(
{ reader ->
val image = reader.acquireLatestImage()
val planes = image.planes
val buffer = planes[0].buffer
val offset = 0
val pixelStride = planes[0].pixelStride
val rowStride = planes[0].rowStride
val rowPadding = rowStride - pixelStride * mWidth
// create bitmap
val bitmap = Bitmap.createBitmap(
mWidth + rowPadding / pixelStride,
mHeight,
Bitmap.Config.ARGB_8888
)
bitmap.copyPixelsFromBuffer(buffer)
image.close()
},
mBackgroundHandler)
答案 0 :(得分:0)
创建位图非常昂贵,并且会降低您的App的运行速度。尝试将您的图片获取为:
mImageReader = ImageReader.newInstance(DISPLAY_WIDTH, DISPLAY_HEIGHT, ImageFormat.YUV_420_888, Runtime.getRuntime().availableProcessors());
然后,您可以使用ScriptIntrinsicYuvToRGB来创建位图,例如:
Image.Plane Y = mImage.getPlanes()[0];
Image.Plane U = mImage.getPlanes()[1];
Image.Plane V = mImage.getPlanes()[2];
int Yb = Y.getBuffer().remaining();
int Ub = U.getBuffer().remaining();
int Vb = V.getBuffer().remaining();
byte[] data = new byte[Yb + Ub + Vb];
Y.getBuffer().get(data, 0, Yb);
V.getBuffer().get(data, Yb, Vb);
U.getBuffer().get(data, Yb + Vb, Ub);
RenderScript rs = RenderScript.create(Main2Activity.this);
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(DISPLAY_WIDTH).setY(DISPLAY_HEIGHT);
Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
final Bitmap bmpout = Bitmap.createBitmap(DISPLAY_WIDTH, DISPLAY_HEIGHT, Bitmap.Config.ARGB_8888);
in.copyFromUnchecked(data);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
out.copyTo(bmpout);
如果在后台线程中使用此代码,它将大大加快所有操作。