I would like to get a bitmap's dimensions in Android without reading the entire file.
I tried using the recommended inJustDecodeBounds and a custom InputStream that logged the read()s. Unfortunately based on this, the Android BitmapFactory appears to read a large amount of bytes.
Similar to:
Java/ImageIO getting image dimensions without reading the entire file? for Android, without using ImageIO.
You are right to use inJustDecodeBounds. Set it to true and make sure to include Options in decode. This just reads the image size.
There is no need to read a stream. Just specify the path in the decode.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(<pathName>, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
java.net.URL imageUrl = new java.net.URL("https://yourUrl.com");
HttpURLConnection connection = (HttpURLConnection)imageUrl.openConnection();
connection.connect();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(connection.getInputStream(), null, options);
int imageWidth = options.outWidth;
int imageHeight = options.outHeight;
Related
I need to get the height and width of an Image which is stored on my Android Device. I already know how to get the file(image), I just need some code how to get the height and width from that file.
Of course, you can.
you can try this:
Bitmap bitmap = BitmapFactory.decodeFile("your image path");
int width = bitmap.getWidth();
int height = bitmap.getHeight();
note: You should have permission to access the file.
If you only need the dimensions of the image but not the decoded image itself, you can use BitmapFactory.Options with inJustDecodeBounds = true to do so:
BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
decodeOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, decodeOptions);
//decodeOptions.outWidth and decodeOptions.outHeight now contain the image dimensions
This way the decode function will return null but set the out variables of the options object. This saves both CPU and memory which can be advantageous if you are processing lots of images at once.
I'm trying to get the width and height of an image, which I load from an image I pick from the gallery.
For testing, I used images from the drawable folder, I used this code:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
Now I got a bitmap that doesn't come from my drawable folder I can't do this:
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
What would be the proper way to retrieve the w/h.
There is a similar method working with an InputStream: BitmapFactory.decodeStream.
Assuming you have a File with your image (exceptions ommitted) :
BitmapFactory.decodeStream(new FileInputStream(myImageFile), null, options);
(this method works for any InputStream)
If you have a Uri and you need the Bitmap, you could theoretically do this
Bitmap troublinglyLargeBmp =
MediaStore.Images.Media.getBitmap(
State.mainActivity.getContentResolver(), theUri );
but it will crash every time,
so you do this .........
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
AssetFileDescriptor fileDescriptor =null;
fileDescriptor =
State.mainActivity.getContentResolver().openAssetFileDescriptor( theUri, "r");
Bitmap actuallyUsableBitmap
= BitmapFactory.decodeFileDescriptor(
fileDescriptor.getFileDescriptor(), null, options);
Utils.Log("'4-sample' method bitmap ... "
+actuallyUsableBitmap.getWidth() +" "
+actuallyUsableBitmap.getHeight() );
that's fantastic and is the working solution.
Notice the factor of "four" which tends to work well, in current conditions (2014) with typical camera sizes, etc. HOWEVER, it would be best to guess or learn exactly the size of the image data at theUri, and then using that information, intelligently choose that factor.
In short, how to correctly choose that scale factor when you load a Uri ?
Android experts, is this a well-known problem, is there a solution? Thanks from your iOS->Android friends! :)
See the Android guide to handling large bitmaps.
Specifically this section:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
EDIT
In your case, you'll replace the decodeResource line with:
BitmapFactory.decodeFileDescriptor(fileDescriptor.getFileDescriptor(), null, options);
I need to get the width and height of a bitmap but using this gives an out of memory exception:
Resources res=getResources();
Bitmap mBitmap = BitmapFactory.decodeResource(res, R.drawable.pic);
BitmapDrawable bDrawable = new BitmapDrawable(res, mBitmap);
//get the size of the image and the screen
int bitmapWidth = bDrawable.getIntrinsicWidth();
int bitmapHeight = bDrawable.getIntrinsicHeight();
I read the solution at the question Get bitmap width and height without loading to memory but what would be the inputStream here?
You need to specify some BitmapFactory.Options as well:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
bDrawable will not contain any bitmap byte array. Taken from here: Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap.
Use this
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
see http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Obviously this is an expensive/time-consuming operation. Any way to improve this?
Bitmap bm = BitmapFactory.decodeStream((InputStream) new URL(
someUrl).getContent());
I'm guessing there's really no way to avoid this relatively intense operation, but wanted to see if anyone had any tweaks they could recommend (aside from caching the actual bitmap, which for whatever reasons simply isn't relevant here)
If you don't need the full resolution you can have it only read ever nth pixel, where n is a power of 2. You do this by setting inSampleSize on an Options object which you pass to BitmapFactory.decodeFile. You can find the sample size by just reading the meta-data from the file in a first pass by setting inJustDecodeBounds on the Options object. Aside from that - no, I don't think there's an easy way to make to go any faster than it already does.
Edit, example:
Options opts = new Options();
// Get bitmap dimensions before reading...
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, opts);
int width = opts.outWidth;
int height = opts.outHeight;
int largerSide = Math.max(width, height);
opts.inJustDecodeBounds = false; // This time it's for real!
int sampleSize = ??; // Calculate your sampleSize here
opts.inSampleSize = sampleSize;
Bitmap bmp = BitmapFactory.decodeFile(path, opts);