Android: Bitmaps loaded from gallery are rotated in ImageView

AndroidBitmapRotationGallery

Android Problem Overview


When I load an image from the media gallery into a Bitmap, everything is working fine, except that pictures that were shot with the camera while holding the phone vertically, are rotated so that I always get a horizontal picture even though it appears vertical in the gallery. Why is that and how can I load it correctly?

Android Solutions


Solution 1 - Android

So, as an example...

First you need to create an ExifInterface:

ExifInterface exif = new ExifInterface(filename);

You can then grab the orientation of the image:

orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);

Here's what the orientation values mean: http://sylvana.net/jpegcrop/exif_orientation.html

So, the most important values are 3, 6 and 8. If the orientation is ExifInterface.ORIENTATION_ROTATE_90 (which is 6), for example, you can rotate the image like this:

Matrix matrix = new Matrix();
matrix.postRotate(90);
rotatedBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), matrix, true);

That's just a quick example, though. I'm sure there are other ways of performing the actual rotation. But you will find those on StackOverflow as well.

Solution 2 - Android

This is a full solution (found in the Hackbook example from the Facebook SDK). It has the advantage of not needing access to the file itself. This is extremely useful if you are loading an image from the content resolver thingy (e.g. if your app is responding to a share-photo intent).

public static int getOrientation(Context context, Uri photoUri) {
    /* it's on the external media. */
    Cursor cursor = context.getContentResolver().query(photoUri,
            new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);

    if (cursor.getCount() != 1) {
        return -1;
    }

    cursor.moveToFirst();
    return cursor.getInt(0);
}

And then you can get a rotated Bitmap as follows. This code also scales down the image (badly unfortunately) to MAX_IMAGE_DIMENSION. Otherwise you may run out of memory.

public static Bitmap getCorrectlyOrientedImage(Context context, Uri photoUri) throws IOException {
    InputStream is = context.getContentResolver().openInputStream(photoUri);
    BitmapFactory.Options dbo = new BitmapFactory.Options();
    dbo.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(is, null, dbo);
    is.close();

    int rotatedWidth, rotatedHeight;
    int orientation = getOrientation(context, photoUri);

    if (orientation == 90 || orientation == 270) {
        rotatedWidth = dbo.outHeight;
        rotatedHeight = dbo.outWidth;
    } else {
        rotatedWidth = dbo.outWidth;
        rotatedHeight = dbo.outHeight;
    }

    Bitmap srcBitmap;
    is = context.getContentResolver().openInputStream(photoUri);
    if (rotatedWidth > MAX_IMAGE_DIMENSION || rotatedHeight > MAX_IMAGE_DIMENSION) {
        float widthRatio = ((float) rotatedWidth) / ((float) MAX_IMAGE_DIMENSION);
        float heightRatio = ((float) rotatedHeight) / ((float) MAX_IMAGE_DIMENSION);
        float maxRatio = Math.max(widthRatio, heightRatio);

        // Create the bitmap from file
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = (int) maxRatio;
        srcBitmap = BitmapFactory.decodeStream(is, null, options);
    } else {
        srcBitmap = BitmapFactory.decodeStream(is);
    }
    is.close();

    /*
     * if the orientation is not 0 (or -1, which means we don't know), we
     * have to do a rotation.
     */
    if (orientation > 0) {
        Matrix matrix = new Matrix();
        matrix.postRotate(orientation);

        srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(),
                srcBitmap.getHeight(), matrix, true);
    }

    return srcBitmap;
}

Solution 3 - Android

Solved it in my case with this code using help of this post:

            Bitmap myBitmap = getBitmap(imgFile.getAbsolutePath());
            
            try {
            	ExifInterface exif = new ExifInterface(imgFile.getAbsolutePath());
            	int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
            	Log.d("EXIF", "Exif: " + orientation);
            	Matrix matrix = new Matrix();
            	if (orientation == 6) {
            		matrix.postRotate(90);
            	}
            	else if (orientation == 3) {
            		matrix.postRotate(180);
            	}
            	else if (orientation == 8) {
            		matrix.postRotate(270);
            	}
        		myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, myBitmap.getWidth(), myBitmap.getHeight(), matrix, true); // rotating bitmap
            }
            catch (Exception e) {
            	
            }
            ImageView img = (ImageView) findViewById(R.id.imgTakingPic);
            img.setImageBitmap(myBitmap);

