简体   繁体   English

我可以从android中的uri获取图像文件的宽度和高度吗?

[英]can i get image file width and height from uri in android?

i can getting the image width through MediaStore.Images.Media normally我可以正常通过MediaStore.Images.Media获取图像宽度

but i need to getting the image width and height from image which selected from dropbox但我需要从 Dropbox 中选择的图像中获取图像的宽度和高度

so currently i have following method to getting image size from dropbox所以目前我有以下方法从 Dropbox 获取图像大小

private void getDropboxIMGSize(Uri uri){
    String size = Long.toString(new File(uri.getPath()).length());
    return size;
}

but what i actually need are getting the file width and height value但我真正需要的是获取文件的宽度和高度值

anyone know how to achieve that?please help!有人知道如何实现吗?请帮忙!

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;
 
}

no there is no way.没有没有办法。 You have to create a Bitmap object.您必须创建一个 Bitmap 对象。 if you use the inJustDecodeBounds flag the bitmap would not be loaded in memory.如果您使用inJustDecodeBounds标志,位图将不会加载到内存中。 In fact BitmapFactory.decodeFile will return null.事实上BitmapFactory.decodeFile将返回 null。 In my example uri is the phisical path to the image在我的示例中, uri是图像的物理路径

Blackbelt's answer is correct if you have a file uri.如果您有文件 uri,Blackbelt 的答案是正确的。 However, if you are using the new file providers as in the official camera tutorial , it won't work.但是,如果您像 官方相机教程那样使用新的文件提供程序,它将不起作用。 This works for that case:这适用于这种情况:

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's answer will work most of the time using Options , but I would like to propose another solution or fallback solution by using the ExifInterface . Blackbelt 的答案大部分时间都可以使用Options ,但我想通过使用ExifInterface提出另一种解决方案或后备解决方案。 If you have the image URI, you can create the ExifInterface using the full path, no need for Bitmap object nor BitmapFactory.Options .如果您有图像 URI,则可以使用完整路径创建ExifInterface ,不需要 Bitmap 对象或BitmapFactory.Options

ex.前任。

int width = exif.getAttributeInt( ExifInterface.TAG_IMAGE_WIDTH, defaultValue );
int height = exif.getAttributeInt( ExifInterface.TAG_IMAGE_LENGTH, defaultValue ); 

This set of utilities to work with the Size abstraction in Android.组实用程序与 Android 中的 Size 抽象一起使用。

It contains an class SizeFromImage.java You can use it like this:它包含一个类SizeFromImage.java你可以这样使用它:

ISize size = new SizeFromImage(imgFilePath);
size.width();
size.hight();

解决方案是使用new File(uri.getPath()).getAbsolutePath()而不是uri.toString()

In addition to @Blackbelt answer you should use the following code to retrieve file path from Uri:除了@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;
}

The accepted answer returns with me a 0 of width/height, by replacing uri.getPath() with uri.getLastPathSegment(), it returns the correct dimensions通过将 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};
}

For folks having content uri (starting with content:// ), open an InputStream & decode that stream to avoid getting 0 width and height.对于拥有内容 uri(以content://开头)的人,打开InputStream并解码该流以避免获得 0 宽度和高度。 I'll use Kotlin我会用 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

Please use 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};
}

It'll return in array form:它将以数组形式返回:

int[]{ width , height }

If you guys keep getting (0,0) in the width and height, you probably want to decode a stream, and not a file.如果你们一直在宽度和高度上得到 (0,0),你可能想要解码一个流,而不是一个文件。

It probably because you're trying to read an image from the assets.这可能是因为您试图从资产中读取图像。 Try this:试试这个:

val b = BitmapFactory.decodeStream(context.assets.open("path/in/assets/img.png"))
val width = b.width
val height = b.height

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM