使用ExifInterface设置图像方向

6
< p > Camera.Parameters 中的 setRotation method 并不适用于所有设备。有人建议手动更改 EXIF 信息来解决这个问题。你可以给我一个简短的示例,演示如何使用 ExifInterface 设置 exif 信息来将图像方向设置为竖直方向吗?

private int savePicture(byte[] data)
{
       File pictureFile = getOutputMediaFile();
       if (pictureFile == null)
           return FILE_CREATION_ERROR;

       try {
           FileOutputStream fos = new FileOutputStream(pictureFile);
           fos.write(data);
           fos.close();
       } catch (FileNotFoundException e) {
           return FILE_NOT_FOUND;
       } catch (IOException e) {
           return ACCESSING_FILE_ERROR;
       }

   return OKAY;
}

我尝试过以下方法:

    try {
        ExifInterface exifi = new ExifInterface(pictureFile.getAbsolutePath());
        exifi.setAttribute(ExifInterface.TAG_ORIENTATION, String.valueOf(ExifInterface.ORIENTATION_ROTATE_90));
        exifi.saveAttributes();
    } catch (IOException e) {
        Log.e(TAG, "Exif error");
    }

但是当我从安卓图库中查看图片时,没有任何变化。

4个回答

10

对于那些真正想将这些EXIF信息写出来的人,这里提供一些代码:

ExifInterface exifInterface = new ExifInterface(someFile.getPath());
exifInterface.setAttribute(ExifInterface.TAG_ORIENTATION,
                           String.valueOf(orientation));
exifInterface.saveAttributes();

其中orientation是标准方向之一,即ExifInterface.ORIENTATION_ROTATE_{90,180,270}之一。


这与原帖中提到的尝试有何不同? - Enrico
唉...我找不到任何借口,除了我没有滚动到顶部帖子的右侧... :( - Thomas Keller
没关系。很好知道我没有错过什么。 - Enrico

3
如果方向保存到文件中,但在图库中没有显示出来,可能是因为方向被缓存到MediaStore中。因此,您需要尝试在那里更新此信息。
以下是代码片段(未经测试):
/**
 * @param fileUri the media store file uri
 * @param orientation in degrees 0, 90, 180, 270
 * @param context
 * @return
 */
public boolean setOrientation(Uri fileUri, int orientation, Context context) {
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.ORIENTATION, orientation);
    int rowsUpdated = context.getContentResolver().update(fileUri, values, null, null);
    return rowsUpdated > 0;
}

/**
 * Get content uri for the file path
 * 
 * @param path
 * @param context
 * @return
 */
public Uri getContentUriForFilePath(String path, Context context) {
    String[] projection = {
        MediaStore.Images.Media._ID
    };
    Cursor cursor = context.getContentResolver().query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
            MediaStore.Images.Media.DATA + " = ?", new String[] {
                path
            }, null);
    Uri result = null;
    if (cursor != null) {
        try {
            if (cursor.moveToNext()) {
                long mediaId = cursor.getLong(0);
                result = ContentUris.withAppendedId(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediaId);
            }
        } finally {
            cursor.close();
        }
    }
    return result;
}

1
以下代码对我有效:

文件 imageFile = 新文件(字符串_路径); //在此添加路径

        ExifInterface exif = null;

        try {

            exif = new ExifInterface(imageFile.getAbsolutePath());

        } catch (IOException e) {

            e.printStackTrace();

        }

        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

        int rotate = 0;

        switch (orientation) {

            case ORIENTATION_ROTATE_270:
                rotate = 270;
                break;

            case ORIENTATION_ROTATE_180:
                rotate = 180;
                break;

            case ORIENTATION_ROTATE_90:
                rotate = 90;
                break;

        }

        Matrix matrix = new Matrix();

        matrix.postRotate(rotate);

        this.btmap = Bitmap.createBitmap(this.btmap, 0, 0, this.btmap.getWidth(), this.btmap.getHeight(), matrix, true);

        Glide.with(this).load(this.btmap).into((ImageView) getActivity().findViewById(R.id.btnimg));

1

我曾经遇到过类似的问题,尝试了你正在处理的解决方案,最终使用了矩阵函数。

无论我拍摄的图像是什么,都是横向的,所以在应用程序中,我只需要应用以下代码即可,它可以很好地工作:

Matrix matrix = new Matrix();
//set image rotation value to 90 degrees in matrix.
matrix.postRotate(90);
//supply the original width and height, if you don't want to change the height and width of //bitmap.
Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0, newWidth, newHeight, matrix, true);

好的,但如果我们这样做,性能会大大降低,因为:1)将byte[]数据写入文件2)读取文件并提取exif信息3)解压缩文件到bmp4)旋转图像5)再次压缩为jpeg6)覆盖文件。我想知道是否有更简单的解决方案,可以直接在data[]上操作。 - user2923045
1
你处理问题的方式会降低应用程序的性能,要明智地使用它,没有必要像你解释的那样处理图像,将图像保存为原样,不需要应用你解释的所有输入,当你需要在视图中显示它时,在运行时执行,并明智地处理查看图像,这不会降低其性能。 - Bette Devine
我不同意你的看法,Bette。我想使用Android画廊来展示图片,但Android画廊以错误的方向显示它们。 - user2923045
你不同意哪个点?为什么要让你的图片在画廊中可见?如果这些链接对你有用,请查看: https://android.googlesource.com/platform/frameworks/base/+/master/media/java/android/media/ExifInterface.java https://dev59.com/8FTTa4cB1Zd3GeqPweCw - Bette Devine
1
不,我的意思是我不想开发自己的相册。为了浏览我正在开发的相机应用程序拍摄的照片,我想使用任何设备中已经安装的相册应用程序。但是,当手机处于纵向拍摄模式时,使用android.development中的示例代码以及在线教程中的几个示例拍摄的照片是无法使用的,因为它们显示的方向不正确。 - user2923045
你也可以直接使用相同的矩阵并将其设置在图像视图上,只需确保将iv的比例类型设置为matrix,并可能需要在其上调用invalidate。 - wkhatch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接