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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:18:14  来源:igfitidea点击:

Android: Rotate and display image from file

javaandroidandroid-bitmap

提问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 picturePathis 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. inSampleSizeis 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 bmOriginalas 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

如何在android中旋转图像

I hope that helped.

我希望这有帮助。