这个问题已经被问了无数次,但是没有一个真正解决保存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
。
然后我看到了这个答案,但问题是它将已经保存的位图旋转到正确的方向。例如,如果您想将Bitmap
设置为ImageView
,则可以这样做。但是,如果我想共享位图,或者想在设备库中打开它,方向仍然不正确。然后,我将不得不执行与上面相同的过程-FileOutputStream
等。这将导致同样的问题。
如何将位图
以正确的方向保存到设备?
尝试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();
}
但是旋转仍然是不正确的。
我注意到这个问题与
ffmpegmediataretriever
有关,当使用mediamadedataretriever
时,这个问题不会发生。
我设法创造了一个变通办法。这可能不是应该做的,但就目前而言,它是有效的。
我的活动
设置为纵向/横向取决于我正在播放的视频的旋转。因此,我可以使用它来确定是否旋转位图。
我首先创建了一个位图
,就像我以前做的那样:
Bitmap mBitmapBeforeRotation = mmr.getFrameAtTime(mPresentationTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
然后我得到屏幕的旋转,位图的宽度/高度
,并相应地旋转位图
:
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
。我可以先创建一个位图
与MediaMetadataRetriever
(因为MediaMetadataRetriever
给我的位图
的正确旋转),然后这样做:
int videoWidth;
int videoHeight;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(this, mVideoUri);
Bitmap bmp = retriever.getFrameAtTime();
videoWidth = bmp.getWidth();
videoHeight = bmp.getHeight();
我可以像上面那样做。
我不会接受我自己的答案,因为我没有在多台设备上测试过,而且这是一种非常“黑客式”的解决方法。
■
您需要使用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;
}
}
更多详情请参考以下链接:
如何获得从默认图像库中选择的图像的正确方向
https://github.com/google/cameraview/issues/22#issuecomment-269321811
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));
我在Android上工作。我需要保存一个没有质量损失的位图。 我使用位图的方法进行了尝试,将质量设置为100。这对我不起作用,位图失去了太多的质量。我已经测试了JPEG和PNG格式。 我已经测试过将位图复制到,然后提取,并使用保存它。在这种情况下,我无法显示用这种方式保存的图像,我只看到一个空白页。 我的问题是,有没有办法在不压缩的情况下将位图保存在SD卡中? 编辑:这里我的代码的一部分 我检测到
问题内容: 如果在保存之前使用图像,那是正常的。但是,如果我保存并以后使用,则需要旋转90度。我如何确保它不会横向保存? 问题答案: 如果需要以正确的旋转方式保存PNG,则如果方向不正确,则需要重新绘制图像。您可以按以下方式重绘它: 编辑/更新: 对于iOS10 + tvOS10 +,您可以使用: 游乐场测试: 不透明图像的用法: 具有透明度:
所以我用下面的方法设置了摄像头- 如您所见,我在摄像机参数上使用了setRoation()来实际指定图像方向,并在摄像机本身上使用了setDisplayOriation()来处理表面预览中的方向更改。(注释和未注释的代码似乎都没有保留方向。当我检查数据时,它返回0) 之后,在回调中,我甚至尝试使用矩阵保存具有方向的图像。 实际问题 > 当我在肖像模式下拍照时,一切正常。它看起来像是被拿走了。 但是
问题内容: 我正在显示一组图像,然后,如果用户希望,可以将图像保存到SD卡。我需要将其保存到外部存储的帮助。有人可以帮我这个忙吗? 网格视图: ImageAdapter: 问题答案: 嗨,我还没有使用过作为应用程序一部分提供的代码,但是我确实使用它来调试了其中一个应用程序在运行时生成的位图。 使用此代码,只要您有位图,就只需要此+清单权限 希望能帮到您 杰森
我正在从相机中保存一个处于横向模式的图像。所以它被保存在横向模式下,然后我在它上面应用一个覆盖层,它也是在横向模式下。我想旋转那个图像,然后保存。例如,如果我有这个 我想顺时针旋转90度一次,这样做,并将其保存到SD卡: 如何做到这一点?
我是新的Android和工作在一个项目中,我必须使用自定义相机与覆盖图像捕获图像。 我可以用叠加(组合图像)捕获图像,但问题是叠加图像方向在保存新的组合图像后发生变化,即叠加图像主要设置在纵向模式,但在保存后显示在横向模式。 我已经搜索了很多关于如何改变可绘制图像的方向,但所有方向的改变都是针对位图图像的。若我将可绘制图像更改为位图并更改旋转,它不会显示任何覆盖图像。我不知道代码出了什么问题。我的