Camera开发时SurfaceView预览界面被拉伸
2019-11-21 本文已影响0人
Allenlll
Camera开发时如果使用的是SurfaceView进行显示,当计算后的Camera预览分辨率比例与SurfaceView宽高比例不一样时,预览时就会被拉伸。
出现的问题
例如:bestPreviewSizeWidth
和bestPreviewSizeHeight
分别是计算后的最合适SurfaceView的预览图宽和高,但它的比例还是和SurfaceView不一样。
//预览图片大小
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(bestPreviewSizeWidth, bestPreviewSizeHeight);
这时就要对SurfaceView进行缩放,使它的比例和bestPreviewSizeWidth
和bestPreviewSizeHeight
相同。
问题解决
查阅在官方demo中有如下代码,计算了一个Matrix
,然后调用textureView.setTransform(matrix)
对textureView
进行了缩放,使其比例和预览图bufferRatio
比例相同。
/** Helper function that fits a camera preview into the given [TextureView] */
private fun updateTransform(textureView: TextureView?, rotation: Int?, newBufferDimens: Size,
newViewFinderDimens: Size) {
// Buffers are rotated relative to the device's 'natural' orientation: swap width and height
val bufferRatio = bufferDimens.height / bufferDimens.width.toFloat()
val scaledWidth: Int
val scaledHeight: Int
// Match longest sides together -- i.e. apply center-crop transformation
if (viewFinderDimens.width > viewFinderDimens.height) {
scaledHeight = viewFinderDimens.width
scaledWidth = (viewFinderDimens.width * bufferRatio).roundToInt()
} else {
scaledHeight = viewFinderDimens.height
scaledWidth = (viewFinderDimens.height * bufferRatio).roundToInt()
}
// Compute the relative scale value
val xScale = scaledWidth / viewFinderDimens.width.toFloat()
val yScale = scaledHeight / viewFinderDimens.height.toFloat()
// Scale input buffers to fill the view finder
matrix.preScale(xScale, yScale, centerX, centerY)
// Finally, apply transformations to our TextureView
textureView.setTransform(matrix)
SurfaceView解决方法
官方demo使用的是最新的CameraX api
,预览使用的是TextureView
。如果使用的是SurfaceView
应该怎么解决呢?
在计算完最优的预览宽高后,发现比例还是不对时,可以利用计算后的宽高调用如下方法。
private void setAspectRatio(int width, int height) {
previewWidth = width;
previewHeight = height;
requestLayout();
}
然后在onMeasure中计算同比例的宽高,后调用setMeasuredDimension(width, height);
为SurfaceView重新定义宽高。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = View.MeasureSpec.getSize(heightMeasureSpec);
if (previewWidth == 0 || previewHeight == 0) {
LogUtil.d(TAG,"onMeasure zero:");
return;
}
LogUtil.d(TAG,"onMeasure ajust1:"+width+":"+height);
float bufferRatio = previewHeight / (float)previewWidth;//1080/1902=0.9
if(previewWidth*previewHeight<width*height){
width = (int)(height * bufferRatio);
setMeasuredDimension(width, height);
LogUtil.d(TAG,"onMeasure ajust2:"+width+":"+height);
LogUtil.d(TAG,"onMeasure ajust3:"+previewWidth+":"+previewHeight);
}
}