1. 程式人生 > >Android 自定義相機 Camera 圖片方向問題

Android 自定義相機 Camera 圖片方向問題

相機預覽方向問題


對於相機的預覽方向我們可以通過如下API進行設定

camera.setDisplayOrientation(0);
但是,該API影響的是相機的預覽方向,對於照片的儲存方向並沒有什麼影響,最終照片儲存的方向還是由Camera的影象Sensor決定的。


照片儲存方向問題


第一種解決辦法就是對拍照後的圖片先進行旋轉再進行儲存,如下

public static Bitmap rotateBitmapByDegree(Bitmap bmp, int degree) {
    if (degree == 0 || null == bmp) return bmp;
    Bitmap returnBm = null;
    // 根據旋轉角度,生成旋轉矩陣
    Matrix matrix = new Matrix();
    matrix.postRotate(degree);
    // 將原始圖片按照旋轉矩陣進行旋轉,並得到新的圖片
    returnBm = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
    if (returnBm == null) {
        returnBm = bmp;
    }
    if (returnBm != bmp && !bmp.isRecycled()) {
        bmp.recycle();
        bmp = null;
    }
    return returnBm;
}
但是這種方法比較耗時,尤其圖片較大的時候,不建議使用。


第二種方法就是通過ExifInterface對圖片進行旋轉,如下

public static void setPictureDegreeZero(String path) {
    try {
        ExifInterface exifInterface = new ExifInterface(path);
        // 修正圖片的旋轉角度,設定其不旋轉。這裡也可以設定其旋轉的角度,可以傳值過去,
        // 例如旋轉90度,傳值ExifInterface.ORIENTATION_ROTATE_90,需要將這個值轉換為String型別的
        exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION, String.valueOf(ExifInterface.ORIENTATION_ROTATE_90))
        exifInterface.saveAttributes();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
這種方法一定要在儲存完圖片之後再使用,否則不會生效。最終的效果就是你拍照的時候什麼方向,儲存到本地的照片就是什麼方向。


第三種方法就是通過OrientationEventListener實現對圖片儲存方向的糾正,如下

public class IOrientationEventListener extends OrientationEventListener {

	public IOrientationEventListener(Context context) {
		super(context);
	}

	@Override
	public void onOrientationChanged(int orientation) {
		if (ORIENTATION_UNKNOWN == orientation) {
			return;
		}
		Camera.CameraInfo info = new Camera.CameraInfo();
		Camera.getCameraInfo(mCameraId, info);
		orientation = (orientation + 45) / 90 * 90;
		int rotation = 0;
		if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
			rotation = (info.orientation - orientation + 360) % 360;
		} else {
			rotation = (info.orientation + orientation) % 360;
		}
        Log.e("TAG","orientation: " + orientation);
		if (null != mCamera) {
			Camera.Parameters parameters = mCamera.getParameters();
			parameters.setRotation(rotation);
			mCamera.setParameters(parameters);
		}
	}
}

備註:後置攝像頭cameraId=0;


final IOrientationEventListener orientationEventListener = new IOrientationEventListener(this);
surfaceView.getHolder().setKeepScreenOn(true);//螢幕常亮
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
	//當SurfaceHolder被建立的時候回撥
	@Override
	public void surfaceCreated(SurfaceHolder surfaceHolder) {
		orientationEventListener.enable();
		......
	}

	//當SurfaceHolder的尺寸發生變化的時候被回撥
	@Override
	public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
		......
	}

	//當SurfaceHolder被銷燬的時候回撥
	@Override
	public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
		orientationEventListener.disable();
		......
	}
});
這種方法最終的效果就是不管你拍照的時候是什麼方向,最終儲存到本地的照片都是0度方向的,跟系統相機拍照後一個效果。