gpt4 book ai didi

java - 相机预览未全屏显示(显示在一个框中)

转载 作者:行者123 更新时间:2023-11-30 11:23:25 25 4
gpt4 key购买 nike

我想使用自定义相机拍摄比预览尺寸小的照片,我听说保持纵横比很重要。我在AOSP ICS中使用了PreviewFrameLayout。 .我发现 SurfaceView 只显示在盒子中 Activity 的中心,并没有填满整个屏幕。

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

并像这样设置预览和图片大小:

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

我使用这里的代码将宽高比设置为图片大小:

    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>

这包含在主相机布局中,如下所示:

  <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

纵横比是倒置的,因为它是纵向的。

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

Camera 显示为一个比 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.

Camera Preview stretched when using FrameLayout 添加了一个问题来解决这个问题

编辑2:

Camera PreviewFrameLayout 几乎完美地工作(它几乎是全屏)...当我将此代码添加到构造函数时,就在 ShutterButton 上方:

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

还存在屏幕显示方向为90的横屏拍照预览等问题...

我发现尽管使用 ExifInterfaceMatrix 修复了 ImagePreviewActivity 中的旋转代码,但在横向和纵向模式下,获得的图像都顺时针旋转了 90 度

Exif 方向始终为 0,我上次修复了这个问题(在设置方向时没有使用 Parameters.setRotation 代码的 PreviewFrameLayout...但它似乎在这里不起作用

最佳答案

我看不到 getOptimalPreviewSize() 在哪里被调用;此外,没有真正的理由将预览大小设置为与屏幕匹配;通常,默认相机预览由制造商选择,以便在屏幕上看起来不错(涉及缩放)。

有了这些,您发布的代码就可以大大简化。如果我理解正确的话,您在 Activity 中固定了 screenOrientation,并希望用相机预览填充整个屏幕,保持宽高比以匹配所需的图片大小。

This simple example , 展示了如何设置预览表面 View 的宽度和高度。如果这对您来说还不够,请随时询问更多详细信息。

关于java - 相机预览未全屏显示(显示在一个框中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21226682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com