34

Notice how the view of the camera (NOT THE CAPTURED IMAGE) was flipped to left (image above), the orientation of the Activity is correct, but the camera view is messed up, please help me guys :) thank you.

Here is the XML layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center|top"
            android:orientation="vertical" >

            <SurfaceView
                android:id="@+id/camerapreview"
                android:layout_margin="10dp"
                android:layout_width="300dp"
                android:layout_height="300dp" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

And here is the code for the activity:

public class CustomCameraActivity extends Activity implements SurfaceHolder.Callback {

    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.camera);

        surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if(previewing){
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null){
            try {
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        camera = Camera.open();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }
}
Ali
  • 3,346
  • 4
  • 21
  • 56
jofftiquez
  • 7,548
  • 10
  • 67
  • 121

4 Answers4

37

I found the solution here. Answer by @Ed Jellard.

i just have to add camera.setDisplayOrientation(90); on surfaceCreated(SurfaceHolder holder) method, now the display is on the right angle.

see the happy T-REX :)

Ali
  • 3,346
  • 4
  • 21
  • 56
jofftiquez
  • 7,548
  • 10
  • 67
  • 121
  • I don't think this T-REX is happy :P Anyways, it helped me. Thanks. – Amit Gupta Aug 10 '15 at 15:59
  • 1
    @AmitGupta looks happy to me. :D – jofftiquez Aug 11 '15 at 02:15
  • 2
    This will only work if the device's camera is oriented in a landscape fashion. While this will work for the majority, it won't work for devices like the Nexus 5X whose camera is reverse landscape (you'd need to set the orientation to 180) – Brandon Nov 05 '16 at 03:23
  • This will work only on this device, and you have rotated image on the other devices. This might be the right solution: https://www.captechconsulting.com/blogs/android-camera-orientation-made-simple – SpyZip Jan 24 '17 at 09:03
19

This problem was solved a long time ago but I encountered some difficulties to put all pieces together so here is my final solution, I hope this will help others :

public void startPreview() {
        try {
            Log.i(TAG, "starting preview: " + started);

            // ....
            Camera.CameraInfo camInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(cameraIndex, camInfo);
            int cameraRotationOffset = camInfo.orientation;
            // ...

            Camera.Parameters parameters = camera.getParameters();
            List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
            Camera.Size previewSize = null;
            float closestRatio = Float.MAX_VALUE;

            int targetPreviewWidth = isLandscape() ? getWidth() : getHeight();
            int targetPreviewHeight = isLandscape() ? getHeight() : getWidth();
            float targetRatio = targetPreviewWidth / (float) targetPreviewHeight;

            Log.v(TAG, "target size: " + targetPreviewWidth + " / " + targetPreviewHeight + " ratio:" + targetRatio);
            for (Camera.Size candidateSize : previewSizes) {
                float whRatio = candidateSize.width / (float) candidateSize.height;
                if (previewSize == null || Math.abs(targetRatio - whRatio) < Math.abs(targetRatio - closestRatio)) {
                    closestRatio = whRatio;
                    previewSize = candidateSize;
                }
            }

            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            int degrees = 0;
            switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break; // Natural orientation
            case Surface.ROTATION_90:
                degrees = 90;
                break; // Landscape left
            case Surface.ROTATION_180:
                degrees = 180;
                break;// Upside down
            case Surface.ROTATION_270:
                degrees = 270;
                break;// Landscape right
            }
            int displayRotation;
            if (isFrontFacingCam) {
                displayRotation = (cameraRotationOffset + degrees) % 360;
                displayRotation = (360 - displayRotation) % 360; // compensate
                                                                    // the
                                                                    // mirror
            } else { // back-facing
                displayRotation = (cameraRotationOffset - degrees + 360) % 360;
            }

            Log.v(TAG, "rotation cam / phone = displayRotation: " + cameraRotationOffset + " / " + degrees + " = "
                    + displayRotation);

            this.camera.setDisplayOrientation(displayRotation);

            int rotate;
            if (isFrontFacingCam) {
                rotate = (360 + cameraRotationOffset + degrees) % 360;
            } else {
                rotate = (360 + cameraRotationOffset - degrees) % 360;
            }

            Log.v(TAG, "screenshot rotation: " + cameraRotationOffset + " / " + degrees + " = " + rotate);

            Log.v(TAG, "preview size: " + previewSize.width + " / " + previewSize.height);
            parameters.setPreviewSize(previewSize.width, previewSize.height);
            parameters.setRotation(rotate);
            camera.setParameters(parameters);
            camera.setPreviewDisplay(mHolder);
            camera.startPreview();

            Log.d(TAG, "preview started");

            started = true;
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }
Louis GRIGNON
  • 699
  • 6
  • 17
  • I don't know how to deal with the variables. It would be great if you add more information about the rest. There are lots of red variables in the code. – c-an Nov 15 '18 at 13:47
1

There is a property in class Camera.CameraInfo named as orientation. It returns the integer. You can get the current orientation and then changed accordingly.

See this answer for handling orientation and CameraInfo class.

I am sure this will help you.

Community
  • 1
  • 1
Faizan Mubasher
  • 4,427
  • 11
  • 45
  • 81
-3

Camera rotates automatically when you rotate your phone, However if you want the image captured by camera or from gallery to be in the right orientation, use this :-

public void rotate(String filePath){
              Bitmap cameraBitmap = null;
            BitmapFactory.Options bmOptions = new BitmapFactory.Options();
            bmOptions.inJustDecodeBounds = false;
            bmOptions.inPurgeable = true;
            bmOptions.inBitmap = cameraBitmap; 
            bmOptions.inMutable = true; 

        cameraBitmap = BitmapFactory.decodeFile(filePath,bmOptions); 
        // Your image file path
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            cameraBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);


        ExifInterface exif = new ExifInterface(filePath);
        float rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);  
        System.out.println(rotation);

        float rotationInDegrees = exifToDegrees(rotation);
        System.out.println(rotationInDegrees);

        Matrix matrix = new Matrix();
        matrix.postRotate(rotationInDegrees);

        Bitmap rotatedBitmap = Bitmap.createBitmap(cameraBitmap , 0, 0, cameraBitmap.getWidth(), cameraBitmap.getHeight(), matrix, true);
        FileOutputStream fos=new FileOutputStream(filePath);
        rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.write(bos.toByteArray());
        cameraBitmap.recycle();
        System.gc();
        fos.flush();
        fos.close();
}

private static float exifToDegrees(float exifOrientation) {        
    if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; } 
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {  return 180; } 
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {  return 270; }            
    return 0;    
} 
Rahul Gupta
  • 5,275
  • 8
  • 35
  • 66
  • 2
    this is not an actual answer, read [OP comment](http://stackoverflow.com/questions/20064793/how-to-fix-camera-orientation#comment29887869_20064793) – RobinHood Nov 19 '13 at 06:58