相机preVIEW没有出现全屏(在框中显示) [英] Camera Preview does not appear full screen(displayed in a box)

查看:167
本文介绍了相机preVIEW没有出现全屏(在框中显示)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用一个自定义的相机拍下较小尺寸比preVIEW的照片,我听说保持纵横比是非常important.I已经使用了 previewFrameLayout 在<一个href=\"https://android.googlesource.com/platform/packages/apps/Camera/+/ics-factoryrom-2-release/src/com/android/camera/$p$pviewFrameLayout.java\"相对=nofollow> AOSP ICS 。我发现,SurfaceView只显示在活动的一个盒子的中心,不填充整个屏幕。

I would like to use a custom camera to take pictures of a lesser size than the preview,I have heard that maintaining the aspect ratio is very important.I have used the PreviewFrameLayout in AOSP ICS.I have found that the SurfaceView only displays at the center of the activity in a box and does not fill the entire screen.

public class PreviewFrameLayout extends RelativeLayout{

static final String TAG="PreviewFrameLayout";
public interface OnSizeChangedListener
{
    public void onSizeChanged(int w,int h);
}

OnSizeChangedListener mListener;

public void setOnSizeChangedListener(OnSizeChangedListener listener)
{
    mListener=listener;
}

private double mAspectRatio=4.0/3.0;

public PreviewFrameLayout(Context c,AttributeSet attrs)
{
    super(c,attrs);
}

public void setAspectRatio(double ratio)
{
    if(ratio<=0.0)
        throw new IllegalArgumentException();
    if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT)
        ratio=1/ratio;
    if(mAspectRatio!=ratio)
    {
        mAspectRatio=ratio;
        requestLayout();
    }
}

@Override
protected void onMeasure(int widthSpec,int heightSpec)
{
    int previewWidth=MeasureSpec.getSize(widthSpec);
    int previewHeight=MeasureSpec.getSize(heightSpec);

    int hPadding=getPaddingLeft()+getPaddingRight();
    int vPadding=getPaddingTop()+getPaddingBottom();

    previewWidth-=hPadding;
    previewHeight-=vPadding;

    if(previewWidth>previewHeight*mAspectRatio)
        previewWidth=(int) (previewHeight*mAspectRatio+.5);
    else
        previewHeight=(int)(previewWidth/mAspectRatio+.5);
    previewWidth+=hPadding;
    previewHeight+=vPadding;
    Log.d(TAG,"Aspect ratio "+mAspectRatio);
    Log.d(TAG, "Width: "+previewWidth+" Height: "+previewHeight);
    super.onMeasure(MeasureSpec.makeMeasureSpec(previewWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(previewHeight, MeasureSpec.EXACTLY));
}

protected void onSizeChanged(int w,int h,int oldw,int oldh)
{
    if(mListener!=null)
        mListener.onSizeChanged(w, h);
}
}

和设置了preVIEW和画面尺寸是这样的:

and have set the preview and picture size like this:

  private Size getOptimalPreviewSize(List<Size> supportedSizeList,double targetRatio)
{
    final double ASPECT_TOLERANCE=0.05;
    double minDiff=Double.MAX_VALUE;
    Size optimalSize=null;
    Display display=getWindowManager().getDefaultDisplay();
    @SuppressWarnings("deprecation")
    int targetHeight=Math.min(display.getWidth(), display.getHeight());
    if(targetHeight<=0)
    {   
        WindowManager windowManager=(WindowManager)getSystemService(Context.WINDOW_SERVICE);
        targetHeight=windowManager.getDefaultDisplay().getHeight();
    }
    for(Size size:supportedSizeList)
    {
        double ratio=(double)size.width/size.height;
        if(Math.abs(targetRatio-ratio)>ASPECT_TOLERANCE)
            continue;
        if(Math.abs(size.height-targetHeight)<minDiff)
        {
            optimalSize=size;
            minDiff=Math.abs(size.height-targetHeight);
        }
    }

    for(Size size:supportedSizeList)
    {
        if((Math.abs(size.height-targetHeight))<minDiff)
        {   
            optimalSize=size;
            minDiff=Math.abs(size.height-targetHeight);
        }
    }
    return optimalSize;
}

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

和我用code这里设置宽高比的画面尺寸:

And I used the code here to set the aspect ratio to the picture size:

    mParameters=mCamera.getParameters();
    List<Size> supportedPictureSizes=mParameters.getSupportedPictureSizes();
    List<Size> supportedPreviewSizes=mParameters.getSupportedPreviewSizes();
    mPictureSize=getDesiredPictureSize(supportedPictureSizes);
    double targetRatio=(double)mPictureSize.width/mPictureSize.height;
    mPreviewPanel=findViewById(R.id.frame_layout);
    mPreviewFrameLayout=(PreviewFrameLayout)findViewById(R.id.frame);
    mPreviewFrameLayout.setAspectRatio(targetRatio);

