【问题标题】:Rotating the Camera Activity 180 degrees when in landscape causes inverted camera preview在横向时将相机活动旋转 180 度会导致相机预览倒置
【发布时间】:2014-01-20 05:49:45
【问题描述】:

编辑

从倒置纵向旋转到横向之一并从那里旋转到倒置纵向时也是一个问题。我已经在默认的相机应用程序上测试了这些情况,它似乎没有任何这些问题.

结束编辑

我有一个自定义相机,当它旋转 180 度时,从一个风景到另一个风景会显示一个倒置的预览。我在我的代码中使用了一个 OrientationEventListener 像这样。 mCamera.setDisplayOrientationsetDisplayOrientation 中调用,我使用roundOrientation(orientation,orientationHistory) 将方向四舍五入为0,90,180,270,并使用getDisplayRotation 获得自然显示旋转。我在initializeFirstTime 中实例化侦听器并启用它initializeFirstTime 和如果从initializeSecondTime 的暂停状态恢复。我禁用onPause 中的侦听器。我在onResume 中调用initializeFirstTimeinitializeSecondTime。 :

    class MyOrientationEventListener extends OrientationEventListener
{
    
    @Override
    public void onOrientationChanged(int orientation)
    {
        if(orientation==ORIENTATION_UNKNOWN)
            return;
        mOrientation=roundOrientation(orientation,0);
        int orientationCompensation=getDisplayRotation(CameraActivity.this);
        if(mOrientationCompensation!=orientationCompensation)
            mOrientationCompensation=orientationCompensation;
    }

    public MyOrientationEventListener(Context context) {
        super(context);
    }
    
    private int roundOrientation(int orientation, int orientationHistory) {
        boolean changeOrientation = false;
        final int ORIENTATION_HYSTERESIS=5;//a tolerance value above the limit
        if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
            changeOrientation = true;
        } else {
            int dist = Math.abs(orientation - orientationHistory);
            dist = Math.min(dist, 360 - dist);
            changeOrientation = (dist >= 45 +ORIENTATION_HYSTERESIS );
        }
        if (changeOrientation) {
                return ((orientation + 45) / 90 * 90) % 360;
        }
        return orientationHistory;
    }   
}

private void setDisplayOrientation()
{
    mDisplayRotation=getDisplayRotation(this);
    mDisplayOrientation=getDisplayOrientation(mDisplayRotation, CameraInfo.CAMERA_FACING_BACK);
    mCamera.setDisplayOrientation(mDisplayOrientation);
}

private int getDisplayOrientation(int degrees, int cameraId) {
    // See android.hardware.Camera.setDisplayOrientation for
    // documentation.
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    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;
    }
    return result;
}

 private int getDisplayRotation(Activity activity) {
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        switch (rotation) {
            case Surface.ROTATION_0: return 0;
            case Surface.ROTATION_90: return 90;
            case Surface.ROTATION_180: return 180;
            case Surface.ROTATION_270: return 270;
        }
        return 0;
    } 

private MyOrientationEventListener mOrientationListener;
private int mOrientation=OrientationEventListener.ORIENTATION_UNKNOWN;
private int mOrientationCompensation=0;
private int mDisplayRotation;
private int mDisplayOrientation;

这两个方法用于激活OrientationEventListener:

private void initializeFirstTime()
{
    //checking if previously initialized and setting camera parameters
    mOrientationListener=new MyOrientationEventListener(CameraActivity.this);
    mOrientationListener.enable();
    mFirstTimeInitialized=true;
}

private void initializeSecondTime()
{
    mOrientationListener.enable();
}

Camera Preview 像这样开始、停止和重新启动:

  private void startPreview() throws CameraHardwareException
{
    //check if called before onPause or after onResume,
    //open the Camera if null,stop the preview,set the parameters
    setDisplayOrientation();
    try
    {
        Log.d(TAG, "Trying to start the preview");
        mCamera.startPreview();
    }
    catch(Throwable ex)
    {
        closeCamera();
        throw new RuntimeException("Could not start camera preview");
    }
    mPreviewing=true;
}

Activity 生命周期方法是这样实现的:

@Override
public void onResume()
{
    super.onResume();
    mPausing=false;
    //check condition for SurfaceHolder
    //probsbly happens if camera has paused and is resuming
    if(mStatus==PREVIEW_STOPPED)
    {
        try {
            startPreview();
        } catch (CameraHardwareException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    if(surfaceHolder!=null)
    {
        if(!mFirstTimeInitialized)
            initializeFirstTime();
        else
            initializeSecondTime();
    }
    keepScreenOnAwhile();
    if(mStatus==CAMERA_IDLE)
    {
        mResumeTime=SystemClock.uptimeMillis();
        handler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100);
    }
}

@Override
public void onPause()
{
    mPausing=true;
    stopPreview();
    closeCamera();
    resetScreenOn();
    if(mFirstTimeInitialized)
        mOrientationListener.disable();
    handler.removeMessages(FIRST_TIME_INIT);
    handler.removeMessages(CLEAR_SCREEN_DELAY);
    super.onPause();
}

SurfaceHolder.Callbacks 方法已在此处实现:

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    if(holder.getSurface()==null)
    {   
        Log.d(TAG, "holder.getSurface()=null");
        return;
    }
    //stash the holder here for later use,useful if onResume needs to be invoked after this.
    surfaceHolder=holder;
    if(mCamera==null)
        return;
    //sometimes surfaceChanged is called after onPause or before onResume,ignore it
    if(mPausing || isFinishing())
        return;
    if(mStatus==PREVIEW_STOPPED)
        try {
            startPreview();
        } catch (CameraHardwareException e1) {
            Log.e(TAG, "Error starting the preview");
        }
    if(!mPreviewing)
        try {
            startPreview();
        } catch (CameraHardwareException e) {
            Log.e(TAG,"Could not get the camera");
        }
    
    if(!mFirstTimeInitialized)
        if(getDisplayRotation(this)!=mDisplayOrientation)
            setDisplayOrientation();
    if(mPreviewing && holder.isCreating())
    {
        setPreviewDisplay(holder);
    }
    if(!mFirstTimeInitialized)
        handler.sendEmptyMessage(FIRST_TIME_INIT);
    else
        initializeSecondTime();
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    //nothing here
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    stopPreview();
    surfaceHolder=null;
}

方向事件侦听器在 onResume 和 surfaceChanged 中启用,无论我猜哪个调用最快,然后在 onPause 中禁用。OrientationEventListener 仅在 initializeFirstTime 中实例化。

编辑:

发生这种情况是因为我没有正确启用OrientationEventListener。我还为影响图像旋转的参数设置了旋转:

  mParameters.setRotation(rotation);

【问题讨论】:

标签: android android-camera landscape android-orientation


【解决方案1】:

在创建表面时调用它

 private void setUpCamera(Camera c) {

    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    rotation = getWindowManager().getDefaultDisplay().getRotation();
    int degree = 0;
    switch (rotation) {
        case Surface.ROTATION_0:
            degree = 0;
            break;
        case Surface.ROTATION_90:
            degree = 90;
            break;
        case Surface.ROTATION_180:
            degree = 180;
            break;
        case Surface.ROTATION_270:
            degree = 270;
            break;

        default:

            break;
    }

    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        // frontFacing
        rotation = (info.orientation + degree) % 360;
        rotation = (360 - rotation) % 360;
    }
    else {
        // Back-facing
        rotation = (info.orientation - degree + 360) % 360;
    }


    c.setDisplayOrientation(rotation);




    params.setRotation(rotation);
    camera.setParameters(params);


}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    相关资源
    最近更新 更多