Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an image captured using camera intent gets rotated on some devices on Android?

I'm capturing an image and setting it to image view.

public void captureImage() {      Intent intentCamera = new Intent("android.media.action.IMAGE_CAPTURE");     File filePhoto = new File(Environment.getExternalStorageDirectory(), "Pic.jpg");     imageUri = Uri.fromFile(filePhoto);     MyApplicationGlobal.imageUri = imageUri.getPath();     intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);     startActivityForResult(intentCamera, TAKE_PICTURE); }  @Override protected void onActivityResult(int requestCode, int resultCode, Intent intentFromCamera) {     super.onActivityResult(requestCode, resultCode, intentFromCamera);      if (resultCode == RESULT_OK && requestCode == TAKE_PICTURE) {          if (intentFromCamera != null) {             Bundle extras = intentFromCamera.getExtras();             if (extras.containsKey("data")) {                 bitmap = (Bitmap) extras.get("data");             }             else {                 bitmap = getBitmapFromUri();             }         }         else {             bitmap = getBitmapFromUri();         }         // imageView.setImageBitmap(bitmap);         imageView.setImageURI(imageUri);     }     else {     } }  public Bitmap getBitmapFromUri() {      getContentResolver().notifyChange(imageUri, null);     ContentResolver cr = getContentResolver();     Bitmap bitmap;      try {         bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, imageUri);         return bitmap;     }     catch (Exception e) {         e.printStackTrace();         return null;     } } 

But the problem is, the image on some devices every time it gets rotated. For example, on a Samsung device it works good, but on a Sony Xperia the image gets rotated by 90 degrees and on Toshiba Thrive (tablet) by 180 degrees.

like image 847
Shirish Herwade Avatar asked Dec 28 '12 07:12

Shirish Herwade


People also ask

How do I fix the camera orientation on my Android?

Find and turn on the "Auto-rotate" tile in the quick-setting panel. You can also go to Settings > Display > Auto-rotate screen to turn it on. Your phone screen should rotate automatically now if nothing is wrong with the sensors.

Why does my photo Keep rotating?

If an image contains the wrong image orientation EXIF data, or if that data is stripped in the upload process for whatever reason, it will display as rotated. To fix the EXIF orientation, open the image in your image editing program.

Why does an image captured using camera intent get rotated?

Also answers available to correct it - Why does an image captured using camera intent gets rotated on some devices on Android? I guess it might the be the problem of your Orientation Sensor.. Do you process the sensor value in your program.. to know when the user has taken the photo the device was in horizontal or vertical orientation..

Why do my photos get rotated on Android?

Some phones rotate them, some don't. see the link, it's issue #1193 Also answers available to correct it - Why does an image captured using camera intent gets rotated on some devices on Android? I guess it might the be the problem of your Orientation Sensor..

Does the camera rotate the image when taking pictures?

For example, on a Samsung device it works good, but on a Sony Xperia the image gets rotated by 90 degrees and on Toshiba Thrive (tablet) by 180 degrees. as i think when you use the internal intent for dealing with the camera app,then it rotates image.This is depends upon how you hold the device to capture image.

How to fix image rotated 90 degrees on Android?

When you capture an image on android using intentandroid.media.action.IMAGE_CAPTURE, it gets rotated 90 degrees on some devices.  Here is how to solve this problem with the code snippets. I have tested it on Android 4.1(Jelly Bean), Android 4.4(KitKat) and Android 5.0(Lollipop). Steps Scale down the image if it was bigger than 1024×1024.


2 Answers

Most phone cameras are landscape, meaning if you take the photo in portrait, the resulting photos will be rotated 90 degrees. In this case, the camera software should populate the Exif data with the orientation that the photo should be viewed in.

Note that the below solution depends on the camera software/device manufacturer populating the Exif data, so it will work in most cases, but it is not a 100% reliable solution.

ExifInterface ei = new ExifInterface(photoPath); int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,                                      ExifInterface.ORIENTATION_UNDEFINED);  Bitmap rotatedBitmap = null; switch(orientation) {      case ExifInterface.ORIENTATION_ROTATE_90:         rotatedBitmap = rotateImage(bitmap, 90);         break;      case ExifInterface.ORIENTATION_ROTATE_180:         rotatedBitmap = rotateImage(bitmap, 180);         break;      case ExifInterface.ORIENTATION_ROTATE_270:         rotatedBitmap = rotateImage(bitmap, 270);         break;      case ExifInterface.ORIENTATION_NORMAL:     default:         rotatedBitmap = bitmap; } 

Here is the rotateImage method:

public static Bitmap rotateImage(Bitmap source, float angle) {     Matrix matrix = new Matrix();     matrix.postRotate(angle);     return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),                                matrix, true); } 
like image 169
Jason Robinson Avatar answered Oct 26 '22 23:10

