28

I'm writing an Android application that uses the camera. I'm setting camera display orientation to 90, my activity is in a portrait orientation:

camera.setDisplayOrientation(90);

I'm getting a well oriented preview picture, but the resulting image is rotated to -90 degrees (counter clockwise) and

exif.getAttribute(ExifInterface.TAG_ORIENTATION)

returns ORIENTATION_NORMAL
Is it expected behavior? Should I rotate resulted image after the capture?

Device - Nexus S, API - 10

GetUsername
  • 1,057
  • 5
  • 18
  • 29
  • Same thing is happening to me; I'm also on Nexus S API 10; thanks for the question. – serkanozel Dec 01 '11 at 19:40
  • Answer here http://stackoverflow.com/questions/14066038/why-image-captured-using-camera-intent-gets-rotated-on-some-devices-in-android – Shirish Herwade Jun 27 '16 at 06:23
  • 1
    Possible duplicate of [Why does an image captured using camera intent gets rotated on some devices on Android?](https://stackoverflow.com/questions/14066038/why-does-an-image-captured-using-camera-intent-gets-rotated-on-some-devices-on-a) – bummi Dec 04 '17 at 11:04

4 Answers4

26

Try this

try {
        File f = new File(imagePath);
        ExifInterface exif = new ExifInterface(f.getPath());
        int orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        int angle = 0;

        if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
            angle = 90;
        } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
            angle = 180;
        } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
            angle = 270;
        }

        Matrix mat = new Matrix();
        mat.postRotate(angle);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;

        Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f),
                null, options);
        bitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
                bmp.getHeight(), mat, true);
        ByteArrayOutputStream outstudentstreamOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100,
                outstudentstreamOutputStream);
        imageView.setImageBitmap(bitmap);

    } catch (IOException e) {
        Log.w("TAG", "-- Error in setting image");
    } catch (OutOfMemoryError oom) {
        Log.w("TAG", "-- OOM Error in setting image");
    }

It will work

Ameer
  • 2,709
  • 1
  • 28
  • 44
15

Problem is the camera orientation is a complete disaster (as is capturing an image) because OEMs do not adhere to the standard. HTC phones do things one way, Samsung phones do it a different way, the Nexus line seems to adhere no matter which vendor, CM7 based ROMs I think follow the standard no matter which hardware, but you get the idea. You sort of have to determine what to do based on the phone/ROM. See discussion here: Android camera unexplainable rotation on capture for some devices (not in EXIF)

Community
  • 1
  • 1
Kaediil
  • 166
  • 1
  • 2
6

I had the same problem like you, but i've fix it.
You should use the same code:

Camera.Parameters parameters = camera.getParameters();
parameters.setRotation(90);
camera.setParameters(parameters);

I hope you can use this code too.

leonkuehn
  • 124
  • 2
  • 9
2
camera.setDisplayOrientation(90);

I have coded the app for only Portrait Mode.

Will make the Camera to rotate to 90 degree and This may result in not suitable for all devices in android In order to get the Correct Preview for all android devices use the following code which is refereed in developers site.

Below you have to send your activity, cameraId = back is 0 and for Front camera is 1

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;
    //int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        // do something for phones running an SDK before lollipop
        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);
} 

This is how to set the setDisplayOrientation for camera

Now you may have trouble is saving the captured Image in Correct Orientation, which is bug in Camera API to support all devices in android .you can overcome using the Steps below

PLS NOTE EXIF VALUE WILL NOT GIVE YOU CORRECT VALUE IN ALL DEVICES , So this would help you

int CameraEyeValue = setPhotoOrientation(CameraActivity.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back

By using the same concept we used before for DisplayOrientation

public int setPhotoOrientation(Activity activity, int cameraId) {
    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;
    // do something for phones running an SDK before lollipop
    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;
    }

    return result;
}

So your final PictureCallBack method should look like

private PictureCallback getPictureCallback() {
    PictureCallback picture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            //make a new picture file
            File pictureFile = getOutputMediaFile();

            if (pictureFile == null) {
                return;
            }
            try {
                //write the file
                FileOutputStream fos = new FileOutputStream(pictureFile);
                Bitmap bm=null;

                // COnverting ByteArray to Bitmap - >Rotate and Convert back to Data
                if (data != null) {
                    int screenWidth = getResources().getDisplayMetrics().widthPixels;
                    int screenHeight = getResources().getDisplayMetrics().heightPixels;
                    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();

                        int CameraEyeValue = setPhotoOrientation(AndroidCameraExample.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back
                        if(cameraFront) { // As Front camera is Mirrored so Fliping the Orientation
                            if (CameraEyeValue == 270) {
                                mtx.postRotate(90);
                            } else if (CameraEyeValue == 90) {
                                mtx.postRotate(270);
                            }
                        }else{
                                mtx.postRotate(CameraEyeValue); // CameraEyeValue is default to Display Rotation
                        }

                        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;
                    }
                }
                // COnverting the Die photo to Bitmap



                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                bm.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                byte[] byteArray = stream.toByteArray();
                fos.write(byteArray);
                //fos.write(data);
                fos.close();

                Toast toast = Toast.makeText(myContext, "Picture saved: " + pictureFile.getName(), Toast.LENGTH_LONG);
                toast.show();

            } catch (FileNotFoundException e) {
            } catch (IOException e) {
            }

            //refresh camera to continue preview
            mPreview.refreshCamera(mCamera);
            mPreview.setCameraDisplayOrientation(CameraActivity.this,GlobalCameraId,mCamera);
        }
    };
    return picture;
}

As the Works only for Portrait mode using Front and Back camera The Picture is rotated to only portrait mode with correct portrait Orientation in all android devices .

For LandScape you can Make this as reference and make changes in the below block

   if(cameraFront) { // As Front camera is Mirrored so Fliping the Orientation
         if (CameraEyeValue == 270) {
             mtx.postRotate(90); //change Here 
          } else if (CameraEyeValue == 90) {
             mtx.postRotate(270);//change Here 
           }
        }else{
           mtx.postRotate(CameraEyeValue); // CameraEyeValue is default to Display Rotation //change Here 
        }
vignesh waran
  • 159
  • 2
  • 4