Android摄像头preVIEW异样的目光 [英] Android camera preview look strange

查看:146
本文介绍了Android摄像头preVIEW异样的目光的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在执行一个摄像头应用程序,当我看preVIEW(特别是前置摄像头),图像很肥。它看起来像图像得到横向拉长。我按照与optimzed相机大小的SDK示例,但它并不能帮助。如何调整我的相机设置,以便将$像其他相机应用p $ PVIEW?

感谢。

我的code是如下。

 公共类CameraActivity扩展活动实现SurfaceHolder.Callback,Camera.ShutterCallback,Camera.PictureCallback {

相机m_camera;
SurfaceView m_surfaceView;
INT m_numOfCamera;
INT m_defaultCameraId;
INT m_currentCamera;
INT m_surfaceWidth;
INT m_surfaceHeight;

@覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.activity_camera);
    getActionBar()setDisplayHomeAsUpEnabled(真)。


    m_surfaceView =(SurfaceView)findViewById(R.id.camera preVIEW);
    。m_surfaceView.getHolder()的addCallback(本);

    m_camera = Camera.open();

    m_numOfCamera = Camera.getNumberOfCameras();

    CameraInfo cameraInfo =新CameraInfo();
    的for(int i = 0; I< m_numOfCamera ++我){
        Camera.getCameraInfo(ⅰ,cameraInfo);
        如果(cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK){
            m_defaultCameraId =我;
            m_currentCamera = m_defaultCameraId;
        }
    }

    如果(m_numOfCamera&小于1){
        菜单项switchCam =(菜单项)findViewById(R.id.menu_switch_camera);
        switchCam.setVisible(假);
    }
}

@覆盖
公共无效的onPause(){
    super.onPause();
    m_camera.stop preVIEW();
}

@覆盖
公共无效的onDestroy(){
    super.onDestroy();
    m_camera.release();
}

@覆盖
公共布尔onCreateOptionsMenu(功能菜单){
    。getMenuInflater()膨胀(R.menu.activity_camera,菜单);
    返回true;
}

@覆盖
公共布尔onOptionsItemSelected(最后一个菜单项项)
{
    如果(item.getItemId()== android.R.id.home)
    {
        意向意图=新的意图(这一点,MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(意向);

        返回true;
    }
    否则,如果(item.getItemId()== R.id.menu_switch_camera)
    {
        如果(m_camera!= NULL){
            m_camera.stop preVIEW();
            m_camera.release();
            m_camera = NULL;
        }

        m_camera = Camera.open((m_currentCamera + 1)%m_numOfCamera);
        m_currentCamera =(m_currentCamera + 1)%m_numOfCamera;

        Camera.Parameters PARAMS = m_camera.getParameters();
        名单< Camera.Size>大小= params.getSupported previewSizes();
        Camera.Size大小= getOptimal previewSize(尺寸,m_surfaceWidth,m_surfaceHeight);

        params.set previewSize(size.width,size.height);

        m_camera.setParameters(PARAMS);
        setCameraDisplayOrientation(这一点,m_currentCamera,m_camera);
        m_camera.start preVIEW();
        尝试 {
            m_camera.set previewDisplay(m_surfaceView.getHolder());
        }赶上(例外五){
            e.printStackTrace();
        }
        返回true;
    }
    返回true;
}

公共无效onPictureTaken(byte []的为arg0,摄像机ARG1){
    // TODO自动生成方法存根

}

公共无效onShutter(){
    // TODO自动生成方法存根

}

公共无效surfaceChanged(SurfaceHolder为arg0,INT格式,INT W,INT高){
    m_surfaceWidth = W;
    m_surfaceHeight = H;
    Camera.Parameters PARAMS = m_camera.getParameters();
    名单< Camera.Size>大小= params.getSupported previewSizes();
    Camera.Size选择= getOptimal previewSize(尺寸,W,H);

    params.set previewSize(selected.width,selected.height);


    m_camera.setParameters(PARAMS);
    setCameraDisplayOrientation(这一点,m_currentCamera,m_camera);
    m_camera.start preVIEW();
}

私有静态无效setCameraDisplayOrientation(活动活动,
         INT cameraId,android.hardware.Camera摄像头){
     android.hardware.Camera.CameraInfo信息=
             新android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId,资讯);
     INT旋转= activity.getWindowManager()。getDefaultDisplay()
             .getRotation();
     INT度= 0;
     开关(旋转){
         案例Surface.ROTATION_0:度= 0;打破;
         案例Surface.ROTATION_90:度= 90;打破;
         案例Surface.ROTATION_180:度= 180;打破;
         案例Surface.ROTATION_270:度= 270;打破;
     }

     INT结果;
     如果(info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
         结果=(info.orientation +度)%360;
         结果=(360  - 结果)%360; //补偿镜
     }其他{//背向
         结果=(info.orientation  - 度+ 360)%360;
     }
     camera.setDisplayOrientation(结果);
 }


