Реализую в своем приложении возможность съемки фото с передней/задней камеры. Вот код реализации:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
SurfaceHolder holder;
Camera camera;
Context context;
Camera.Size bestSize;
static int cameraId;
public CameraPreview(Context context, Camera camera) {
super(context);
this.context = context;
this.camera = camera;
holder = getHolder();
holder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
}
catch (IOException e) {
e.printStackTrace();
Log.d("camera", "All is terrible");
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
prepareCamera();
launchPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public int getCorrectCameraOrientation() {
int rotation = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE))
.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 = 0;
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
// back cam
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
result = ((360 - degrees) + info.orientation);
} else {
// front cam
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = ((360 - degrees) - info.orientation);
result += 360;
}
}
return result % 360;
}
static public Observable<Camera> createCamera(int cameraId){
CameraPreview.cameraId = cameraId;
// open front or rear camera, depends on cameraId
Observable<Camera> cameraObservable = Observable.create(
s -> {
Camera camera = null;
if(Camera.getNumberOfCameras() > 1)
camera = Camera.open(cameraId);
else {
// return front camera if not rear
camera = Camera.open(1);
}
s.onNext(camera);
s.onCompleted();
});
return cameraObservable;
}
private void launchPreview(){
try
{
camera.setPreviewDisplay(holder);
camera.startPreview();
}
catch(Exception e)
{
Log.d("CAMERA", "Error: " + e.getMessage());
}
}
private void getBestPictureResolution(){
List<Camera.Size> sizes = camera.getParameters().getSupportedPictureSizes();
Camera.Size result = sizes.get(0);
for (Camera.Size size: sizes) {
if(size.width > result.width && size.height > result.height) {
result = size;
}
}
bestSize = result;
}
private void setOptimalPreviewSize() {
Display display = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
Camera.Size size = camera.getParameters().getPreviewSize();
RectF rectDisplay = new RectF();
RectF rectPreview = new RectF();
rectDisplay.set(0, 0, display.getWidth(), display.getHeight());
rectPreview.set(0, 0, size.height, size.width);
Matrix matrix = new Matrix();
matrix.setRectToRect(rectPreview, rectDisplay,
Matrix.ScaleToFit.START);
matrix.mapRect(rectPreview);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
lp.height = (int) (rectPreview.bottom);
lp.width = (int) (rectPreview.right);
setLayoutParams(lp);
requestLayout();
}
private void prepareCamera(){
if(camera != null)
camera.stopPreview();
Camera.Parameters params = camera.getParameters();
if(bestSize == null)
getBestPictureResolution();
params.setPictureSize(bestSize.width, bestSize.height);
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.setDisplayOrientation(getCorrectCameraOrientation());
params.setRotation(getCorrectCameraOrientation());
setOptimalPreviewSize();
camera.setParameters(params);
}
}
Превью с обеих камер работает нормально, с правильным rotation. Если делать фото с задней камеры, то все хорошо: изображение правильно повернуто, а если с передней, то фото перевернуто. Как это исправить?