Hope it saves someone's time!

Solution 4 - Android

Use a Utility to do the Heavy Lifting.

9re created a simple utility to handle the heavy lifting of dealing with EXIF data and rotating images to their correct orientation.

You can find the utility code here: https://gist.github.com/9re/1990019

Simply download this, add it to your project's src directory and use ExifUtil.rotateBitmap() to get the correct orientation, like so:

String imagePath = photoFile.getAbsolutePath();             // photoFile is a File class.
Bitmap myBitmap  = BitmapFactory.decodeFile(imagePath);

Bitmap orientedBitmap = ExifUtil.rotateBitmap(imagePath, myBitmap);

Solution 5 - Android

Have you looked at the EXIF data of the images? It may know the orientation of the camera when the picture was taken.

Solution 6 - Android

Kotlin code:

if (file.exists()){
    val bitmap = BitmapFactory.decodeFile(file.absolutePath)

    val exif = ExifInterface(file.absoluteFile.toString())
    val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
    val matrix = Matrix()

    when(orientation){
        ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90F)
        ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180F)
        ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270F)
    }

    val rotatedBitmap = Bitmap.createBitmap(bitmap, 0,0 , bitmap.width, bitmap.height, matrix, true)
    bitmap.recycle()
    iv_capture.setImageBitmap(rotatedBitmap)
}

Solution 7 - Android

its because gallery correct displaying rotated images but not ImageView look at here:

                    myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(),optionss);
					ExifInterface exif = new ExifInterface(selectedImagePath);
					int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
					int rotationInDegrees = exifToDegrees(rotation);
					deg = rotationInDegrees;
					Matrix matrix = new Matrix();
					if (rotation != 0f) {
						matrix.preRotate(rotationInDegrees);
						myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, myBitmap.getWidth(), myBitmap.getHeight(), matrix, true);
					}

and you need this:

private static int exifToDegrees(int 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;    
} 

Solution 8 - Android

Got it to work after many attempts thanks to a post I can no longer find :-(

Exif seems to work always, the difficulty was to get the filepath. The code I found makes a different between API older than 4.4 and after 4.4. Basically the picture URI for 4.4+ contains "com.android.providers". For this type of URI, the code uses DocumentsContract to get the picture id and then runs a query using the ContentResolver, while for older SDK, the code goes straight to query the URI with the ContentResolver.

Here is the code (sorry I cannot credit who posted it):

/**
 * Handles pre V19 uri's
 * @param context
 * @param contentUri
 * @return
 */
public static String getPathForPreV19(Context context, Uri contentUri) {
    String res = null;

    String[] proj = { MediaStore.Images.Media.DATA };
    Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
    if(cursor.moveToFirst()){;
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        res = cursor.getString(column_index);
    }
    cursor.close();

    return res;
}

/**
 * Handles V19 and up uri's
 * @param context
 * @param contentUri
 * @return path
 */
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPathForV19AndUp(Context context, Uri contentUri) {
    String wholeID = DocumentsContract.getDocumentId(contentUri);

    // Split at colon, use second item in the array
    String id = wholeID.split(":")[1];
    String[] column = { MediaStore.Images.Media.DATA };

    // where id is equal to
    String sel = MediaStore.Images.Media._ID + "=?";
    Cursor cursor = context.getContentResolver().
            query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    column, sel, new String[]{ id }, null);

    String filePath = "";
    int columnIndex = cursor.getColumnIndex(column[0]);
    if (cursor.moveToFirst()) {
        filePath = cursor.getString(columnIndex);
    }

    cursor.close();
    return filePath;
}

