Android相机和肖像旋转

4
我在我的Android应用中遇到了问题,我按照this article中的步骤拍摄应用程序中的照片,它可以正常工作,但不幸的是照片是横向模式而不是纵向模式。我在SO上和网络上找到了几篇文章,涉及到这个问题,从我的理解来看,这种行为不是Android的行为,而是设备行为,可能会因设备而异。

所以问题是:当我从意图中获取照片时,如何知道拍摄的照片是否需要旋转?

这里你可以看到使用模拟器拍摄的截图(我在我的Sony Xperia上也有同样的行为):

enter image description here

然后当我在 ImageView 中显示它时:

enter image description here


请在您展示此图像的代码中发布,我们可以通过编程方式旋转图像。 - Sandeep Parish
我已经有了旋转图像的代码,问题是如何知道图片是否需要旋转。 - Moussa
当您从前置摄像头或后置摄像头捕获图像时,如果您设置了单个摄像头的角度,则需要旋转图像,否则您需要为前置和后置摄像头设置摄像头角度。 - Sandeep Parish
2
问题是如何知道图片是否需要旋转。检查Exif头。 - greenapps
当我从意图中获取图片时,您不会从意图中获取它。也不会从使用的相机应用程序中获取。情境是不同的。请更好地描述发生了什么。 - greenapps
1个回答

0

由于我没有找到完整的答案来回答我的问题,所以我发布了我的解决方案。

1. 从相机获取照片

protected File pictureFromCamera;
protected Uri photoUri;
...
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null)
{
    // Create the File where the photo should go
    pictureFromCamera = generateFile();
    if (pictureFromCamera != null)
    {
        String authority = BuildConfig.APPLICATION_ID + ".provider";
        photoUri = FileProvider.getUriForFile(DermatoPhotoCollectionActivity.this, authority, pictureFromCamera);
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
        startActivityForResult(takePictureIntent, REQUEST_PHOTO_FROM_CAMERA);
    }
}

2. 获取照片的方向

以下是获取方向的代码,它受到了this article的启发。请注意,这需要一个依赖项: compile "com.android.support:exifinterface:27.1.1"

获取照片的方向取决于设备,可能无法在某些设备上工作(例如,在我的Xperia上运行良好,但在Android模拟器上不行)。

public static int getOrientation(Context context, Uri photoUri)
{
    InputStream in = null;
    int orientation = ExifInterface.ORIENTATION_NORMAL;
    try
    {
        in = context.getContentResolver().openInputStream(photoUri);
        if (in != null)
        {
            android.support.media.ExifInterface exifInterface = new android.support.media.ExifInterface(in);
            orientation = exifInterface.getAttributeInt(android.support.media.ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
        }
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    finally
    {
        if (in != null)
        {
            try
            {
                in.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    return orientation;
}

3. 如有需要,旋转图片

我使用asyncTask来旋转照片

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (resultCode == RESULT_OK)
    {
        final String pathPhotoFromCamera = pictureFromCamera.getAbsolutePath();

        final ProgressDialog progressDialog = createProgressDialog();
        progressDialog.show();

        int orientation = getOrientation(this, photoUri);
        int rotationAngle = 0;

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

        AsyncTaskRotatePicture.AsyncTaskParams params = new AsyncTaskRotatePicture.AsyncTaskParams(pathPhotoFromCamera, rotationAngle);

        AsyncTaskRotatePicture taskRotatePicture = new AsyncTaskRotatePicture(new CallBack()
        {
            @Override
            public void onPostExecute()
            {
                progressDialog.dismiss();
            }
        });

        taskRotatePicture.execute(params);
    }
}

4. 最后旋转照片的代码

该函数将覆盖原始照片。

public static void rotatePhoto(String photoFilePath, int rotationAngle)
{
    Bitmap bm = BitmapFactory.decodeFile(photoFilePath);
    Matrix matrix = new Matrix();
    matrix.setRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
    byte[] extractedBitmap = extractByteFromBitmap(Bitmap.createBitmap(bm, 0, 0, bm.getWidth() - 1, bm.getHeight() - 1, matrix, true));
    saveBitmapOnSdcard(extractedBitmap, photoFilePath);
}

你好,能否请您展示一下您是如何编写 generateFile() 函数的呢? - jzeferino
我有一个符合我的要求的自定义函数,但是链接文章中提供的那个应该也可以正常工作:https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en 搜索函数:private File createImageFile() throws IOException - Moussa

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