Camera开发时SurfaceView预览界面被拉伸

2019-11-21  本文已影响0人  Allenlll

Camera开发时如果使用的是SurfaceView进行显示,当计算后的Camera预览分辨率比例与SurfaceView宽高比例不一样时,预览时就会被拉伸。

出现的问题

例如:bestPreviewSizeWidthbestPreviewSizeHeight分别是计算后的最合适SurfaceView的预览图宽和高,但它的比例还是和SurfaceView不一样。

 //预览图片大小
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(bestPreviewSizeWidth, bestPreviewSizeHeight);

这时就要对SurfaceView进行缩放,使它的比例和bestPreviewSizeWidthbestPreviewSizeHeight相同。

问题解决

查阅在官方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);
        }
    }
上一篇下一篇

猜你喜欢

热点阅读