public static String getRealPathFromURI(Context context,
		Uri contentUri) {
	String uriString = String.valueOf(contentUri);
	boolean goForKitKat= uriString.contains("com.android.providers");
	
	 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && goForKitKat) {
	        Log.i("KIKAT","YES");
		 	return getPathForV19AndUp(context, contentUri);
	    } else {
	        
	    	return getPathForPreV19(context, contentUri);
	    }
}

Solution 9 - Android

You can just read the path from sd card and do the following code...it'll Replace the existing photo after rotating it..

Not: Exif doesnt work on most of the devices, it gives the wrong data so it's good to hard code the rotating before saving to any degree you want to,You just have to change the angle value in postRotate to any you want to.

	String photopath = tempphoto.getPath().toString();
	Bitmap bmp = BitmapFactory.decodeFile(photopath);

	Matrix matrix = new Matrix();
	matrix.postRotate(90);
	bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);

	FileOutputStream fOut;
	try {
		fOut = new FileOutputStream(tempphoto);
		bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
		fOut.flush();
		fOut.close();

	} catch (FileNotFoundException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

}

Solution 10 - Android

I improved upon the answer by Teo Inke. It no longer rotates the image unless it is actually necessary. It is also easier to read, and should run faster.

// Load Image
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
	            
// Rotate Image if Needed
try
{
	// Determine Orientation
	ExifInterface exif = new ExifInterface(filePath);
	int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
	                
	// Determine Rotation
	int rotation = 0;
	if      (orientation == 6) 		rotation = 90;
	else if (orientation == 3) 		rotation = 180;
	else if (orientation == 8) 		rotation = 270;
	                
	// Rotate Image if Necessary
	if (rotation != 0)
	{
	   	// Create Matrix
	   	Matrix matrix = new Matrix();
	   	matrix.postRotate(rotation);
	                	
	   	// Rotate Bitmap
	   	Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 
	                	
	    // Pretend none of this ever happened!
	    bitmap.recycle();
	    bitmap = rotated;
	    rotated = null;
	 }
}
catch (Exception e)
{
	// TODO: Log Error Messages Here
}

// TODO: Use Result Here
xxx.setBitmap(bitmap);

Solution 11 - Android

The first thing you need is the real File path If you have it great, if you are using URI then use this method to get the real Path:

 public static String getRealPathFromURI(Uri contentURI,Context context) {
    String path= contentURI.getPath();
    try {
        Cursor cursor = context.getContentResolver().query(contentURI, null, null, null, null);
        cursor.moveToFirst();
        String document_id = cursor.getString(0);
        document_id = document_id.substring(document_id.lastIndexOf(":") + 1);
        cursor.close();

        cursor = context.getContentResolver().query(
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null);
        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
    }
    catch(Exception e)
    {
        return path;
    }
    return path;
}

extract your Bitmap for example:

  try {
                            Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImage);
                    
                        }
                        catch (IOException e)
                        {
                            Log.e("IOException",e.toString());
                        }

you can use decodeFile() instead if you wish.

Now that you have the Bitmap and the real Path get the Orientation of the Image:

 private static int getExifOrientation(String src) throws IOException {
        int orientation = 1;

        ExifInterface exif = new ExifInterface(src);
        String orientationString=exif.getAttribute(ExifInterface.TAG_ORIENTATION);
        try {
            orientation = Integer.parseInt(orientationString);
        }
        catch(NumberFormatException e){}
        
        return orientation;
    }

and finally rotate it to the right position like so:

