Skip to content
This repository has been archived by the owner on Jan 7, 2023. It is now read-only.

Cropped image is rotated sideways while the original image is not. #140

Open
MaxHastings opened this issue Jul 13, 2015 · 22 comments
Open
Labels

Comments

@MaxHastings
Copy link

The original image is rotated correctly while cropping it. However, the finished cropped image is rotated 90 degrees. I believe this bug only happens when the image is a certain aspect ratio. This seems to be happening on many different Android versions if not all.

@rondelrosario
Copy link

I have the same issue. This is very inconsistent as I have rotated it previously to handle it before and in another build I didn't need to.

@MaxHastings
Copy link
Author

Yeah I hope it gets fixed... It's a great library other than this bug...

@sergii-frost
Copy link
Contributor

Got same issue on Samsung Galaxy S4 with Android 4.4.2
At same time works perfectly on Nexus 5 with Android 5.1.1
Library version is 1.0.0

@sergii-frost
Copy link
Contributor

Possible fix is provided here #146

@KillerMeng
Copy link

In fact,your original image 's TAG_ORIENTATION are not 0 ,and the android-crop did not rotate to 0 degrees at last.

@abist
Copy link

abist commented Jul 27, 2015

The library actually uses the exif data to rotate, but it doesn't seem to work. What I did to rectify it was taking the data from onActivityResult and rotating it myself. Here's how to do it - http://stackoverflow.com/questions/20478765/how-to-get-the-correct-orientation-of-the-image-selected-from-the-default-image

It fixed the problem.

@kohchihao
Copy link

is there any fix??? im in need for this library to work .

@huyhu
Copy link

huyhu commented Aug 8, 2015

i have the same issue for Samsung Galaxy S3, LG G2 and LG G3

@zhenleiji
Copy link

I have the same issue for Sony Xperia Z2. When I worked with image, I had a lot of problem regarding rotation. After extensive research I found the solution for rotations issue. See below:

/**
 * Rotate a bitmap based on orientation metadata.
 * src - image path
 */
