M
M
Michael Kim2016-12-27 16:04:25
Android
Michael Kim, 2016-12-27 16:04:25

Why is the photo from the front camera turned upside down?

I implement in my application the ability to take photos from the front / rear camera. Here is the implementation code:

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

The preview from both cameras works fine with the correct rotation. If you take a photo from the rear camera, then everything is fine: the image is rotated correctly, and if you take a photo from the front, then the photo is upside down. How to fix it?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
K
Kostya Bakay, 2017-01-11
@kostyabakay

Faced a similar problem recently. Some phones (Samsung in my case) can change the photo orientation themselves. Because of this, a photo taken from the gallery was rotated in my ImageView. To fix this, I used such a crutch - onActivityResult () gets a photo that was selected from the gallery and in the getImageOrientation () method I set the desired orientation.

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d("myLogs", "requestCode = " + requestCode + ", resultCode = " + resultCode);
        if (requestCode == 999 && resultCode == Activity.RESULT_OK)
            try {
                Matrix matrix = new Matrix();
                matrix.postRotate(getImageOrientation(data));

                if (mAvatarBitmap != null) mAvatarBitmap.recycle();
                InputStream stream = getActivity().getContentResolver().openInputStream(data.getData());
                mAvatarBitmap = BitmapFactory.decodeStream(stream);
                if (stream != null) stream.close();

                Bitmap rotatedBitmap = Bitmap.createBitmap(mAvatarBitmap, 0, 0, mAvatarBitmap.getWidth(), mAvatarBitmap.getHeight(), matrix, true);
                storeImage(rotatedBitmap);
                setLogo();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

    private int getImageOrientation(Intent data) {
        Uri imageUri = data.getData();
        String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
        Cursor cur = getActivity().getContentResolver().query(imageUri, orientationColumn, null, null, null);
        int orientation = -1;
        if (cur != null && cur.moveToFirst()) {
            orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
            Log.d("orientation", "Picture orientation: " + orientation);
        } else {
            Log.d("orientation", "Wrong picture orientation: " + orientation);
        }
        if (cur != null) cur.close();

        return orientation;
    }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question