尝试在 SurfaceView 中设置时拉伸相机预览
Posted
技术标签:
【中文标题】尝试在 SurfaceView 中设置时拉伸相机预览【英文标题】:Camera preview stretched when trying to set in SurfaceView 【发布时间】:2015-01-20 10:34:09 【问题描述】:我正在尝试在 SurfaceView 中设置相机预览 当我在 Surface 中设置相机时,它看起来像拉伸预览。 我该如何解决?
`public class CamActivity extends Activity implements SurfaceHolder.Callback`
``
`Camera camera;`
`SurfaceView surface;`
`SurfaceHolder mholder;`
`Button capture;`
`Bitmap bitmap;`
`public String path = Environment.getDataDirectory().getAbsolutePath() + "/storage/emulated/0/Pictures/Cam";`
@Override
`protected void onCreate(Bundle savedInstanceState) `
``
` super.onCreate(savedInstanceState);`
` setContentView(R.layout.activity_cam);`
` surface=(SurfaceView)findViewById(R.id.camera_view);`
` if(mholder==null)`
` mholder=surface.getHolder();`
` mholder.addCallback(this);`
`mholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);`
`capture=(Button)findViewById(R.id.camera_capture);`
`File mFolder = new File(path);`
`if (!mFolder.exists()) `
` mFolder.mkdir();`
``
`capture.setOnClickListener(new OnClickListener() `
` @SuppressWarnings("deprecation")`
` @Override`
` public void onClick(View v) `
` camera.takePicture(null, null, new PictureCallback()`
` `
@Override
` public void onPictureTaken(byte[] data, Camera camera)`
` `
` Random generator = new Random();`
` int n = 10000;`
` n = generator.nextInt(n);`
` String fname = "Image-"+ n +".jpg";`
` File pictureFile = new File(Environment.getExternalStoragePublicDirectory(`
` Environment.DIRECTORY_PICTURES)+"/", fname);`
` try `
` FileOutputStream fos = new FileOutputStream(pictureFile);`
` bitmap.compress(Bitmap.CompressFormat.JPEG,90, fos);`
` fos.flush();`
` fos.close();`
` catch (FileNotFoundException e) `
`Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show();`
` catch (IOException e) `
`Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG).show();`
` `
` `
` );`
` `
`);`
``
@Override
`public void surfaceCreated(SurfaceHolder holder) `
``
` camera=Camera.open();`
` try`
` `
` camera.setPreviewDisplay(holder);`
` Toast.makeText(getApplicationContext(), path, Toast.LENGTH_LONG).show();`
` `
` catch (IOException exception)`
` `
` camera.release();`
` camera = null;`
` `
``
@Override
`public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) `
``
` camera.startPreview();`
` camera.setDisplayOrientation(90);`
``
@Override
`public void surfaceDestroyed(SurfaceHolder holder)`
`
` camera.stopPreview();`
` camera.release();`
` camera = null;`
``
``
【问题讨论】:
你能把你的代码放上去吗? 您的 Surfaceview 尺寸与视频尺寸不同。要么与宽度成比例地减小高度,要么使用相机按钮使宽度全屏显示,作为其顶部的叠加层。 如何设置相同的尺寸? @Shobhit 普里 检查我的代码#Moradiya Aksh 查看 Grafika 获取一些示例 (github.com/google/grafika)。它展示了使用自定义布局 (AspectFrameLayout
) 来设置 SurfaceView 的大小,并使用视图矩阵而不是布局通过 TextureView 完成相同的事情。
【参考方案1】:
您需要监听 Activity 中的方向变化,并为相机设置正确的方向。
将此方法添加到您的相机活动中:
public void setCameraDisplayOrientation(Activity activity)
if(null == mCamera)
return;
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation)
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
orientation = (info.orientation + degrees) % 360;
orientation = (360 - orientation) % 360; // compensate the mirror
else // back-facing
orientation = (info.orientation - degrees + 360) % 360;
if(null != mCamera)
mCamera.setDisplayOrientation(orientation);
同时添加 OrientationEventListner
mOrientationEventListener = new OrientationEventListener(mApplication,
SensorManager.SENSOR_DELAY_NORMAL)
@Override
public void onOrientationChanged(int orientation)
if ((orientation == ORIENTATION_UNKNOWN) || (mCamera == null))
return;
Camera.Parameters params = mCamera.getParameters();
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT)
rotation = (info.orientation - orientation + 360) % 360;
else
/*
* back-facing camera
*/
rotation = (info.orientation + orientation) % 360;
params.setRotation(rotation);
if(null == mCamera)
return;
mCamera.setParameters(params);
;
活动开始后启用方向监听器 /* * 启动方向监听器 */ if(mOrientationEventListener.canDetectOrientation()) mOrientationEventListener.enable();
在活动的 onConfigurationChanged 和 onResume 回调中,进行如下调用
setCameraDisplayOrientation(Activity 活动)
希望对你有帮助
问候, 虾肉
编辑更新: 请查看此相机示例代码,您的大部分疑问应该得到解决 https://github.com/shrishmv/CameraTest
【讨论】:
如何获取 cameraId ? 请给我答案 查看github项目 从 github 下载并运行示例应用程序。它不应该给出任何错误。将其用作参考并相应地修改您的代码。你能告诉我你到底想做什么吗? 检查这些东西(使用我的示例应用程序作为参考) 1)设置正确的预览大小和图片大小。 IE。首先查询支持的大小并设置适当的大小2)设置相机preivew的布局参数(高度和宽度),即surfaceview等于预览占用集或相同纵横比的大小3)正确设置方向,每当屏幕旋转时或surfaceview 更改 4)如果您的surfaceview 超出屏幕/活动范围,则将父级的布局参数设置为所需的大小,然后设置surfaceview 布局参数。所有这些都在我的示例应用程序中完成。以上是关于尝试在 SurfaceView 中设置时拉伸相机预览的主要内容,如果未能解决你的问题,请参考以下文章
使SurfaceView大于屏幕(将相机预览适配到大于显示的SurfaceView)
使SurfaceView大于屏幕(将相机预览适配到大于显示的SurfaceView)