使用的FrameLayout时相机preVIEW拉伸相机、FrameLayout、preVIEW

2023-09-08 08:45:14 作者:少年痴货最帅比@

我发现,当我用相机preVIEW显示在一个小范围内 previewFrameLayout ,当我使用的宽高比被拉伸和在的FrameLayout 。这里是我目前使用将相机设置为preVIEW和的FrameLayout大小code:

I have found that the CameraPreview is displayed in a small area when I use the PreviewFrameLayout and is stretched when I use the aspect ratio and the FrameLayout. Here is the code that I currently use to set the Camera Preview and the FrameLayout size:

   private Size getOptimalPreviewSize(Activity currentActivity,
        List<Size> sizes, double targetRatio) {
    // Use a very small tolerance because we want an exact match.
    final double ASPECT_TOLERANCE = 0.001;
    if (sizes == null) return null;

    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    // Because of bugs of overlay and layout, we sometimes will try to
    // layout the viewfinder in the portrait orientation and thus get the
    // wrong size of mSurfaceView. When we change the preview size, the
    // new overlay will be created before the old one closed, which causes
    // an exception. For now, just get the screen size

    Display display = currentActivity.getWindowManager().getDefaultDisplay();

    int targetHeight = Math.min(display.getHeight(), display.getWidth());

    if (targetHeight <= 0) {
        // We don't know the size of SurfaceView, use screen height
        targetHeight = display.getHeight();

    }

    // Try to find an size match aspect ratio and size
    for (Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;

        if (Math.abs(size.height - targetHeight) < minDiff) {

            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    // Cannot find the one match the aspect ratio. This should not happen.
    // Ignore the requirement.
    if (optimalSize == null) {
        Log.w(TAG, "No preview size match the aspect ratio");
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {

                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

//this is what I really want to use:
private Size getDesiredPictureSize(List<Size> supportedSizeList)
{
    //Resolution is widthxheight

    Size result=null;
    final int minArea=500*500;  
    final int maxArea=1000*1000;
    for(Size size:supportedSizeList)
    {
        if(size.width*size.height>minArea && size.width*size.height<maxArea)
        {
            if(result==null)
                result=size;
            else
            {
                int resultArea=result.width*result.height;
                int sizeArea=size.width*size.height;
                if(resultArea<sizeArea)
                {   
                    result=size;
                }   
            }
        }
    }
    return result;
}

//I am just testing with this method:  
private Size getBestPictureSize(List<Size> supportedSizeList)
{
    Size result=null;
    for(Size size:supportedSizeList)
    {
        if(result==null)
            result=size;
            int resultArea=result.width*result.height;
            int sizeArea=size.width*size.height;
            if(resultArea<sizeArea)
                result=size;
    }
    return result;
}

List<Size> supportedPictureSizes=mParameters.getSupportedPictureSizes();
    List<Size> supportedPreviewSizes=mParameters.getSupportedPreviewSizes();

        Log.d(TAG,"Setting picture size");
        mPictureSize=getBestPictureSize(supportedPictureSizes);
        Log.d(TAG,"The Picture Width: "+mPictureSize.width+" The Picture Height: "+mPictureSize.height);

    double targetRatio=(double)mPictureSize.width/mPictureSize.height;
    mPreviewSize=getOptimalPreviewSize(this,supportedPreviewSizes, targetRatio);
    Log.d(TAG, "The Preview Width:"+mPreviewSize.width+" Preview Height: "+mPreviewSize.height);
    double ratio=(double)mPreviewSize.width/mPreviewSize.height;
    Log.d(TAG,"Picture Ratio: "+targetRatio);
    Log.d(TAG, "Preview Ratio: "+ratio);
    int new_width=0, new_height=0;
    if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT)
    {
        if((double)previewFrame.getWidth()/previewFrame.getHeight()<ratio)
        {
            new_width=(int)(Math.round(previewFrame.getHeight()*ratio));
            new_height=getWindowManager().getDefaultDisplay().getHeight();
        }
        else
        {
            new_width=getWindowManager().getDefaultDisplay().getHeight();
            new_height=(int)Math.round((double)new_width/ratio);
        }
      }

 if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE)
    {
        if((double)previewFrame.getWidth()/previewFrame.getHeight()<ratio)
        {
            new_width=(int)(Math.round(previewFrame.getHeight()*ratio));
            new_height=getWindowManager().getDefaultDisplay().getHeight();
        }
        else
        {
            new_width=getWindowManager().getDefaultDisplay().getWidth();
            new_height=(int)Math.round((double)new_width/ratio);
        }
    }


//Should I set the size of the container first???
 mParameters.setPictureSize(mPictureSize.width, mPictureSize.height);
    mParameters.setPreviewSize(mPreviewSize.width,mPreviewSize.height);
    previewFrame.setLayoutParams(new RelativeLayout.LayoutParams(new_width, new_height));  

我发现,使用 previewFrameLayout 从AOSP显示我的CDamera preVIEW在一个盒子里,而不是全屏,我使用$ P的详细信息$ pviewFrameLayout可以在Camera preVIEW没有出现全屏(在框中显示)

I found that using the PreviewFrameLayout from AOSP displayed my CDamera Preview in a box and not full-screen,details of my use of PreviewFrameLayout can be found at Camera Preview does not appear full screen(displayed in a box)

推荐答案

首先,如果你使用的的FrameLayout 在XML主办的 previewFrame ,你也应该调用

First of all, if you use FrameLayout in your xml to host previewFrame, you should also call

previewFrame.setLayoutParams(new FrameLayout.LayoutParams(new_width, new_height));

接下来,你可以看到,无论是getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT或 Configuration.ORIENTATION_LANDSCAPE ,你做同样的计算,所以这个方向是不相关的。

Next, you can see that whether getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE, you do the same calculations, so this orientation is not relevant at all.

最后,你应该设置摄像机方向当屏幕旋转。

Finally, you should set the camera orientation when the screen is rotated.

我相信你可以找到[这里工作示例](http://stackoverflow.com/a/19448369/192373).

I believe that you can find a [working example here] (http://stackoverflow.com/a/19448369/192373).