public static Bitmap rotateBitmap(String src, Bitmap bitmap) {
        try {
            int orientation = getExifOrientation(src);

            if (orientation == 1) {
                return bitmap;
            }

            Matrix matrix = new Matrix();
            switch (orientation) {
                case 2:
                    matrix.setScale(-1, 1);
                    break;
                case 3:
                    matrix.setRotate(180);
                    break;
                case 4:
                    matrix.setRotate(180);
                    matrix.postScale(-1, 1);
                    break;
                case 5:
                    matrix.setRotate(90);
                    matrix.postScale(-1, 1);
                    break;
                case 6:
                    matrix.setRotate(90);
                    break;
                case 7:
                    matrix.setRotate(-90);
                    matrix.postScale(-1, 1);
                    break;
                case 8:
                    matrix.setRotate(-90);
                    break;
                default:
                    return bitmap;
            }

            try {
                Bitmap oriented = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                bitmap.recycle();
                return oriented;
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                return bitmap;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmap;
    }

That's it , you now have the bitmap rotated to the right position.

cheers.

Solution 12 - Android

This works, but probably not the best way to do it, but it might help someone.

String imagepath = someUri.getAbsolutePath();
imageview = (ImageView)findViewById(R.id.imageview);
imageview.setImageBitmap(setImage(imagepath, 120, 120));    

public Bitmap setImage(String path, final int targetWidth, final int targetHeight) {
	Bitmap bitmap = null;
// Get exif orientation		
	try {
        ExifInterface exif = new ExifInterface(path);
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
        if (orientation == 6) {
            orientation_val = 90;
        }
        else if (orientation == 3) {
        	orientation_val = 180;
        }
        else if (orientation == 8) {
        	orientation_val = 270;
        }
	}
        catch (Exception e) {
        }

		try {
// First decode with inJustDecodeBounds=true to check dimensions
	        final BitmapFactory.Options options = new BitmapFactory.Options();
	        options.inJustDecodeBounds = true;
	        BitmapFactory.decodeFile(path, options);

// Adjust extents
	        int sourceWidth, sourceHeight;
	        if (orientation_val == 90 || orientation_val == 270) {
	            sourceWidth = options.outHeight;
	            sourceHeight = options.outWidth;
	        } else {
	            sourceWidth = options.outWidth;
	            sourceHeight = options.outHeight;
	        }

// Calculate the maximum required scaling ratio if required and load the bitmap
	        if (sourceWidth > targetWidth || sourceHeight > targetHeight) {
	            float widthRatio = (float)sourceWidth / (float)targetWidth;
	            float heightRatio = (float)sourceHeight / (float)targetHeight;
	            float maxRatio = Math.max(widthRatio, heightRatio);
	            options.inJustDecodeBounds = false;
	            options.inSampleSize = (int)maxRatio;
	            bitmap = BitmapFactory.decodeFile(path, options);
	        } else {
	            bitmap = BitmapFactory.decodeFile(path);
	        }

// Rotate the bitmap if required
	        if (orientation_val > 0) {
	            Matrix matrix = new Matrix();
	            matrix.postRotate(orientation_val);
	            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
	        }

// Re-scale the bitmap if necessary
	        sourceWidth = bitmap.getWidth();
	        sourceHeight = bitmap.getHeight();
	        if (sourceWidth != targetWidth || sourceHeight != targetHeight) {
	            float widthRatio = (float)sourceWidth / (float)targetWidth;
	            float heightRatio = (float)sourceHeight / (float)targetHeight;
	            float maxRatio = Math.max(widthRatio, heightRatio);
	            sourceWidth = (int)((float)sourceWidth / maxRatio);
	            sourceHeight = (int)((float)sourceHeight / maxRatio);
	            bitmap = Bitmap.createScaledBitmap(bitmap, sourceWidth,     sourceHeight, true);
	        }
	    } catch (Exception e) {
	    }
	    return bitmap;
	}

Solution 13 - Android

The methods below scales AND rotates the bitmap according to the orientation:

public Bitmap scaleAndRotateImage(String path, int orientation, final int targetWidth, final int targetHeight)
{
    Bitmap bitmap = null;

    try
    {
        // Check the dimensions of the Image
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        // Adjust the Width and Height
        int sourceWidth, sourceHeight;
        if (orientation == 90 || orientation == 270)
        {
            sourceWidth = options.outHeight;
            sourceHeight = options.outWidth;
        }
        else
        {
            sourceWidth = options.outWidth;
            sourceHeight = options.outHeight;
        }

        // Calculate the maximum required scaling ratio if required and load the bitmap
        if (sourceWidth > targetWidth || sourceHeight > targetHeight)
        {
            float widthRatio = (float)sourceWidth / (float)targetWidth;
            float heightRatio = (float)sourceHeight / (float)targetHeight;
            float maxRatio = Math.max(widthRatio, heightRatio);
            options.inJustDecodeBounds = false;
            options.inSampleSize = (int)maxRatio;
            bitmap = BitmapFactory.decodeFile(path, options);
        }
        else
        {
            bitmap = BitmapFactory.decodeFile(path);
        }

        // We need to rotate the bitmap (if required)
        int orientationInDegrees = exifToDegrees(orientation);
        if (orientation > 0)
        {
            Matrix matrix = new Matrix();
            if (orientation != 0f)
            {
                matrix.preRotate(orientationInDegrees);
            };

            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }

        // Re-scale the bitmap if necessary
        sourceWidth = bitmap.getWidth();
        sourceHeight = bitmap.getHeight();

        if (sourceWidth != targetWidth || sourceHeight != targetHeight)
        {
            float widthRatio = (float)sourceWidth / (float)targetWidth;
            float heightRatio = (float)sourceHeight / (float)targetHeight;
            float maxRatio = Math.max(widthRatio, heightRatio);
            sourceWidth = (int)((float)sourceWidth / maxRatio);
            sourceHeight = (int)((float)sourceHeight / maxRatio);
            bitmap = Bitmap.createScaledBitmap(bitmap, sourceWidth, sourceHeight, true);
        }
    }
    catch (Exception e)
    {
        Logger.d("Could not rotate the image");
        Logger.d(e.getMessage());
    }
    return bitmap;
}

Example:

public void getPictureFromDevice(Uri Uri,ImageView imageView)
{
    try
    {
        ExifInterface exifInterface = new ExifInterface(Uri.getPath());
        int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

        Bitmap bitmap = scaleAndRotateImage(Uri.getPath(), orientation, imageView.getWidth(), imageView.getHeight());
        imageView.setImageBitmap(bitmap);
    }
    catch (OutOfMemoryError outOfMemoryError)
    {
        Logger.d(outOfMemoryError.getLocalizedMessage());
        Logger.d("Failed to load image from filePath (out of memory)");
        Logger.d(Uri.toString());
    }
    catch (Exception e)
    {
        Logger.d("Failed to load image from filePath");
        Logger.d(Uri.toString());
    }
}

Solution 14 - Android

maybe this will help (rotate 90 degree)(this worked for me)

private Bitmap rotateBitmap(Bitmap image){
		int width=image.getHeight();
		int height=image.getWidth();
		
		Bitmap srcBitmap=Bitmap.createBitmap(width, height, image.getConfig());
		
		for (int y=width-1;y>=0;y--)
			for(int x=0;x<height;x++)
				srcBitmap.setPixel(width-y-1, x,image.getPixel(x, y));
		return srcBitmap;
		
	}

Solution 15 - Android

The cursor should be closed after opening it.

Here is an example.

 public static int getOrientation(Context context, Uri selectedImage)
{
    int orientation = -1;
    Cursor cursor = context.getContentResolver().query(selectedImage,
            new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
    if (cursor.getCount() != 1)
       return orientation;

    cursor.moveToFirst();
    orientation = cursor.getInt(0);
    cursor.close(); // ADD THIS LINE
   return orientation;
}

Solution 16 - Android

I have melted @Timmmm answer and @Manuel. If you do this solution, you will not get a Run Out Of Memory Exception.

This method retrieves the image orientation:

private static final int ROTATION_DEGREES = 90;
// This means 512 px
private static final Integer MAX_IMAGE_DIMENSION = 512;

public static int getOrientation(Uri photoUri) throws IOException {

    ExifInterface exif = new ExifInterface(photoUri.getPath());
    int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);

    switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            orientation = ROTATION_DEGREES;
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            orientation = ROTATION_DEGREES * 2;
            break;
        case ExifInterface.ORIENTATION_ROTATE_270:
            orientation = ROTATION_DEGREES * 3;
            break;
        default:
            // Default case, image is not rotated
            orientation = 0;
    }

    return orientation;
}

Therefore, you would use this method to resize image before load it on memory. In that way, you will not get a Memory Exception.

public static Bitmap getCorrectlyOrientedImage(Context context, Uri photoUri) throws IOException {
    InputStream is = context.getContentResolver().openInputStream(photoUri);
    BitmapFactory.Options dbo = new BitmapFactory.Options();
    dbo.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(is, null, dbo);
    is.close();

    int rotatedWidth, rotatedHeight;
    int orientation = getOrientation(photoUri);

    if (orientation == 90 || orientation == 270) {
        rotatedWidth = dbo.outHeight;
        rotatedHeight = dbo.outWidth;
    } else {
        rotatedWidth = dbo.outWidth;
        rotatedHeight = dbo.outHeight;
    }

    Bitmap srcBitmap;
    is = context.getContentResolver().openInputStream(photoUri);
    if (rotatedWidth > MAX_IMAGE_DIMENSION || rotatedHeight > MAX_IMAGE_DIMENSION) {
        float widthRatio = ((float) rotatedWidth) / ((float) MAX_IMAGE_DIMENSION);
        float heightRatio = ((float) rotatedHeight) / ((float) MAX_IMAGE_DIMENSION);
        float maxRatio = Math.max(widthRatio, heightRatio);

        // Create the bitmap from file
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = (int) maxRatio;
        srcBitmap = BitmapFactory.decodeStream(is, null, options);
    } else {
        srcBitmap = BitmapFactory.decodeStream(is);
    }
    is.close();

    // if the orientation is not 0, we have to do a rotation.
    if (orientation > 0) {
        Matrix matrix = new Matrix();
        matrix.postRotate(orientation);

        srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(),
                srcBitmap.getHeight(), matrix, true);
    }

    return srcBitmap;
}

This works perfectly for me. I hope this helps somebody else

Solution 17 - Android

Improving on the solution above by Timmmm to add some extra scaling at the end to ensure that the image fits within the bounds:

public static Bitmap loadBitmap(String path, int orientation, final int targetWidth, final int targetHeight) {
	Bitmap bitmap = null;
	try {
		// First decode with inJustDecodeBounds=true to check dimensions
	    final BitmapFactory.Options options = new BitmapFactory.Options();
	    options.inJustDecodeBounds = true;
	    BitmapFactory.decodeFile(path, options);
	    
	    // Adjust extents
	    int sourceWidth, sourceHeight;
	    if (orientation == 90 || orientation == 270) {
	    	sourceWidth = options.outHeight;
	    	sourceHeight = options.outWidth;
	    } else {
	    	sourceWidth = options.outWidth;
	    	sourceHeight = options.outHeight;
	    }
	    
	    // Calculate the maximum required scaling ratio if required and load the bitmap
	    if (sourceWidth > targetWidth || sourceHeight > targetHeight) {
	    	float widthRatio = (float)sourceWidth / (float)targetWidth;
	    	float heightRatio = (float)sourceHeight / (float)targetHeight;
	    	float maxRatio = Math.max(widthRatio, heightRatio);
	    	options.inJustDecodeBounds = false;
	    	options.inSampleSize = (int)maxRatio;
	    	bitmap = BitmapFactory.decodeFile(path, options);
	    } else {
	    	bitmap = BitmapFactory.decodeFile(path);
	    }
	    
	    // Rotate the bitmap if required
	    if (orientation > 0) {
	    	Matrix matrix = new Matrix();
	    	matrix.postRotate(orientation);
	    	bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
	    }
	    
	    // Re-scale the bitmap if necessary
	    sourceWidth = bitmap.getWidth();
	    sourceHeight = bitmap.getHeight();
	    if (sourceWidth != targetWidth || sourceHeight != targetHeight) {
	    	float widthRatio = (float)sourceWidth / (float)targetWidth;
	    	float heightRatio = (float)sourceHeight / (float)targetHeight;
	    	float maxRatio = Math.max(widthRatio, heightRatio);
    		sourceWidth = (int)((float)sourceWidth / maxRatio);
    		sourceHeight = (int)((float)sourceHeight / maxRatio);
	    	bitmap = Bitmap.createScaledBitmap(bitmap, sourceWidth, sourceHeight, true);
	    }
	} catch (Exception e) {
	}
	return bitmap;
}