此布局的父母是 RelativeLayout的

<com.example.newcameraproject.PreviewFrameLayout android:id="@+id/frame"
        android:layout_centerInParent="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <SurfaceView android:id="@+id/camera_preview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
      </com.example.newcameraproject.PreviewFrameLayout>

这是包含在主摄像头的布局是这样的:

This is included in the main camera layout like this:

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>

 <include layout="@layout/preview_frame"/>

 </LinearLayout>

修改

纵向

CameraActivity(6502): Resolution Width: 720 Resolution Height: 1184
CameraActivity(6502): The Picture Width: 1152 The Picture Height: 864
CameraActivity(6502): The Preview Width:960 Preview Height: 720
CameraActivity(6502): Picture Ratio: 1.3333333333333333
CameraActivity(6502): Preview Ratio: 1.3333333333333333
PreviewFrameLayout(6502): Left: 0 Right: 0 Top: 0 Bottom: 0
PreviewFrameLayout(6502): Aspect ratio 0.75
PreviewFrameLayout(6502): Width: 720 Height: 960

宽高比被反转,因为它是在纵向

The aspect ratio is inverted because it is in the portrait orientation.

if(getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT)
        ratio=1/ratio;

相机会显示为一个框只是比活动少。

The Camera displays as a box just smaller than the activity.

  CameraActivity(6502): Resolution Width: 1196 Resolution Height: 720
  CameraActivity(6502): The Picture Width: 1152 The Picture Height: 864
  CameraActivity(6502): The Preview Width:960 Preview Height: 720
  CameraActivity(6502): Picture Ratio: 1.3333333333333333
  CameraActivity(6502): Preview Ratio: 1.3333333333333333
  PreviewFrameLayout(6502): Left: 0 Right: 0 Top: 0 Bottom: 0
  PreviewFrameLayout(6502): Aspect ratio 1.3333333333333333
  PreviewFrameLayout(6502): Width: 787 Height: 590

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

修改

1.Ensured that getOptimalPreviewSize and other methods works,changed code outside of this post to do so.
2.Even though these methods now work,the preview was not filling the screen,so changed to FrameLayout.The final version(see above) now works for both landscape and portrait.
3.I have noticed that the image in the preview looks stretched when the Camera Activity is rotated to landscape.

添加一个问题在<一来解决这个href=\"http://stackoverflow.com/questions/21255172/camera-$p$pview-stretched-when-using-framelayout\">Camera当使用preVIEW拉伸的FrameLayout

摄像头previewFrameLayout作品几乎完美的(它几乎是全屏幕)......只是ShutterButton上方,当我加入这个code的构造器:

The Camera PreviewFrameLayout works almost perfectly(it is almost full screen)...just above the ShutterButton when I added this code to the constructor:

 public PreviewFrameLayout(Context c,AttributeSet attrs)
{
    super(c,attrs);
    setAspectRatio(4.0/3.0);
}

有仍然是如服用景观图片所在的屏幕有90和$ P $的pviewing它的显示方向的问题...

There still are problems such as taking a picture in landscape where the screen has a display orientation of 90 and previewing it...

我发现,获得的图像顺时针旋转在风景和肖像模式90度,尽管使用 ExifInterface 矩阵来修复图像previewActivity这种旋转code

I find that the image obtained is rotated 90 degrees clockwise in both landscape and portrait modes despite using the ExifInterface and Matrix to fix this rotation code in ImagePreviewActivity

Exif的方向始终为0,这我确定的最后一次(无设定方向在使用 Parameters.setRotation code中的previewFrameLayout ...但它似乎并没有在这里工作。

The Exif orientation is always 0,I fixed this the last time(without the PreviewFrameLayout using Parameters.setRotation code when setting orientation...but it does not seem to be working here

推荐答案

我看不出其中 getOptimal previewSize()被调用;同时,有没有真正的理由来设置preVIEW尺寸屏幕相匹配;通常情况下,默认的摄像头preVIEW是由制造商选择在屏幕上看起来不错(其中涉及缩放)。

I cannot see where getOptimalPreviewSize() is called; also, there is no real reason to set preview size to match the screen; usually, the default camera preview is chosen by the manufacturer to look good on the screen (which involves scaling).

通过这一切,你发表了code可以显著简化。如果我理解正确的话,你已经在你的活动固定screenOrientation,并要填写所有相机preVIEW,preserving宽高比屏幕匹配所需的图像大小。

With all that, the code you published could be significantly simplified. If I understand correctly, you have fixed screenOrientation in your activity, and want to fill all the screen with camera preview, preserving aspect ratio to match the desired picture size.

这个简单的例子,展示了如何设置宽度和高度为preVIEW表面观。如果这还不够你,随时要求更多的细节。

This simple example, shows how to set width and height for the preview surface view. If this is not enough for you, feel free to ask for more details.

这篇关于相机preVIEW没有出现全屏(在框中显示)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