jayrambhia / CropperNoCropper

Instagram Style Image Cropper for Android (Library)
http://www.jayrambhia.com/project/nocropper-library
Apache License 2.0
475 stars 99 forks source link

Images from gallery and camera are rotated. #15

Closed skined90 closed 7 years ago

skined90 commented 7 years ago

On some devices, when I get image from gallery or camera intent, they are rotated in the crop view. I've tested it on LG G3 and Samsung Galaxy Note 3.

vbuberen commented 7 years ago

@skined90 On some devices the camera itself is rotated physically, so you get rotated images. But users usually can't see it, because image viewer app reads EXIF data inside the photo file and rotates it back, as it should be. And looks like Cropper can`t handle it.

Here is some code, which I have used in some apps to handle this problem:

int rotationAngle;
ExifInterface ei = new ExifInterface(Uri.fromFile(originalFile).getPath());
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotationAngle = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotationAngle = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                rotationAngle = 270;
                break;
            default:
                rotationAngle = 0;
        }

        Bitmap imageToRotate = BitmapFactory.decodeFile(originalFile.getAbsolutePath());
        Matrix matrix = new Matrix();
        matrix.postRotate(rotationAngle);
        Bitmap rotatedBitmap = Bitmap.createBitmap(imageToRotate, 0, 0, imageToRotate.getWidth(), imageToRotate.getHeight(), matrix, true);
vbuberen commented 7 years ago

@skined90 Yep, also checked on G3 and got rotated image. So LG G3 is another devices with rotated camera. You can use the code above to handle it or you can add buttons to rotate the image when it is already passed to Cropper. If you user version prior to 0.1.3 you can just call BitmapUtils.rotateBitmap(bitmap, angle). If newer, you should implement this rotation itself, because lib creator deleted this method from BitmapUtils. Rotation is done with this code:

Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
jayrambhia commented 7 years ago

That behavior is intentional. The cropper takes a Bitmap as input, crops and gives a Bitmap as output. That is the only responsibility it has. I don't want to add more complexity to it.

Here's the code that would help in getting correct orientation of the bitmap.

public static Bitmap readBitmapFromFile(String path) throws OutOfMemoryError {
    Bitmap bitmap = BitmapFactory.decodeFile(path);
    if (bitmap != null) {
        return autoExif(bitmap, path);
    } else {
        return null;
    }
}

public static Bitmap autoExif(@NonNull Bitmap bitmap, @NonNull String path) {
    ExifInterface exif;
    try {
        exif = new ExifInterface(path);
    } catch (IOException e) {
        e.printStackTrace();
        return bitmap;
    }

    return rotateBitmapForExif(bitmap,
                               exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                                                    ExifInterface.ORIENTATION_NORMAL));
}

public static Bitmap rotateBitmapForExif(Bitmap bitmap, int orientation) {

    Matrix matrix = new Matrix();
    switch (orientation) {

        case ExifInterface.ORIENTATION_NORMAL:
            return bitmap;
        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;
        default:
            return bitmap;
    }
    Bitmap bmRotated = Bitmap.createBitmap(
            bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    bitmap.recycle();
    return bmRotated;
}