Photo rotated from camera (SAMSUNG device)

UPD 29.08.2018 I found that this method doesn't work with Samsung device based on Android 8+. I don't have Samsung s8 (for example) and can't understand why this again does not work there. If someone can test and check why this not work - let's try to fix this together.


I found how to fix: well it's really stupid and very hard for me.

First step get activity result

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {

            String _path = Environment.getExternalStorageDirectory() + File.separator + "TakenFromCamera.jpg";
            String p1 = Environment.getExternalStorageDirectory().toString();
            String fName = "/TakenFromCamera.jpg";
            final int rotation = getImageOrientation(_path);
            File file = resaveBitmap(p1, fName, rotation);
            Bitmap mBitmap = BitmapFactory.decodeFile(_path);

Main steps it's getImageOrientation before changes in file.

  1. getImageOrientation (by path)
  2. resave file (if need send to server, if you need only for preview we can skip this step)
  3. get correct bitmap from file

For preview it's enough to perform only steps 1 and 3, and using this function - just rotate bitmap.

private Bitmap checkRotationFromCamera(Bitmap bitmap, String pathToFile, int rotate) {
        Matrix matrix = new Matrix();
        matrix.postRotate(rotate);
        Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return rotatedBitmap;
    }

getImageOrientation

public static int getImageOrientation(String imagePath) {
    int rotate = 0;
    try {
        ExifInterface exif = new ExifInterface(imagePath);
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_270:
                rotate = 270;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotate = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotate = 90;
                break;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return rotate;
}

and resaveBitmap if need

private File resaveBitmap(String path, String filename, int rotation) { //help for fix landscape photos
        String extStorageDirectory = path;
        OutputStream outStream = null;
        File file = new File(filename);
        if (file.exists()) {
            file.delete();
            file = new File(extStorageDirectory, filename);
        }
        try {
            // make a new bitmap from your file
            Bitmap bitmap = BitmapFactory.decodeFile(path + filename);
            bitmap = checkRotationFromCamera(bitmap, path + filename, rotation);
            bitmap = Bitmap.createScaledBitmap(bitmap, (int) ((float) bitmap.getWidth() * 0.3f), (int) ((float) bitmap.getHeight() * 0.3f), false);
            bitmap = Utils.getCircleImage(bitmap);
            outStream = new FileOutputStream(path + filename);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            outStream.flush();
            outStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

If you want to rotate an image but you only have the byte array, you can use this:

private byte[] rotationFromCamera(byte[] data) {
    int rotation = Exif.getOrientation(data);
    if(rotation == 0) return data;
    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, null);
    Matrix matrix = new Matrix();
    matrix.postRotate(rotation);
    Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
    return stream.toByteArray();
}

and this exif util from this answer

This is a bit slow if the image is large.


Found this here, works for me Samsung S8.

static final String[] CONTENT_ORIENTATION = new String[] {
            MediaStore.Images.ImageColumns.ORIENTATION
    };


public static int getExifOrientation(Context context, Uri uri) {
    ContentResolver contentResolver = context.getContentResolver();
    Cursor cursor = null;
    try {
        String id = DocumentsContract.getDocumentId(uri);
        id = id.split(":")[1];
        cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                CONTENT_ORIENTATION, MediaStore.Images.Media._ID + " = ?", new String[] { id }, null);
        if (cursor == null || !cursor.moveToFirst()) {
            return 0;
        }
        return cursor.getInt(0);
    } catch (RuntimeException ignored) {
        // If the orientation column doesn't exist, assume no rotation.
        return 0;
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}

This works when I get the image from Gallery Intent.ACTION_GET_CONTENT.

Tested it with MediaStore.ACTION_IMAGE_CAPTURE, and it returned 0. But maybe I'm doing something wrong.