Solution 18 - Android

Use the following code to rotate an image correctly:

private Bitmap rotateImage(Bitmap bitmap, String filePath)
{
    Bitmap resultBitmap = bitmap;

    try
    {
        ExifInterface exifInterface = new ExifInterface(filePath);
        int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);

        Matrix matrix = new Matrix();

        if (orientation == ExifInterface.ORIENTATION_ROTATE_90)
        {
            matrix.postRotate(ExifInterface.ORIENTATION_ROTATE_90);
        }
        else if (orientation == ExifInterface.ORIENTATION_ROTATE_180)
        {
            matrix.postRotate(ExifInterface.ORIENTATION_ROTATE_180);
        }
        else if (orientation == ExifInterface.ORIENTATION_ROTATE_270)
        {
            matrix.postRotate(ExifInterface.ORIENTATION_ROTATE_270);
        }

        // Rotate the bitmap
        resultBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    }
    catch (Exception exception)
    {
        Logger.d("Could not rotate the image");
    }
    return resultBitmap;
}

Solution 19 - Android

I solved the problem with the following workaround. Note that I am also scaling the image, which was necessary to avoid OutOfMemoryExceptions.

Beware that this solution will not work properly with portrait images or opside-down images (thank you Timmmm for noting). Timmmm's solution above might be the better choice if that is required and it looks more elegant, too: https://stackoverflow.com/a/8914291/449918

