Android:从Uri获取位图方向

时间:2015-08-02 07:11:30

标签: android

使用以下方法打开图像选择器后

Intent intent = new Intent(); 
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "choose image", 1);

从选定的Uri获取位图的推荐方法是使用以下代码:

InputStream input = cxt.getContentResolver().openInputStream(fileUri);
Bitmap bmp = BitmapFactory.decodeStream(input);

但是此方法不会自动旋转使用相机以纵向模式拍摄的图像。

如何仅使用Uri获取Bitmap方向? (考虑到Uri可能来自Google云端硬盘或其他可能无法转换为磁盘上真实文件的位置)

1 个答案:

答案 0 :(得分:0)

我使用这个类: src是所选图像的字符串,位图是从图像中提取的位图。

public class ExifUtils {
public static Bitmap rotateBitmap(String src, Bitmap bitmap) {
    try {
        int orientation = getExifOrientation(src);

        if (orientation == 1) {
            return bitmap;
        }

        Matrix matrix = new Matrix();
        switch (orientation) {
        case 2:
            matrix.setScale(-1, 1);
            break;
        case 3:
            matrix.setRotate(180);
            break;
        case 4:
            matrix.setRotate(180);
            matrix.postScale(-1, 1);
            break;
        case 5:
            matrix.setRotate(90);
            matrix.postScale(-1, 1);
            break;
        case 6:
            matrix.setRotate(90);
            break;
        case 7:
            matrix.setRotate(-90);
            matrix.postScale(-1, 1);
            break;
        case 8:
            matrix.setRotate(-90);
            break;
        default:
            return bitmap;
        }

        try {
            Bitmap oriented = Bitmap.createBitmap(bitmap, 0, 0,
                    bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            bitmap.recycle();
            return oriented;
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
            return bitmap;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return bitmap;
}

private static int getExifOrientation(String src) throws IOException {
    int orientation = 1;

    try {
        /**
         * if your are targeting only api level >= 5 ExifInterface exif =
         * new ExifInterface(src); orientation =
         * exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
         */
        if (Build.VERSION.SDK_INT >= 5) {
            Class<?> exifClass = Class
                    .forName("android.media.ExifInterface");
            Constructor<?> exifConstructor = exifClass
                    .getConstructor(new Class[] { String.class });
            Object exifInstance = exifConstructor
                    .newInstance(new Object[] { src });
            Method getAttributeInt = exifClass.getMethod("getAttributeInt",
                    new Class[] { String.class, int.class });
            java.lang.reflect.Field tagOrientationField = exifClass
                    .getField("TAG_ORIENTATION");
            String tagOrientation = (String) tagOrientationField.get(null);
            orientation = (Integer) getAttributeInt.invoke(exifInstance,
                    new Object[] { tagOrientation, 1 });
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }

    return orientation;
  }
}

在您需要上传图片的部分。这是如何使用它:

ExifUtils.rotateBitmap(path, decodeSampledBitmap(file, 400, 400)));

decodeSampledBitmap是:

    public Bitmap decodeSampledBitmap(File res, int reqWidth, int reqHeight) {
    if (res != null) {
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        try {
            FileInputStream stream2 = new FileInputStream(res);

            BitmapFactory.decodeStream(stream2, null, options);

            stream2.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Calculate inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        o2.inJustDecodeBounds = false;
        FileInputStream stream = null;
        try {
            stream = new FileInputStream(res);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        Bitmap bitmap = BitmapFactory.decodeStream(stream, null, o2);
        try {
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    } else
        return null;
}

public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

如果要上传它们,还有一种方法可以从位图中检索字节。此方法还会压缩位图大小:

    public byte[] getBytesFromBitmap(Bitmap bitmap) {
    if (bitmap != null) {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
        return stream.toByteArray();
    } else
        return null;
}