java Android:从文件中旋转和显示图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25598027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: Rotate and display image from file
提问by user2864874
I have a very simple layout with an ImageView. My application opens the camera, saves an image, and then displays the image in the ImageView with BitmapFactory.decodeFile
. The only issue is that it's rotated. I understand that a) this is due to the phone's camera defaulting to landscape, so this needs to be handled in code and b) image processing must be done in a separate thread from the UI.
我有一个带有 ImageView 的非常简单的布局。我的应用程序打开相机,保存图像,然后在 ImageView 中使用BitmapFactory.decodeFile
. 唯一的问题是它被旋转了。我知道 a) 这是由于手机的摄像头默认为横向,所以这需要在代码中处理,并且 b) 图像处理必须在与 UI 不同的线程中完成。
The Android training documentation seems to be geared toward loading images from resource id's instead of file paths. This just throws a wrench in things as I'm able to follow the tutorials up to a point but ultimately have trouble reconciling the differences.
Android 培训文档似乎面向从资源 ID 而不是文件路径加载图像。这只会给事情带来麻烦,因为我可以在一定程度上按照教程进行操作,但最终无法协调差异。
I'm certainly new at this so if someone could just give me a high-level overview of what needs to be done to accomplish this, I'd really appreciate it. The following code is where I'm currently adding the bitmap to the ImageView. I assume that my call to the separate thread would go in onCreate
?
我当然是新手,所以如果有人能给我一个高层次的概述,说明需要做什么来完成这个,我真的很感激。以下代码是我当前将位图添加到 ImageView 的位置。我假设我对单独线程的调用会进入onCreate
?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_image);
Bitmap bm = BitmapFactory.decodeFile(MainActivity.image_path);
displayImageView = (ImageView) findViewById(R.id.myImageView);
displayImageView.setImageBitmap(bm);
}
回答by Kaushik
Use ExifInterfacefor rotate
使用ExifInterface进行旋转
picturePath = getIntent().getStringExtra("path");
Bitmap bitmap = BitmapFactory.decodeFile(picturePath);
ExifInterface exif = new ExifInterface(picturePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
break;
default:
break;
}
myImageView.setImageBitmap(bitmap);
bitmap.recycle();
Note :Here picturePath
is selected Image'spath from Gallery
注:这里picturePath
选择图片的路径,从Gallery
回答by user2864874
I was able to get it working with the following approach. I think you could do this without the AsyncTask but it seems that best practice states you should perform image processing in a non-UI thread (please feel free to correct - I'm quite new at this).
我能够使用以下方法使其工作。我认为您可以在没有 AsyncTask 的情况下执行此操作,但似乎最佳实践规定您应该在非 UI 线程中执行图像处理(请随时纠正 - 我对此很陌生)。
An improvement which could be made to this would be to handle the scaling in a more granular way. inSampleSize
is a great tool but it will only scale by powers of 2. Another improvement would be to initially only read the meta/EXIF data into bmOriginal
as the only use of this variable is to retrieve the height and width.
可以对此进行的改进是以更细粒度的方式处理缩放。 inSampleSize
是一个很棒的工具,但它只能按 2 的幂进行缩放。另一个改进是最初只读取元/EXIF 数据,bmOriginal
因为此变量的唯一用途是检索高度和宽度。
ImageView XML - pretty much standard. android:layout_width/height set to fill_parent
.
ImageView XML - 非常标准。android:layout_width/height 设置为fill_parent
.
From the activity's java file -
从活动的 java 文件 -
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_image);
new ImageRotator().execute(MainActivity.image_path);
}
private class ImageRotator extends AsyncTask<String, Void, Bitmap>{
protected Bitmap doInBackground(String... image_path){
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = 4;
Bitmap bmOriginal = BitmapFactory.decodeFile(image_path[0], bitmapOptions);
Matrix matrix = new Matrix();
matrix.postRotate(90);
bmOriginal = Bitmap.createBitmap(bmOriginal, 0, 0, bmOriginal.getWidth(), bmOriginal.getHeight(), matrix, true);
return bmOriginal;
}
protected void onPostExecute(Bitmap result) {
myImageView = (ImageView) findViewById(R.id.myImageView);
myImageView.setImageBitmap(result);
}
}
The scaling process was found hereand there's a great explanation of AsyncTask's features here.
缩放过程中被发现这里有年代的AsyncTask的功能有很大的解释在这里。
Thanks so much to all who responded and again - please feel free to let me know if this is way off base or even if there's just a better way to do this.
非常感谢所有回复的人 - 请随时让我知道这是否离谱,或者即使有更好的方法来做到这一点。
回答by wrkwrk
Why bother to rotate the image. As you said "The ImageView itself is properly oriented. It's just that the image inside it is always displayed 90 degrees counter-clockwise. " , then just make the ImageView rotate 90 degrees clockwise, the image will display correctly.
为什么要旋转图像。正如你所说的“ImageView 本身是正确定向的。只是它里面的图像总是逆时针显示 90 度。”,然后只需将 ImageView 顺时针旋转 90 度,图像就会正确显示。
displayImageView.setRotation(90);
回答by Eenvincible
You can rotate an image using a matrix or set the rotation in your xml. If you want more control however, you can check out this tutorial written for rotating images and saving to disk:
您可以使用矩阵旋转图像或在 xml 中设置旋转。但是,如果您想要更多控制,可以查看本教程,用于旋转图像并保存到磁盘:
How to rotate an image in android
I hope that helped.
我希望这有帮助。