这个问题被问了无数次,但是在保存Bitmap
时,它们都没有解决轮换问题。
这是我最初将Bitmap
保存到设备中的方式:
FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
mmr.setDataSource(mStringFilePath);
//Time is us
int mPresentationTime = mPlayer.getPresentationTime();
Bitmap mBitmap = mmr.getFrameAtTime(mPresentationTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
File mFileBitmap = new File(directoryToStore, "test.png");
try {
FileOutputStream outputStream = new FileOutputStream(mFileBitmap);
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
以上方法将.png
保存为错误的方向。
然后我看到了this的答案,但是问题在于它已经将已经保存的Bitmap
旋转到正确的方向。例如,如果要将Bitmap
设置为ImageView
,就可以了。但是,如果我想共享Bitmap
,或想在设备库中打开它,方向仍然不正确。然后,我将不得不执行与上述相同的过程-FileOutputStream
等。这只会导致相同的问题。
有人可以帮助我了解如何将Bitmap
以正确的方向保存到设备吗?
尝试Long提供的答案。
我使用您提供的2方法创建了一个名为RotateBit
的新类。然后,我将代码更改为此:
FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
mmr.setDataSource(mStringFilePath);
//Time is us
int mPresentationTime = mPlayer.getPresentationTime();
Bitmap mBitmapBeforeRotation = mmr.getFrameAtTime(mPresentationTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
int rotatingInt = RotateBit.getBitmapOriention(mStringFilePath);
Bitmap mBitmap = RotateBit.rotateBitmap(mBitmapBeforeRotation, rotatingInt);
File mFileBitmap = new File(directoryToStore, "test.png");
try {
FileOutputStream outputStream = new FileOutputStream(mFileBitmap);
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
但是旋转仍然不正确。
我注意到此问题与FFmpegMediaMetadataRetriever
有关,使用MediaMetadataRetriever
时不会发生此问题。
答案 0 :(得分:0)
public static int getBitmapOriention(String path){
ExifInterface exif = null;
int orientation = 0;
try {
exif = new ExifInterface(path);
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
//Log.e("getBitmapOriention", "getBitmapOriention: "+orientation );
} catch (Exception e) {
e.printStackTrace();
}
return orientation;
}
/**
* @param bitmap bitmap from path
* @param orientation ExifInterface
* @return oriention flag
*/
public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90);
break;
default:
return bitmap;
}
try {
Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return bmRotated;
}
catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
}
对我有用
rotateBitmap(mBitmap,getBitmapOriention(mPath));
答案 1 :(得分:0)
您需要使用ExifInterface
进行轮换。
public static void normalizeImageForUri(Context context, Uri uri, ImageView imgImageView) {
try {
// Log.d(TAG, "URI value = " + uri.getPath());
ExifInterface exif = new ExifInterface(getRealPathFromURI(context, uri));
// Log.d(TAG, "Exif value = " + exif);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
Bitmap rotatedBitmap = rotateBitmap(bitmap, orientation);
imgImageView.setImageBitmap(rotatedBitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
用于检查位图的旋转:
private static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
return bitmap;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
matrix.setScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.setRotate(180);
break;
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
matrix.setRotate(180);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_TRANSPOSE:
matrix.setRotate(90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.setRotate(90);
break;
case ExifInterface.ORIENTATION_TRANSVERSE:
matrix.setRotate(-90);
matrix.postScale(-1, 1);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.setRotate(-90);
break;
default:
return bitmap;
}
try {
Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
return bmRotated;
} catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
}
有关此链接的更多详细信息,请参见:
How to get the Correct orientation of the image selected from the Default Image gallery
https://github.com/google/cameraview/issues/22#issuecomment-269321811
答案 2 :(得分:0)
我设法创建了一种解决方法。这可能不是应该怎么做,但目前为止,它可以正常工作。
根据正在播放的视频的旋转方式,我的Activity
设置为纵向/横向。因此,我可以使用它来确定是否旋转Bitmap
。
我首先像以前一样创建一个Bitmap
:
Bitmap mBitmapBeforeRotation = mmr.getFrameAtTime(mPresentationTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
然后我得到屏幕的旋转,Bitmap
的宽度/高度,并相应地旋转Bitmap
:
int mBitW = Integer.parseInt(String.valueOf(mBitmapBeforeRotation.getWidth()));
int mBitH = Integer.parseInt(String.valueOf(mBitmapBeforeRotation.getHeight()));
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Do nothing because Landscape doesn't give wrong Bitmap rotation
} else {
if (mBitW>mBitH){
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap fixedBitmapRotation = Bitmap.createBitmap(mBitmapBeforeRotation, 0, 0, mBitmapBeforeRotation.getWidth(), mBitmapBeforeRotation.getHeight(), matrix, true);
String nameOfImage = "nameOfImage" + ".jpeg";
final File mFile = new File(directoryyToStore, nameOfImage);
try {
FileOutputStream outputStream = new FileOutputStream(mFile);
fixedBitmapRotation.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
texeBit = mp.getPath();
}
请注意。 我不必使用屏幕旋转来确定是否应该旋转Bitmap
。我可以先用Bitmap
创建一个MediaMetadataRetriever
(因为MediaMetadataRetriever
为Bitmap
提供了正确的旋转方式),然后执行以下操作:
int videoWidth;
int videoHeight;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(this, mVideoUri);
Bitmap bmp = retriever.getFrameAtTime();
videoWidth = bmp.getWidth();
videoHeight = bmp.getHeight();
我可以做上面的事情。
我不会接受自己的回答,因为我没有在多台设备上进行测试,而且这是解决此问题的一种非常“ hack-ish”的方式。
■