美文网首页
Camera开发时SurfaceView预览界面被拉伸

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

作者: Allenlll | 来源:发表于2019-11-21 19:51 被阅读0次

    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);
            }
        }
    

    相关文章

      网友评论

          本文标题:Camera开发时SurfaceView预览界面被拉伸

          本文链接:https://www.haomeiwen.com/subject/gbxxwctx.html