Android:三星设备自动旋转图像

时间:2017-12-12 17:41:38

标签: android image android-glide metadata-extractor

我创建了一个自定义相机。当我单击应用程序中的捕获按钮时,已拍摄图像。此外,我在名为 onPictureTaken 的函数中以字节数组的形式获取数据。

我正在使用名为 Glide 的库将字节数组转换为位图。

我的问题是在三星设备中图像会自动旋转。我已经研究了很长一段时间了。我发现这个库被称为元数据提取库,用于从byte []获取Exif信息并在其上旋转图像,但它不能在Samsung设备上运行。 元数据提取库每次为肖像图像返回值1,表示图像不需要旋转,但是以纵向模式拍摄的图像始终旋转90度。

每当照片以纵向模式拍摄时,前后相机都会以90度的角度旋转,元提取库显示值为1.

还有其他东西,然后提取Exif信息流数据的元数据提取提取库吗?

注意: 我不能使用ExifInterface,因为它需要的最低Api级别为24,而我在API级别22上进行测试

我尝试了很多解决方案,但没有任何效果。对此有什么解决方案吗?

代码如下:

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

        }

我正在使用三星J5进行测试。

3 个答案:

答案 0 :(得分:1)

你不需要一个图书馆。以下是我编写的一些方法,可以帮到你。

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

我将它们包装在一个名为ImageHelper的类中。您可以像这样使用它:

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

然后当然rotateImage代码是:

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

    }

当然,我正在为照片编辑,裁剪和缩放应用做这一切,所以你可以忽略一些额外的东西,但这应该照顾你。古德勒克。

答案 1 :(得分:0)

几乎在所有三星设备中,图像旋转问题都很常见,就我而言,我正在使用三星Note 3,并且发生了相同的问题,但是我正在使用以下代码来解决此问题

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

此代码对我有用,希望对您有帮助

答案 2 :(得分:0)

可以使用Google提供的ExifInterface轻松修复。
您可以将其添加到您的项目中,如下所示:

implementation "androidx.exifinterface:exifinterface:1.1.0"

此后,从图像中获取旋转并将其应用于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
        }