我可以通过
MediaStore.Images.Media
正常获取图像宽度
但是我需要从从 dropbox 中选择的图像中获取图像的宽度和高度
所以目前我有以下方法从 dropbox 获取图像大小
private void getDropboxIMGSize(Uri uri){
String size = Long.toString(new File(uri.getPath()).length());
return size;
}
但我真正需要的是获取文件的宽度和高度值
有人知道如何实现吗?请帮忙!
private void getDropboxIMGSize(Uri uri){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(uri.getPath()).getAbsolutePath(), options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
}
没有办法。您必须创建一个位图对象。如果你使用
inJustDecodeBounds
标志位图将不会加载到内存中。事实上BitmapFactory.decodeFile
将返回null。在我的例子中uri
是图片的物理路径
如果你有文件 uri,Blackbelt 的答案是正确的。但是,如果您使用 官方相机教程 中的新文件提供程序,它将不起作用。这适用于那种情况:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(
getContext().getContentResolver().openInputStream(mPhotoUri),
null,
options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
Blackbelt 的答案大部分时间都可以使用
Options
,但我想通过使用 ExifInterface
提出另一种解决方案或后备解决方案。如果您有图像 URI,则可以使用完整路径创建 ExifInterface
,不需要位图对象或 BitmapFactory.Options
。
例如
int width = exif.getAttributeInt( ExifInterface.TAG_IMAGE_WIDTH, defaultValue );
int height = exif.getAttributeInt( ExifInterface.TAG_IMAGE_LENGTH, defaultValue );
解决方案是使用
new File(uri.getPath()).getAbsolutePath()
代替uri.toString()
通过将 uri.getPath() 替换为 uri.getLastPathSegment(),接受的答案返回宽度/高度为 0,它返回正确的尺寸
public static int[] getImageDimension(Uri uri){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(uri.getLastPathSegment()).getAbsolutePath(), options);
return new int[]{options.outWidth, options.outHeight};
}
除了@Blackbelt 的回答,您还应该使用以下代码从 Uri 检索文件路径:
public static String getPathFromURI(Context context, Uri contentUri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
DocumentsContract.isDocumentUri(context, contentUri)) {
return getPathForV19AndUp(context, contentUri);
} else {
return getPathForPreV19(context, contentUri);
}
}
private static String getPathForPreV19(Context context, Uri contentUri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
try {
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
return cursor.getString(columnIndex);
} finally {
cursor.close();
}
}
return null;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static String getPathForV19AndUp(Context context, Uri contentUri) {
String documentId = DocumentsContract.getDocumentId(contentUri);
String id = documentId.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = context.getContentResolver().
query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[]{ id }, null);
if (cursor != null) {
try {
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
return cursor.getString(columnIndex);
}
} finally {
cursor.close();
}
}
return null;
}
对于拥有内容 uri(以
content://
开头)的人,打开一个 InputStream
并解码该流以避免宽度和高度为 0。我会用 Kotlin
val uri: Uri = ....
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
val inputStream = contentResolver.openInputStream(uri)
BitmapFactory.decodeStream(inputStream, null, options)
val width = options.outWidth
val height = options.outHeight
请使用InputStream:
public int[] getImageSize(Uri uri){
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream input = this.getContentResolver().openInputStream(uri);
BitmapFactory.decodeStream(input, null, options); input.close();
return new int[]{options.outWidth, options.outHeight};
}
catch (Exception e){}
return new int[]{0,0};
}
会以数组形式返回:
int[]{ width , height }
这是@simplatek
提出的
ExifInterface
解决方案的具体工作示例,使用Uri
类型的扩展功能:
fun Uri.getImageDimensions(context: Context): Pair<Int, Int> {
val inputStream = context.contentResolver.openInputStream(this)!!
val exif = ExifInterface(inputStream)
val width = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, defaultValue)
val height = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, defaultValue)
return Pair(width, height)
}
如果你们一直在宽度和高度上得到 (0,0),您可能想要解码流,而不是文件。
这可能是因为您正在尝试从资产中读取图像。试试这个:
val b = BitmapFactory.decodeStream(context.assets.open("path/in/assets/img.png"))
val width = b.width
val height = b.height
如果您难以获得恢复尺寸 - 宽度和高度相互发生 - 对于肖像图像,这是一个扩展的解决方案:
private fun getImageSize(uri: Uri): Size {
var input = activity?.contentResolver?.openInputStream(uri)!!
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeStream(input, null, options)
input = activity?.contentResolver?.openInputStream(uri)!!
var orientation = ExifInterface(input).getAttribute(TAG_ORIENTATION)?.toInt()
if (orientation == null) {
orientation = ORIENTATION_NORMAL
}
if (orientation == ORIENTATION_ROTATE_90 || orientation == ORIENTATION_ROTATE_270) {
val outWidth = options.outWidth
val outHeight = options.outHeight
options.outWidth = outHeight
options.outHeight = outWidth
}
return Size(options.outWidth, options.outHeight)
}
重要的一点是 decodeStream 在完成其工作时关闭 inputStream。所以需要重新打开才能从ExifInterface获取方向。
对了,ExifInterface来自
androidx.exifinterface:exifinterface:x.x.x