can i get image file width and height from uri in android?
Asked Answered
M

11

52

i can getting the image width through MediaStore.Images.Media normally

but i need to getting the image width and height from image which selected from dropbox

so currently i have following method to getting image size from 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!

Merthiolate answered 8/5, 2013 at 12:36 Comment(0)
B
124
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. if you use the inJustDecodeBounds flag the bitmap would not be loaded in memory. In fact BitmapFactory.decodeFile will return null. In my example uri is the phisical path to the image

Brigettebrigg answered 8/5, 2013 at 12:39 Comment(17)
will this way cause oom fc? no need to set to null/recycling after getting width and height?Merthiolate
no . Since the bitmap will be not loaded in memory it will not cause OOM neither you need to recycle it.Brigettebrigg
but i getting width and height is 0 at logcat?Merthiolate
You have access to the phisical image?Brigettebrigg
I just chosen a jpeg imageMerthiolate
yes,i also found that dropbox uri are start with file:// and gallery image start with content://Merthiolate
imageHeight and imageWidth are zero? Sounds strange. Can you check the image size with a file expolorer?Brigettebrigg
it's odds,I can see the file path in logcat,but I can't find the file in file explorer,search /data /sdcard and internal memory /dataMerthiolate
good :). I will update my answer with the modification you provide in yoursBrigettebrigg
@blackbelt I propose please edit your sample code with regards to jkjk's answer.Personality
@Personality thanks for the input. The OP does not want the file size. What he needs is: i need to get the image width and heightBrigettebrigg
@blackbelt Ok! But I mean please change decodeFile(uri.getPath()).getAbsolutePath(), to decodeFile(new File(uri.getPath()).getAbsolutePath(),Personality
This is not a solution, since Uris may not be actually files.Walhalla
It was at the time the answer was written Christian.Brigettebrigg
I don't know why, but it returns width and height 0Rotman
I am getting 0 height and 0 width using this solutionSavagism
Hi, how does decodeFile get the dimensions? Are they from the meta-data or are they from really decoding the image data? Thanks.Showbread
C
25

Blackbelt's answer is correct if you have a file uri. 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;
Catricecatrina answered 12/7, 2017 at 13:19 Comment(3)
Thank you for the solution. It is able to get height width of content://media/external/images/media/272. However, the height and width is reverted (imageHeight = actual width and imageWidth = actual height). Do you know how to solve it?Calistacalisthenics
@h8pathak I'm not up to date on this stuff anymore. Feel free to edit it, or comment the exact code and I'll edit it.Catricecatrina
This works but is very slow. Using ExifInterface is much fasterSieber
I
16

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. If you have the image URI, you can create the ExifInterface using the full path, no need for Bitmap object nor BitmapFactory.Options.

ex.

int width = exif.getAttributeInt( ExifInterface.TAG_IMAGE_WIDTH, defaultValue );
int height = exif.getAttributeInt( ExifInterface.TAG_IMAGE_LENGTH, defaultValue ); 
Infatuate answered 20/1, 2016 at 0:56 Comment(1)
this solution only works for Android API 23 and aboveJohanson
M
3

the solution is use new File(uri.getPath()).getAbsolutePath() instead of uri.toString()

Merthiolate answered 8/5, 2013 at 13:7 Comment(1)
This is not a solution, since Uris may not be actually files.Walhalla
E
3

The accepted answer returns with me a 0 of width/height, by replacing uri.getPath() with uri.getLastPathSegment(), it returns the correct dimensions

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};
}
Eyler answered 1/9, 2019 at 5:41 Comment(1)
This still returns 0 for width and height.Arundinaceous
B
3

For folks having content uri (starting with content://), open an InputStream & decode that stream to avoid getting 0 width and height. I'll use 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
Bromidic answered 27/7, 2020 at 13:52 Comment(0)
P
3

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 }
Purdah answered 16/8, 2020 at 9:37 Comment(1)
one answer that solve the problemArmlet
C
2

In addition to @Blackbelt answer you should use the following code to retrieve file path from 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;
}
Chamblee answered 28/10, 2016 at 8:30 Comment(0)
A
1

This is a concrete working example of the ExifInterface solution proposed by @simplatek, using an extension function on the Uri type:

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)
}
Arundinaceous answered 2/8, 2022 at 22:18 Comment(0)
L
0

If you guys keep getting (0,0) in the width and height, you probably want to decode a stream, and not a file.

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
Lamasery answered 1/12, 2020 at 15:59 Comment(0)
M
0

If you struggle with getting reverted dimensions - width and height taking place each other - for portrait images, this is an extended solution:

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

An important point is that decodeStream closes the inputStream when finishes its job. So it is required to be opened again to be able to get orientation from ExifInterface.

By the way, ExifInterface comes from androidx.exifinterface:exifinterface:x.x.x

Maracaibo answered 1/4, 2023 at 3:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.