在横向时将相机活动旋转180度会导致倒置的相机预览

时间:2014-01-20 05:49:45

标签: android android-camera landscape android-orientation

修改

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

END EDIT

我有一个自定义相机,当旋转180度时,从一个横向到另一个横向显示反转的预览。我在我的代码中使用了OrientationEventListener,就像这样。 在mCamera.setDisplayOrientation中调用setDisplayOrientation,我使用roundOrientation(orientation,orientationHistory)将方向四舍五入到0,90,180,270,然后使用getDisplayRotation获得自然显示轮换。我在{{实例化}侦听器1}}并启用它initializeFirstTime,如果从initializeFirstTime的暂停状态恢复。我在initializeSecondTime中禁用了监听器。我呼叫onPauseinitializeFirstTime initializeSecondTime。 :

onResume

这两个方法用于激活OrientationEventListener:

    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;

相机预览启动,停止并重新启动,如下所示:

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

Activity生命周期方法已实现如下:

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

SurfaceHolder.Callbacks方法已经在这里实现:

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

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

编辑:

这是否正在发生,因为我没有正确启用@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; } 。我也为正确影响图像旋转的参数设置了旋转:

OrientationEventListener

1 个答案:

答案 0 :(得分: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);


}