公共无效surfaceCreated(SurfaceHolder为arg0){
    尝试 {
        m_camera.set previewDisplay(m_surfaceView.getHolder());
    }赶上(例外五){
        e.printStackTrace();
    }
}

公共无效surfaceDestroyed(SurfaceHolder为arg0){
    // TODO自动生成方法存根

}

私人大小getOptimal previewSize(名单<大小>的大小,INT W,INT高){


    最终双ASPECT_TOLERANCE = 0.1;
    双targetRatio =(双)W / H;
    如果(大小== NULL)
        返回null;

    大小optimalSize = NULL;
    双minDiff = Double.MAX_VALUE;

    INT targetHeight = H;

    //试着找一个大小匹配纵横比和尺寸
    对于(尺寸大小:大小){
        双率=(双)size.width / size.height;
        如果(Math.abs(比 -  targetRatio)> ASPECT_TOLERANCE)
            继续;
        如果(Math.abs(size.height  -  targetHeight)< minDiff){
            optimalSize =大小;
            minDiff = Math.abs(size.height  -  targetHeight);
        }
    }

    //不能找到一个匹配的纵横比,忽略此要求
    如果(optimalSize == NULL){
        minDiff = Double.MAX_VALUE;
        对于(尺寸大小:大小){
            如果(Math.abs(size.height  -  targetHeight)< minDiff){
                optimalSize =大小;
                minDiff = Math.abs(size.height  -  targetHeight);
            }
        }
    }

    返回optimalSize;
}

}
 

解决方案

相机preVIEW总是充满了 SurfaceView 显示它。如果 m_surfaceView 不与相机的高宽比匹配,preVIEW将被拉长。长宽比

您需要创建 m_surfaceView 匹配的纵横比。这意味着,你需要从code创建它,而不是从布局XML文件中。

有一个示例项目 APIDemos ,你会发现在Android的样本项目。在该项目中有一个名为的事情 相机preVIEW 。这其中有一个良好的示范来设置相机preVIEW在 SurfaceView 。它有一个类扩展的ViewGroup ,并添加 SurfaceView 从code的孩子。该 onMeasure()方法已被重写,以确定的高度和宽度的 SurfaceView ,所以纵横比为preserved。承担该项目一看,我希望这将是明显的。

[抱歉,我不能张贴链接在这里 - 应该是链接,但我发现它坏了。但是,如果你已经安装了Android SDK中的示例项目,你可以找到的样本项目。打开一个新的Andr​​oid示例项目,选择APIDemos,然后找一类名为相机preVIEW 。它应该是在包装 com.example.android.apis.graphics ,据我记得。]

I am implementing a camera app and when I look at the preview (especially with front camera), the image is very fat. It looks like the image get stretched horizontally. I follow the sdk sample with the optimzed camera size but it doesn't help. How can I adjust my camera setting so that it will preview like the other camera app?

Thanks.

My code is below.

