来自相机(三星设备)的照片旋转

12

我讨厌这家公司。他们的设备有很多漏洞。好了,问题是: 我正在尝试解决一个愚蠢的问题(据我所知已经存在5年以上)。 照片是从相机拍摄的 - 旋转了90度。 我有两个设备:

  Nexus 5p and Samsung j2  
  Nexus - work perfect. Everything fine. 
  Samsung - photo rotated
例如:
Photo size - nexus : Portrate : width 1000, height 1900.  Landscape :
width 1900 , height 1000

让我们在三星设备上查看:

Photo size  - Portrate: width 1900(?????) height - 1000(????)
rotate to landscape : width 1900 height 1000

经过一些测试: 如果在三星设备上横向拍摄照片-那么一切正常。照片不会旋转。

如果以纵向模式拍摄照片,则照片会旋转90度。(但是照片的大小与横向模式相同(这怎么可能)?

有人知道如何修复这个愚蠢的错误吗? 也许有人可以告诉我如何检测相机方向?我正在使用IntentActivity进行拍照:

String _path = Environment.getExternalStorageDirectory()
                                    + File.separator + "camera_img.jpg";
                            File file = new File(_path);
                            Uri outputFileUri = Uri.fromFile(file);
                            Intent intent = new Intent(
                                    android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                            intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
                            startActivityForResult(intent, CAMERA_REQUEST);

需要帮助吗? 我还添加了一个检测器,如果是三星设备则旋转屏幕。但只有在竖屏模式下拍照才能正确旋转。在横屏模式下一切都好。所以我需要某种方式来检测照片是在哪种方向上创建的。有人知道吗?


我遇到了相同的问题,请参考以下链接,https://dev59.com/3WYq5IYBdhLWcg3w8VG8 - Dhruv Patel
@DhruvPatel 这不起作用是因为照片的尺寸总是横向尺寸。 - Peter
你能把一张横向和一张纵向的文件放在互联网上,这样我们就可以看一下吗? - greenapps
以简单的方式,您可以使用Glide获取位图或直接将其设置在ImageView中,如https://dev59.com/3WYq5IYBdhLWcg3w8VG8#68029909所述。 - Abdur Rehman
5个回答

7

更新于2018年8月29日:我发现这种方法在基于Android 8+的三星设备上不起作用。例如三星S8,我无法理解为什么这里又失效了。如果有人能够测试并查明原因,让我们一起尝试修复。


我找到了如何解决问题:这个方法非常愚蠢,对我来说也很困难。

第一步是获取活动结果。

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

在对文件进行更改之前,主要步骤是getImageOrientation

  1. 通过路径获取getImageOrientation
  2. 重新保存文件(如果需要发送到服务器,如果只是预览,则可以跳过此步骤)
  3. 从文件中获取正确的位图

仅进行1和3步即可进行预览,并使用此函数-旋转位图。

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

获取图片的方向

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

如果需要的话,可以重新保存位图。
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;
    }

看看我的答案,它适用于三星S8。 https://dev59.com/nlYN5IYBdhLWcg3wjIuZ#57460550 - paakjis

2
如果您想旋转一张图片,但只有字节数组,您可以使用以下方法:
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();
}

并且这个exif工具来自于这个答案

如果图片很大,这会有点慢。


2
我在这里找到了最初的回答,适用于我的三星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();
        }
    }
}

当我从图库获取图片时,这个方法可以工作:Intent.ACTION_GET_CONTENT

我尝试使用MediaStore.ACTION_IMAGE_CAPTURE,但它返回了0。也许是我做错了什么。

最初的回答:


0

你是使用相机API自己拍照吗? 如果是的话,你可以通过以下方式获取方向: Camera1 API:

CameraInfo cameraInfo = new CameraInfo();
int sensorOrientation = cameraInfo.orientation;

Camera2 API:

CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics characteristics = mCameraCharacteristics;
int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

请仔细阅读我的帖子,我在那里写道:我正在使用IntentActivity而不是Camera API。 - Peter
抱歉,我的错。你应该使用EXIF来查看图像的旋转。 - Quentin Menini

0

使用Glide lib可以解决这个问题

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_PICK_PHOTO_FOR_PROFILE && resultCode == RESULT_OK && data != null && data.getData() != null) {
        try {
           Glide.with(this).load(data.getData()).into(mProfileFragment.mProfileImage);
        } catch (Exception e) {
            Utils.handleException(e);
        }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接