解决stride引起的相机预览花屏问题
·
介绍
开发者在使用相机服务时,如果仅用于预览流展示,通常使用XComponent组件实现,如果需要获取每帧图像做二次处理(例如获取每帧图像完成二维码识别或人脸识别场景),可以通过ImageReceiver中imageArrival事件监听预览流每帧数据,解析图像内容。在解析图像内容时,如果未考虑stride,直接通过使用width*height读取图像内容去解析图像,会导致相机预览异常,从而出现相机预览花屏的现象。
当开发者获取预览流每帧图像buffer后,若发现图片内容出现花屏堆叠状,出现“相机预览花屏”现象,此时需要排查解析每帧图像,当预览流图像stride与width不一致时,需要对stride进行无效像素处理。
解决方案
开发者使用width,height,stride三个值,处理相机预览流数据。
分两种情况:
- 当stride和width相等时,按宽读取buffer不影响结果;
- 当stride和width不等时,将相机返回的预览流数据即component.byteBuffer中的数据去除掉stride, 此时将component.byteBuffer中的数据去除掉stride,拷贝得到新的dstArr数据进行数据处理,将处理后的dstArr数组buffer,通过width和height直接创建pixelMap, 并存储到全局变量stridePixel中,传给Image送显。
以下为关键示例代码:
function onImageArrival(receiver: image.ImageReceiver): void {
receiver.on('imageArrival', () => {
receiver.readNextImage((err: BusinessError, nextImage: image.Image) => {
if (err || nextImage === undefined) {
Logger.error(TAG, `requestPermissionsFromUser call Failed! error: ${err.code}`);
return;
}
nextImage.getComponent(image.ComponentType.JPEG, async (err, component: image.Component) => {
let width = 1080;
let height = 1080;
let stride = component.rowStride;
Logger.info(TAG, `receiver getComponent width:${width} height:${height} stride:${stride}`);
if (stride === width) {
let pixelMap = await image.createPixelMap(component.byteBuffer, {
size: { height: height, width: width },
srcPixelFormat: image.PixelMapFormat.NV21,
})
AppStorage.setOrCreate('stridePixel', pixelMap);
} else {
const dstBufferSize = width * height * 1.5;
const dstArr = new Uint8Array(dstBufferSize);
for (let j = 0; j < height * 1.5; j++) {
const srcBuf = new Uint8Array(component.byteBuffer, j * stride, width);
dstArr.set(srcBuf, j * width); // Store the width*height data in dstArr.
}
let pixelMap = await image.createPixelMap(dstArr.buffer, {
size: { height: height, width: width },
srcPixelFormat: image.PixelMapFormat.NV21,
})
AppStorage.setOrCreate('stridePixel', pixelMap);
}
nextImage.release();
})
});
})
}
更多推荐
所有评论(0)