File path = // ... location of your bitmap file
int w = 512; int h = 384; // size that does not lead to OutOfMemoryException on Nexus One
Bitmap b = BitmapFactory.decodeFile(path);


// Hack to determine whether the image is rotated
boolean rotated = b.getWidth() > b.getHeight();

Bitmap resultBmp = null;

// If not rotated, just scale it
if (!rotated) {
	resultBmp = Bitmap.createScaledBitmap(b, w, h, true);
	b.recycle();
	b = null;

// If rotated, scale it by switching width and height and then rotated it
} else {
	Bitmap scaledBmp = Bitmap.createScaledBitmap(b, h, w, true);
	b.recycle();
	b = null;

	Matrix mat = new Matrix();
	mat.postRotate(90);
	resultBmp = Bitmap.createBitmap(scaledBmp, 0, 0, h, w, mat, true);

	// Release image resources
	scaledBmp.recycle();
	scaledBmp = null;
}

// resultBmp now contains the scaled and rotated image

Cheers

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionManuelView Question on Stackoverflow
Solution 1 - AndroidManuelView Answer on Stackoverflow
Solution 2 - AndroidTimmmmView Answer on Stackoverflow
Solution 3 - AndroidTeo InkeView Answer on Stackoverflow
Solution 4 - AndroidJoshua PinterView Answer on Stackoverflow
Solution 5 - AndroidJamesView Answer on Stackoverflow
Solution 6 - AndroidRahul KhatriView Answer on Stackoverflow
Solution 7 - Androidfarhad.kargaranView Answer on Stackoverflow
Solution 8 - AndroidGeorgesView Answer on Stackoverflow
Solution 9 - AndroidMayank SainiView Answer on Stackoverflow
Solution 10 - Androiduser2820531View Answer on Stackoverflow
Solution 11 - AndroidGal RomView Answer on Stackoverflow
Solution 12 - AndroiderebosView Answer on Stackoverflow
Solution 13 - AndroidNightBitsView Answer on Stackoverflow
Solution 14 - AndroidtzahibsView Answer on Stackoverflow
Solution 15 - AndroidGuillaume agisView Answer on Stackoverflow
Solution 16 - AndroidAntonioView Answer on Stackoverflow
Solution 17 - AndroidMeanmanView Answer on Stackoverflow
Solution 18 - AndroidNightBitsView Answer on Stackoverflow
Solution 19 - AndroidMartinView Answer on Stackoverflow