Jason Robinson


By combining Jason Robinson's answer with Felix's answer and filling the missing parts, here is the final complete solution for this issue that will do the following after testing it on Android Android 4.1 (Jelly Bean), Android 4.4 (KitKat) and Android 5.0 (Lollipop).

Steps

  1. Scale down the image if it was bigger than 1024x1024.

  2. Rotate the image to the right orientation only if it was rotate 90, 180 or 270 degree.

  3. Recycle the rotated image for memory purposes.

Here is the code part:

Call the following method with the current Context and the image URI that you want to fix

/**  * This method is responsible for solving the rotation issue if exist. Also scale the images to  * 1024x1024 resolution  *  * @param context       The current context  * @param selectedImage The Image URI  * @return Bitmap image results  * @throws IOException  */ public static Bitmap handleSamplingAndRotationBitmap(Context context, Uri selectedImage)         throws IOException {     int MAX_HEIGHT = 1024;     int MAX_WIDTH = 1024;      // First decode with inJustDecodeBounds=true to check dimensions     final BitmapFactory.Options options = new BitmapFactory.Options();     options.inJustDecodeBounds = true;     InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);     BitmapFactory.decodeStream(imageStream, null, options);     imageStream.close();      // Calculate inSampleSize     options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);      // Decode bitmap with inSampleSize set     options.inJustDecodeBounds = false;     imageStream = context.getContentResolver().openInputStream(selectedImage);     Bitmap img = BitmapFactory.decodeStream(imageStream, null, options);      img = rotateImageIfRequired(context, img, selectedImage);     return img; } 

Here is the CalculateInSampleSize method from the pre mentioned source:

/**   * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding   * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates   * the closest inSampleSize that will result in the final decoded bitmap having a width and   * height equal to or larger than the requested width and height. This implementation does not   * ensure a power of 2 is returned for inSampleSize which can be faster when decoding but   * results in a larger bitmap which isn't as useful for caching purposes.   *   * @param options   An options object with out* params already populated (run through a decode*   *                  method with inJustDecodeBounds==true   * @param reqWidth  The requested width of the resulting bitmap   * @param reqHeight The requested height of the resulting bitmap   * @return The value to be used for inSampleSize   */ private static int calculateInSampleSize(BitmapFactory.Options options,                                          int reqWidth, int reqHeight) {     // Raw height and width of image     final int height = options.outHeight;     final int width = options.outWidth;     int inSampleSize = 1;      if (height > reqHeight || width > reqWidth) {          // Calculate ratios of height and width to requested height and width         final int heightRatio = Math.round((float) height / (float) reqHeight);         final int widthRatio = Math.round((float) width / (float) reqWidth);          // Choose the smallest ratio as inSampleSize value, this will guarantee a final image         // with both dimensions larger than or equal to the requested height and width.         inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;          // This offers some additional logic in case the image has a strange         // aspect ratio. For example, a panorama may have a much larger         // width than height. In these cases the total pixels might still         // end up being too large to fit comfortably in memory, so we should         // be more aggressive with sample down the image (=larger inSampleSize).          final float totalPixels = width * height;          // Anything more than 2x the requested pixels we'll sample down further         final float totalReqPixelsCap = reqWidth * reqHeight * 2;          while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {             inSampleSize++;         }     }     return inSampleSize; } 

Then comes the method that will check the current image orientation to decide the rotation angle

 /**  * Rotate an image if required.  *  * @param img           The image bitmap  * @param selectedImage Image URI  * @return The resulted Bitmap after manipulation  */ private static Bitmap rotateImageIfRequired(Context context, Bitmap img, Uri selectedImage) throws IOException {  InputStream input = context.getContentResolver().openInputStream(selectedImage); ExifInterface ei; if (Build.VERSION.SDK_INT > 23)     ei = new ExifInterface(input); else     ei = new ExifInterface(selectedImage.getPath());      int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);      switch (orientation) {         case ExifInterface.ORIENTATION_ROTATE_90:             return rotateImage(img, 90);         case ExifInterface.ORIENTATION_ROTATE_180:             return rotateImage(img, 180);         case ExifInterface.ORIENTATION_ROTATE_270:             return rotateImage(img, 270);         default:             return img;     } } 

Finally the rotation method itself

private static Bitmap rotateImage(Bitmap img, int degree) {     Matrix matrix = new Matrix();     matrix.postRotate(degree);     Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);     img.recycle();     return rotatedImg; } 

-Don't forget to vote up for those guys answers for their efforts and Shirish Herwade who asked this helpful question.

like image 41
Sami Eltamawy Avatar answered Oct 27 '22 00:10

Sami Eltamawy