public class CameraActivity extends Activity implements SurfaceHolder.Callback, Camera.ShutterCallback, Camera.PictureCallback {

Camera m_camera;
SurfaceView m_surfaceView;
int m_numOfCamera;
int m_defaultCameraId;
int m_currentCamera;
int m_surfaceWidth;
int m_surfaceHeight;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);
    getActionBar().setDisplayHomeAsUpEnabled(true);


    m_surfaceView = (SurfaceView)findViewById(R.id.cameraPreview);
    m_surfaceView.getHolder().addCallback(this);

    m_camera = Camera.open();

    m_numOfCamera = Camera.getNumberOfCameras();

    CameraInfo cameraInfo = new CameraInfo();
    for (int i = 0; i < m_numOfCamera; ++i) {
        Camera.getCameraInfo(i, cameraInfo);
        if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
            m_defaultCameraId = i;
            m_currentCamera = m_defaultCameraId;
        }       
    }

    if (m_numOfCamera < 1) {
        MenuItem switchCam = (MenuItem)findViewById(R.id.menu_switch_camera);
        switchCam.setVisible(false);
    }
}

@Override
public void onPause() {
    super.onPause();
    m_camera.stopPreview();
}

@Override
public void onDestroy() {
    super.onDestroy();
    m_camera.release();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_camera, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(final MenuItem item) 
{
    if (item.getItemId() == android.R.id.home) 
    {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);

        return true;
    } 
    else if (item.getItemId() == R.id.menu_switch_camera)
    {
        if (m_camera != null) {
            m_camera.stopPreview();
            m_camera.release();
            m_camera = null;
        }   

        m_camera = Camera.open((m_currentCamera + 1) % m_numOfCamera);
        m_currentCamera = (m_currentCamera + 1) % m_numOfCamera;

        Camera.Parameters params = m_camera.getParameters();
        List<Camera.Size> sizes = params.getSupportedPreviewSizes();
        Camera.Size size = getOptimalPreviewSize(sizes, m_surfaceWidth, m_surfaceHeight);

        params.setPreviewSize(size.width,  size.height);

        m_camera.setParameters(params);
        setCameraDisplayOrientation(this, m_currentCamera, m_camera);
        m_camera.startPreview();
        try {
            m_camera.setPreviewDisplay(m_surfaceView.getHolder());
        } catch (Exception e) {
            e.printStackTrace();
        }   
        return true;
    }
    return true;
}

public void onPictureTaken(byte[] arg0, Camera arg1) {
    // TODO Auto-generated method stub

}

public void onShutter() {
    // TODO Auto-generated method stub

}

public void surfaceChanged(SurfaceHolder arg0, int format, int w, int h) {
    m_surfaceWidth = w;
    m_surfaceHeight = h;
    Camera.Parameters params = m_camera.getParameters();
    List<Camera.Size> sizes = params.getSupportedPreviewSizes();
    Camera.Size selected = getOptimalPreviewSize(sizes, w, h);

    params.setPreviewSize(selected.width,  selected.height);


    m_camera.setParameters(params);
    setCameraDisplayOrientation(this, m_currentCamera, m_camera);
    m_camera.startPreview();    
}

private static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     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;
     }

     int result;
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }


public void surfaceCreated(SurfaceHolder arg0) {
    try {
        m_camera.setPreviewDisplay(m_surfaceView.getHolder());
    } catch (Exception e) {
        e.printStackTrace();
    }   
}

public void surfaceDestroyed(SurfaceHolder arg0) {
    // TODO Auto-generated method stub

}

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {


    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    if (sizes == null)
        return null;

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

    int targetHeight = h;

    // 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, ignore the requirement
    if (optimalSize == null) {
        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;
}

}

解决方案

The camera preview always fills up the SurfaceView showing it. If the aspect ratio of m_surfaceView doesn't match with the camera's aspect ratio, the preview will be stretched.

You'll need to create m_surfaceView matching the aspect ratio. That means, you'll need to create it from code, not from layout XML file.

There is a sample project APIDemos that you'll find in android sample projects. In the project there is a thing named CameraPreview. This one has a good demonstration for setting up camera preview in a SurfaceView. It has a class that extends ViewGroup, and adds the SurfaceView as its child from the code. The onMeasure() method has been overridden to determine the height and width of the SurfaceView, so the aspect ratio is preserved. Take a look on the project, and I hope it will be clear.

[Sorry I couldn't post the link here - this is supposed to be the link, but I found it broken. But if you have installed the sample projects with the Android SDK, you can find the project in the samples. Open a new Android Sample Project, select APIDemos, then look for a class named CameraPreview. It should be in the package com.example.android.apis.graphics, as far as I remember.]

这篇关于Android摄像头preVIEW异样的目光的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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