Camera preview is in portrait mode but image captured is rotated

I am trying to capture a photo using the camera. The preview by default was in landscape mode which i could change it to portrait mode using

    setCameraDisplayOrientation(this,1,  mCamera);
    public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().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;
     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;
     }
     camera.setDisplayOrientation(result);
 }

The image captured is stored under a folder myImages. But the images is rotated. (look's like the image is captured in landscape mode)

So how can i rotate the image captured and save the same?

public class MainActivity extends Activity {

private static final int REQUEST_CODE = 1; 
ImageView imageView;
Button b;
private Camera mCamera;
private CameraPreview mPreview;
private Bitmap bitmap;
private PictureCallback mPicture;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    boolean check =checkCameraHardware(MainActivity.this);
    if(check)
    {
         mCamera = getCameraInstance();

        // mCamera.setDisplayOrientation(90);
         setCameraDisplayOrientation(this,
                 1,  mCamera);//requires min sdk 9
    }
    // Create an instance of Camera
    mPicture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

            File imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyImages");
            if(!imagesFolder.exists())
            imagesFolder.mkdirs();   
            File pictureFile = new File(imagesFolder, "image.jpg");

            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);

                System.out.println("hello");
                fos.write(data);
                fos.close();
            } catch (FileNotFoundException e) {
                Log.d("No File", "File not found: " + e.getMessage());
            } catch (IOException e) {
                //Log.d(TAG, "Error accessing file: " + e.getMessage());
            }
        }
    };

    // Create our Preview view and set it as the content of our activity.
    mPreview = new CameraPreview(this, mCamera);
    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
    preview.addView(mPreview);
     b = (Button) findViewById(R.id.button_capture);
     b.setOnClickListener(new OnClickListener()
      {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
                 mCamera.takePicture(null, null, mPicture);
                 Toast.makeText(MainActivity.this, "Called",1000).show();

        }

      });
  }
 public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().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;
     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;
     }
     camera.setDisplayOrientation(result);
 }
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
         Toast.makeText(this, "Phone has camera", Toast.LENGTH_LONG).show();
        return true;
    } else {
        // no camera on this device
         Toast.makeText(this, "Phone has no camera", Toast.LENGTH_LONG).show();
        return false;
    }
}
public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}


@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    mCamera.release();
}
  }

The CameraPreview class is the same from the developer site http://developer.android.com/guide/topics/media/camera.html

Note: I am using the back camera not the front facing camera.


Solution 1:

I faced the same problem when taking photo from camera in portrait mode. Below lines of code solved my problem:

public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) {
    android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
    android.hardware.Camera.getCameraInfo(cameraId, info);
    int rotation = activity.getWindowManager().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;
    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;
    }
    camera.setDisplayOrientation(result);
}

Call setCameraDisplayOrientation() method in surfaceCreated callback as the following:

@Override
public void surfaceCreated(SurfaceHolder holder) {
    camera = Camera.open();
    setCameraDisplayOrientation(getActivity(), CameraInfo.CAMERA_FACING_BACK, camera);
}

I had to rotate the image in Camera onPictureTaken() callback:

camera.takePicture(null, null, new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

            if (data != null) {
                int screenWidth = getResources().getDisplayMetrics().widthPixels;
                int screenHeight = getResources().getDisplayMetrics().heightPixels;
                Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);

                if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                    // Notice that width and height are reversed
                    Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true);
                    int w = scaled.getWidth();
                    int h = scaled.getHeight();
                    // Setting post rotate to 90
                    Matrix mtx = new Matrix();
                    mtx.postRotate(90);
                    // Rotating Bitmap
                    bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);
                }else{// LANDSCAPE MODE
                    //No need to reverse width and height
                    Bitmap scaled = Bitmap.createScaledBitmap(bm, screenWidth,screenHeight , true);
                    bm=scaled;
                }
                photoPreview.setImageBitmap(bm);
            }
            isImageCaptured = true;
            photoPreview.setVisibility(View.VISIBLE);
            surfaceView.setVisibility(View.GONE);
        }
});

Solution 2:

Below code worked for me for Front facing camera.

if (data != null) {
                try {
                    int screenWidth = getResources().getDisplayMetrics().widthPixels;
                    int screenHeight = getResources().getDisplayMetrics().heightPixels;
                    bm = BitmapFactory.decodeByteArray(data, 0,
                            (data != null) ? data.length : 0);
                    CameraInfo info = new CameraInfo();
                    Camera.getCameraInfo(cameraFace, info);
                    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                        // Notice that width and height are reversed
                        // Bitmap scaled = Bitmap.createScaledBitmap(bm,
                        // screenHeight, screenWidth, true);
                        // int w = scaled.getWidth();
                        // int h = scaled.getHeight();
                        // Setting post rotate to 90
                        Matrix mtx = new Matrix();
                        mtx.postRotate(90);
                        if (cameraFace == CameraInfo.CAMERA_FACING_FRONT)
                            mtx.postRotate(180);
                        // Rotating Bitmap
                        bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
                                bm.getHeight(), mtx, true);
                    } else {// LANDSCAPE MODE
                        Bitmap scaled = Bitmap.createScaledBitmap(bm,
                                screenWidth, screenHeight, true);
                        bm = scaled;
                    }
                } catch (Exception e) {
                } catch (Error e) {
                }
            }

Solution 3:

Yes, I tried the way in the answer, it works for back camera, for front camera, it need to rotate 270 not 90. :)