我有一个应用程序,使用本机的Camera捕获照片,然后将其上传到服务器。我的问题是所有照片的EXIF方向值均为0,这使其他地方的显示困惑。

如何更改EXIF方向?我不是在寻找一种针对每种情况进行更正的方法,只需将其更改为其他值即可。

我正在使用三星Galaxy Note 4

我尝试了以下解决方案,该解决方案可以在拍照前设置相机的方向:Setting Android Photo EXIF Orientation

Camera c = Camera.open();
c.setDisplayOrientation(90);

Camera.Parameters params = mCamera.getParameters();
params.setRotation(0); // tried 0, 90, 180
c.setParameters(params);

但它不会影响生成的EXIF数据,其始终始终为0

我还尝试了以下解决方案,在拍摄后旋转图像:EXIF orientation tag value always 0 for image taken with portrait camera app android

并且当旋转照片时,EXIF方向始终始终为0。

我也尝试过直接设置EXIF数据:How to save Exif data after bitmap compression in Android
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        final File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE, "");
        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);

            ExifInterface exif = new ExifInterface(pictureFile.toString());
            exif.setAttribute(ExifInterface.TAG_ORIENTATION, "3");
            exif.saveAttributes();

            fos.write(data);
            fos.close();

            //upload photo..
        }
    }
}

但上传后,EXIF方向仍为0。

我还研究了以下解决方案:

Exif data TAG_ORIENTATION always 0

How to write exif data to image in Android?

How to get the Correct orientation of the image selected from the Default Image gallery

how to set camera Image orientation?

但是它们都涉及通过旋转来校正方向,这不会影响EXIF数据,或者直接设置似乎无效的EXIF数据。

如何将文件的EXIF方向数据从0更改为3?

更新:

这是我的上传代码:
Bitmap sBitmap = null;
final File sResizedFile = getOutputMediaFile(MEDIA_TYPE_IMAGE, "_2");
try {
    sBitmap = BitmapFactory.decodeStream(new FileInputStream(pictureFile), null, options);
} catch (FileNotFoundException e) {
    Log.e("App", "[MainActivity] unable to convert pictureFile to bitmap");
    e.printStackTrace();
    return;
}

// ... compute sw and sh int values

Bitmap sOut = Bitmap.createScaledBitmap(sBitmap, sw, sh, false);
Bitmap rotatedBitmap = rotateBitmap(sOut, 3);
FileOutputStream sfOut;
try {
    sfOut = new FileOutputStream(sResizedFile);
    rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, sfOut);
    sfOut.flush();
    sfOut.close();
    sBitmap.recycle();
    sOut.recycle();
    rotatedBitmap.recycle();
} catch (Exception e) {
    Log.e("App", "[MainActivity] unable to save thumbnail");
    e.printStackTrace();
    return;
}
// upload small thumbnail
TransferObserver sObserver = transferUtility.upload(
            "stills/small",        /* The bucket to upload to */
            filename + ".jpg",     /* The key for the uploaded object */
            sResizedFile           /* The file where the data to upload exists */
);

最佳答案

如您所见,EXIF信息在Android(尤其是三星设备)上不可靠。

但是,包含对Media对象的引用的电话SQL数据库是可靠的。我建议这样做。

从Uri获取方向:

private static int getOrientation(Context context, Uri photoUri) {
    Cursor cursor = context.getContentResolver().query(photoUri,
            new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);

    if (cursor.getCount() != 1) {
        cursor.close();
        return -1;
    }

    cursor.moveToFirst();
    int orientation = cursor.getInt(0);
    cursor.close();
    cursor = null;
    return orientation;
}

然后初始化旋转的Bitmap:
public static Bitmap rotateBitmap(Context context, Uri photoUri, Bitmap bitmap) {
    int orientation = getOrientation(context, photoUri);
    if (orientation <= 0) {
        return bitmap;
    }
    Matrix matrix = new Matrix();
    matrix.postRotate(orientation);
    bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
    return bitmap;
}

如果要更改图像的方向,请尝试以下代码段:
public static boolean setOrientation(Context context, Uri fileUri, int orientation) {
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.ORIENTATION, orientation);
    int rowsUpdated = context.getContentResolver().update(fileUri, values, null, null);
    return rowsUpdated > 0;
}

如果您设置图像的方向,以后将始终将其设置为正确的方向。以后需要使用ExifInterface,因为图像已经以正确的方式旋转了。

如果此方法不令人满意,则可以尝试this method

07-24 09:49
查看更多