mimetype
mimetype

Reputation: 31

Android: Samsung devices rotates the image automatically

I have created a custom camera. When I click on the capture button in the application, image has been taken. Moreover, I am getting the data in the form of byte array in the function named as onPictureTaken.

I am converting the byte array into the bitmap using the library known as Glide.

My problem is that in Samsung device the images rotates itself. I have been researching on it for quite a while. I found the library called as metadata extraction library to get the Exif information from byte[] and rotate the image on it but it is not working on the Samsung devices. The metadata extraction library every time returns a value of 1 for portrait image which shows that image does not need rotation however, the image taken in portrait mode is always 90 degree rotated.

Whenever, the photo is taken in portrait mode it is rotated at an angle of 90 degrees for both front and back camera and meta extraction library shows a value of 1.

Is there something other then metadata extraction extraction library which extract Exif information stream data?

Note: I cannot use ExifInterface because it requires the minimum Api level of 24 whereas, I am testing on API level 22

I have tried many solution but nothing is working. Is there any solution for this?

The code is given below:

public void onPictureTaken(byte[] data, Camera camera) {
            mCamera.stopPreview();

            Glide.with(this).load(data)
    .asBitmap().centerCrop().animate(R.anim.abc_fade_in)
    .into(new SimpleTarget<Bitmap>(width, height) {
                            @Override
                            public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                                camera_view.setVisibility(View.INVISIBLE);
                                int w = resource.getWidth();
                                int h = resource.getHeight();

                                // Setting post rotate to 90

                                Matrix mtx = new Matrix();


                                try {

                                    InputStream is = new ByteArrayInputStream(data);
                                    Metadata metadata = ImageMetadataReader.readMetadata(is);
                                    final ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
                                    if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
                                        final int exifOrientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
                                        switch (exifOrientation) {

                                            case 6:
                                                mtx.postRotate(90);
                                                break;  // top left
                                            case 3:
                                                mtx.postRotate(180);;
                                                break;  // top right
                                            case 8:
                                                mtx.postRotate(270);
                                                break;  // bottom right

                                        }
                                        photo = Bitmap.createBitmap(resource, 0, 0, w, h, mtx, true);
                                            /* Work on exifOrientation */
                                    } 


                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }

        }

I am using Samsung J5 for the testing.

Upvotes: 2

Views: 2270

Answers (3)

harshithdwivedi
harshithdwivedi

Reputation: 1421

This can be easily fixed by using ExifInterface provided by Google.
You can add it to your project as follows:

implementation "androidx.exifinterface:exifinterface:1.1.0"

After this, get the rotation from your image and apply it to your ImageView:

        // uri of the image
        val inputStream = contentResolver.openInputStream(Uri.parse(uri))
        val exifInterface = ExifInterface(requireNotNull(inputStream))

        var rotation = 0

        when (exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)) {
            ExifInterface.ORIENTATION_ROTATE_90 -> rotation = 90
            ExifInterface.ORIENTATION_ROTATE_180 -> rotation = 180
            ExifInterface.ORIENTATION_ROTATE_270 -> rotation = 270
        }

Upvotes: 1

Rajnikant Solanki
Rajnikant Solanki

Reputation: 53

Almost in all Samsung Devices the image rotation Issue is common ,in my case i am using Samsung Note 3 and this same issue occurs but i am using below code to solve this issue

public static Bitmap decodeFile(String path) { // this method is for avoiding the image rotation
        int orientation;
        try {
            if (path == null) {
                return null;
            }
            // decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            // Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE = 70;
            int width_tmp = o.outWidth, height_tmp = o.outHeight;
            int scale = 4;
            while (true) {
                if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
                    break;
                width_tmp /= 2;
                height_tmp /= 2;
                scale++;
            }
            // decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            Bitmap bm = BitmapFactory.decodeFile(path, o2);
            Bitmap bitmap = bm;
            ExifInterface exif = new ExifInterface(path);
            orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
            Log.e("orientation", "" + orientation);
            Matrix m = new Matrix();
            if ((orientation == 3)) {
                m.postRotate(180);
                m.postScale((float) bm.getWidth(), (float) bm.getHeight());
//               if(m.preRotate(90)){
                Log.e("in orientation", "" + orientation);
                bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), m, true);
                return bitmap;
            } else if (orientation == 6) {
                m.postRotate(90);
                Log.e("in orientation", "" + orientation);
                bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), m, true);
                return bitmap;
            } else if (orientation == 8) {
                m.postRotate(270);
                Log.e("in orientation", "" + orientation);
                bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), m, true);
                return bitmap;
            }
            return bitmap;
        } catch (Exception e) {
        }
        return null;
    }

This code is work for me so i hope this will helpful for you

Upvotes: 1

Sam
Sam

Reputation: 5392

You don't need a library for this. Here is a couple methods that I wrote that should do the trick for you.

 public static int getCapturedImageOrientation(Context context, Uri imageUri){
    int rotate = 0;
    try {
        context.getContentResolver().notifyChange(imageUri, null);
        File imageFile = new File(imageUri.getPath());

        ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

        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;
        }

        Log.i("RotateImage", "Exif orientation: " + orientation);
        Log.i("RotateImage", "Rotate value: " + rotate);
    } catch (Exception e) {
        Log.e(TAG, "Error getting rotation of image");

    }

    return rotate;
}
public static int GetRotateAngle(Context context, Uri imageUri) {
    String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media.ORIENTATION };
    Cursor cursor = context.getContentResolver().query(imageUri, columns, null, null, null);
    if (cursor == null) {
        //If null, it is not in the gallery, so may be temporary image
        return getCapturedImageOrientation(context, imageUri);

    }

    cursor.moveToFirst();

    int orientationColumnIndex = cursor.getColumnIndex(columns[1]);
    int orientation = cursor.getInt(orientationColumnIndex);
    cursor.close();
    return orientation;
}

I wrap these in a class called ImageHelper. You can use it like this:

 rotateImage(ImageHelper.GetRotateAngle(Context, mCropImageUri));

Then of course the rotateImage code would be:

 private void rotateImage(int degrees) {
        Matrix mat = new Matrix();
        mat.postRotate(degrees);
        mCropImage = Bitmap.createBitmap(mCropImage, 0, 0, mCropImage.getWidth(), mCropImage.getHeight(), mat, true);
        setImageForCropping(mCropImage);

    }

Of course i was doing all this for a photo editing, cropping and scaling app, so you can ignore some of the extras, but this should take care of ya. Goodluck.

Upvotes: 1

Related Questions