CameraView 中的人像模式
Posted
技术标签:
【中文标题】CameraView 中的人像模式【英文标题】:Portrait mode in CameraView 【发布时间】:2013-08-31 21:28:42 【问题描述】:我将使用 BeyondAR 框架开发一个 android 应用程序。我尝试在屏幕的前半部分使用 CameraView 组件(应用程序仅在纵向模式下运行),但是当我将相机旋转 90 度时,图像拉伸并且纵横比错误。有帮助吗?
CameraView 类(Beyondar 框架)
public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
Camera.PictureCallback
/**
*
* @author Joan Puig Sanz (joanpuigsanz@gmail.com)
*
*/
public static interface IPictureCallback
/**
* This method is called when the snapshot of the camera is ready. If
* there is an error, the image will be null
*
* @param picture
*/
void onPictureTaken(Bitmap picture);
private SurfaceHolder mHolder;
private Camera mCamera;
private IPictureCallback mCameraCallback;
private BitmapFactory.Options mOptions;
private Size mPreviewSize;
private List<Size> mSupportedPreviewSizes;
private List<String> mSupportedFlashModes;
public CameraView(Context context)
super(context);
init(context);
public CameraView(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
init(context);
public CameraView(Context context, AttributeSet attrs)
super(context, attrs);
init(context);
private void init(Context context)
mHolder = getHolder();
mHolder.addCallback(this);
try
mCamera = Camera.open();
//mCamera.setDisplayOrientation(90);
//Camera.Parameters params = mCamera.getParameters();
//params.setPreviewSize(427, 1240);
//mCamera.setParameters(params);
setCamera(mCamera);
catch (Exception e)
Log.e(Constants.TAG, "ERROR: Unable to open the camera", e);
if (android.os.Build.VERSION.SDK_INT <= 10) // Android 2.3.x or lower
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
public void setCamera(Camera camera)
mCamera = camera;
if (mCamera != null)
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes();
// Set the camera to Auto Flash mode.
if (mSupportedFlashModes != null
&& mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO))
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
//parameters.setPreviewSize(300, 200);
mCamera.setParameters(parameters);
public void setSupportedPreviewSizes(List<Size> supportedPreviewSizes)
mSupportedPreviewSizes = supportedPreviewSizes;
public Size getPreviewSize()
return mPreviewSize;
public void surfaceCreated(SurfaceHolder holder)
// The Surface has been created, acquire the camera and tell it where
// to draw.
try
if (mCamera == null)
init(getContext());
if (mCamera == null)
return;
mCamera.setPreviewDisplay(holder);
catch (IOException exception)
if (mCamera != null)
mCamera.release();
mCamera = null;
Log.e(Constants.TAG, "CameraView -- ERROR en SurfaceCreated", exception);
public void surfaceDestroyed(SurfaceHolder holder)
// Surface will be destroyed when we return, so stop the preview.
// Because the CameraDevice object is not a shared resource, it's very
// important to release it when the activity is paused.
if (mCamera == null)
return;
mCamera.stopPreview();
mCamera.release();
mCamera = null;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null)
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
private Size getOptimalPreviewSize(List<Size> sizes, int width, int height)
Size result = null;
for (Camera.Size size : sizes)
if (size.width <= width && size.height <= height)
if (result == null)
result = size;
else
int resultArea = result.width * result.height;
int newArea = size.width * size.height;
if (newArea > resultArea)
result = size;
return result;
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
if (mCamera == null || getPreviewSize() == null)
return;
Camera.Parameters parameters = mCamera.getParameters();
Size previewSize = getPreviewSize();
parameters.setPreviewSize(previewSize.width, previewSize.height);
mCamera.setParameters(parameters);
previewCamera();
@Override
public void onPictureTaken(byte[] imageData, Camera camera)
if (imageData != null && mCameraCallback != null)
mCameraCallback.onPictureTaken(StoreByteImage(imageData));
previewCamera();
public void previewCamera()
if (mCamera == null)
return;
try
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
catch (Exception e)
Log.d(Constants.TAG, "Cannot start preview.", e);
private Bitmap StoreByteImage(byte[] imageData)
Bitmap myImage = DebugBitmap.decodeByteArray(imageData, 0, imageData.length, mOptions);
imageData = null;
System.gc();
return myImage;
public void tackePicture(IPictureCallback cameraCallback)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
tackePicture(cameraCallback, options);
public void tackePicture(IPictureCallback cameraCallback, BitmapFactory.Options options)
if (mCamera == null)
return;
mCameraCallback = cameraCallback;
mCamera.takePicture(null, this, this);
mOptions = options;
编辑
MyLayout xml 文件
<LinearLayout
android:layout_
android:layout_
android:layout_weight="1"
android:orientation="horizontal"
android:paddingBottom="@dimen/padding"
android:paddingLeft="@dimen/padding"
android:paddingRight="@dimen/padding"
android:paddingTop="@dimen/padding" >
<FrameLayout
android:orientation="vertical"
android:layout_
android:layout_
>
<com.beyondar.android.opengl.views.BeyondarGLSurfaceView
android:id="@+id/customGLSurface"
android:layout_
android:layout_ />
<com.beyondar.android.views.CameraView
android:id="@+id/camera"
android:layout_
android:layout_ />
<TextView
android:id="@+id/labelText"
android:layout_
android:layout_
android:text="Touch an AR Object"
android:background="#000000"
android:textColor="#FFFFFF"
/>
</FrameLayout>
</LinearLayout
【问题讨论】:
您说“应用程序仅在纵向模式下运行”,您的意思是您已经在自己处理旋转并将 Activity 限制为纵向模式? 是的!但是相机视图有横向模式!这就是问题所在! 【参考方案1】:如果您查看 BeyondAR 的示例应用程序,您会发现它有一个类似的问题,即相机的图像被拉伸以填满屏幕,因此在横向和纵向的两种情况下都没有适当的纵横比。这是使用相机预览时的常见问题,因为它在您首次启动时锁定到特定方向。
为了实现这一点,您需要将旋转视图的大小调整为与设备相机相匹配的纵横比。 Here's the official Android guide。
请注意专门称为“设置预览方向”的部分。
【讨论】:
感谢您的回答,但您能在我的代码中解释一下吗?对不起,我是初学者 BeyondAR 库作为 Android 库项目分发,因此您可以在将库加载到 IDE 后随意编辑该库。您使用的是什么 IDE? eclipse...我在第一篇文章中上传了 Beyondar lib 的 cameraview.java【参考方案2】:BeyondAR 已更新,现在由于有了片段,它变得更容易了。检查网页并更新您的库:
https://github.com/BeyondAR/beyondar
【讨论】:
以上是关于CameraView 中的人像模式的主要内容,如果未能解决你的问题,请参考以下文章
Android ViewPager,片段中的cameraview未显示
在android中的surfaceview上创建cameraview(掩码)