public static Bitmap rotateBitmap(String src) {
        Bitmap bitmap = BitmapFactory.decodeFile(src);
        try {
            ExifInterface exif = new ExifInterface(src);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

            Matrix matrix = new Matrix();
            switch (orientation) {
                case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                    matrix.setScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    matrix.setRotate(180);
                    break;
                case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                    matrix.setRotate(180);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_TRANSPOSE:
                    matrix.setRotate(90);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    matrix.setRotate(90);
                    break;
                case ExifInterface.ORIENTATION_TRANSVERSE:
                    matrix.setRotate(-90);
                    matrix.postScale(-1, 1);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    matrix.setRotate(-90);
                    break;
                case ExifInterface.ORIENTATION_NORMAL:
                case ExifInterface.ORIENTATION_UNDEFINED:
                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;
    }

@sydneyagcaoili
Copy link

I want a fix too

@MaxHastings
Copy link
Author

@zhenleiji Thanks your code seems to work perfectly 💯

@jdamcd jdamcd added the bug label Sep 7, 2015
@rawGH
Copy link

rawGH commented Sep 25, 2015

@sergii-frost Possible fix is provided here #146 >> this works for me (Samsung).

@sergii-frost
Copy link
Contributor

@rawGH thank you, this workaroud works currently.

@rafaelekol
Copy link

I have same issue on Samsung S4 with Android 5. When image is taken in portrait mode.
I tried to get exif.orientation from original image and I get it correct. But when I sent image to crop and receive it back its get turned CCW 90. It would be cool to pass and receive image original orientation to crop library.

@FKSI
Copy link

FKSI commented Oct 10, 2015

Any fix? I've got the same issues and none of the fix mentionned above worked for me :(. I don't have any issues with my Sony Xperia Z1.

@sandrocsimas
Copy link

Need this fix too =(

@Sandrichka22
Copy link

This happens to all my images also, if they have an orientation different than 0. Non of the above solutions works for me. I liked this library more than any other else, but I can't use it with this bug present.. Someone please share if you have a solution

@sergii-frost
Copy link
Contributor

@sandro-csimas @Sandrichka22 thanks to @rawGH and #146 I simply created my own ImageUtils class which looks like this: https://gist.github.com/sergii-frost/04204f8fb708ee6f60ef

And then just before setting your processed image to your ˆmageView (e.g. previewImage) you can simply do like this:

ImageUtils.normalizeImageForUri(this, uri);
previewImage.setImageURI(uri);

Hope this helps ;)

@Sandrichka22
Copy link

@sergii-frost yes, it did help. Thank you very much. I am going to go with this solution. Thx

@amitclickapps
Copy link

This issue is much common in Samsung devices. The images choosen from Gallery or camera are rotated and when sent to Cropper for cropping it rotates. So there is a simple solution for this that i have opted. Before calling the method Crop.of(source, dest).asSquare() use below method to get the real path of the Gallery image or camera image and then send that path as source to the Crop lib method. It works like charm :)

http://stackoverflow.com/questions/20067508/get-real-path-from-uri-android-kitkat-new-storage-access-framework

/**

  • Get a file path from a Uri. This will get the the path for Storage Access

  • Framework Documents, as well as the _data field for the MediaStore and

  • other file-based ContentProviders.
    *

  • @param context The context.

  • @param uri The Uri to query.

  • @author paulburke
    */
    public static String getPath(final Context context, final Uri uri) {

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
    // ExternalStorageProvider
    if (isExternalStorageDocument(uri)) {
    final String docId = DocumentsContract.getDocumentId(uri);
    final String[] split = docId.split(":");
    final String type = split[0];

        if ("primary".equalsIgnoreCase(type)) {
            return Environment.getExternalStorageDirectory() + "/" + split[1];
        }
    
        // TODO handle non-primary volumes
    }
    // DownloadsProvider
    else if (isDownloadsDocument(uri)) {
    
        final String id = DocumentsContract.getDocumentId(uri);
        final Uri contentUri = ContentUris.withAppendedId(
                Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
    
        return getDataColumn(context, contentUri, null, null);
    }
    // MediaProvider
    else if (isMediaDocument(uri)) {
        final String docId = DocumentsContract.getDocumentId(uri);
        final String[] split = docId.split(":");
        final String type = split[0];
    
        Uri contentUri = null;
        if ("image".equals(type)) {
            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        } else if ("video".equals(type)) {
            contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        } else if ("audio".equals(type)) {
            contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        }
    
        final String selection = "_id=?";
        final String[] selectionArgs = new String[] {
                split[1]
        };
    
        return getDataColumn(context, contentUri, selection, selectionArgs);
    }
    

    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
    return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
    return uri.getPath();
    }

    return null;
    }

/**

  • Get the value of the data column for this Uri. This is useful for

  • MediaStore Uris, and other file-based ContentProviders.
    *

  • @param context The context.

  • @param uri The Uri to query.

  • @param selection (Optional) Filter used in the query.

  • @param selectionArgs (Optional) Selection arguments used in the query.

  • @return The value of the _data column, which is typically a file path.
    */
    public static String getDataColumn(Context context, Uri uri, String selection,
    String[] selectionArgs) {

    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {
    column
    };

    try {
    cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
    null);
    if (cursor != null && cursor.moveToFirst()) {
    final int column_index = cursor.getColumnIndexOrThrow(column);
    return cursor.getString(column_index);
    }
    } finally {
    if (cursor != null)
    cursor.close();
    }
    return null;
    }

/**

  • @param uri The Uri to check.
  • @return Whether the Uri authority is ExternalStorageProvider.
    */
    public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

/**

  • @param uri The Uri to check.
  • @return Whether the Uri authority is DownloadsProvider.
    */
    public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

/**

  • @param uri The Uri to check.
  • @return Whether the Uri authority is MediaProvider.
    */
    public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

@Sandrichka22
Copy link

Thank you for your solution as well. I still think that I would prefer @sergii-frost's solution because it works with Uri and not file path. I think it's better if you manipulate Uri. Still, I think that this problem should be solved in the upcoming releases of the library because it's a bug that it's obvious and in my opinion important. As for the devices that the bug is experienced on, I have tested with Samsung and LG devices so far. Thank you for your feedback again.

@ncornette
Copy link

Hi, I created a branch with added camera shoot feature in the example app. The purpose is to help fixing the orientation issue especially on Samsung devices...

Feel free to test or merge this branch to speed up development !

https://github.com/ncornette/android-crop/tree/example-shoot

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests