Android 相机和人像旋转
Android camera and portrait rotation
我的 Android 应用程序有问题,我按照 this article 在我的应用程序中拍照并且工作正常,但不幸的是照片是横向模式而不是纵向模式。我在 SO 上找到了几篇关于这个问题的帖子和网上的文章,据我所知,这种行为不是 Android 行为而是设备行为,它可能会从一个设备变为另一个设备。
所以问题是:当我从意图中获取图片时,如何知道拍摄的图片是否需要旋转?
在这里你可以看到用模拟器拍摄的照片(我在我的索尼 Xperia 上有同样的行为):
然后当我在 ImageView 中显示它时:
因为我没有找到我的问题的任何完整答案,所以我 post 我的解决方案。
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);
}
我的 Android 应用程序有问题,我按照 this article 在我的应用程序中拍照并且工作正常,但不幸的是照片是横向模式而不是纵向模式。我在 SO 上找到了几篇关于这个问题的帖子和网上的文章,据我所知,这种行为不是 Android 行为而是设备行为,它可能会从一个设备变为另一个设备。
所以问题是:当我从意图中获取图片时,如何知道拍摄的图片是否需要旋转?
在这里你可以看到用模拟器拍摄的照片(我在我的索尼 Xperia 上有同样的行为):
然后当我在 ImageView 中显示它时:
因为我没有找到我的问题的任何完整答案,所以我 post 我的解决方案。
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);
}