Unable to retrieve the image from SDCard - android

Drawable image = Drawable.createFromPath(newImagepath);
defective_image.setBackgroundDrawable(image);
The image is stored in the newImagePath variable which is a String. The above throws an outOfMemory Exception.
I also tried retrieving the image into a Bitmap object.
Bitmap bitmapImg= BitmapFactory.decodeFile(newImagepath);
In the above case the bitmapImg is Null. (Without any exception)
However if it is retrieved as a file, it's successful. This doesn't serve my purpose because I want this image to be the background of a RelativeLayout.
File imageFile = new File(newImagepath);
String imgPath = imageFile.getAbsolutePath();
The imgPath is the same as the newImagePath, concluding the path is not wrong. I also verified the image's existence in the SDCard.
This image was captured from the device's camera. This code is working on the emulator successfully. When debugged on the device the above said faults were noticed.
I also tried:-
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

It seems to be a memory issue. So I suggest to decode bitmap size with the option
options.inJustDecodeBounds = true;
then getting the size of this bitmap by looking at fields (don't try to use bitmap : it will be null) :
options.outWidth;
options.outHeight;
Then creating a scaled bitmap (depending on the screen dimension). To do this, you can look at
BitmapFactory.Options.inSampleSize

I would rather use a BitmapFactory to decode the Image from the file-path:
Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
jpgView.setImageDrawable(bitmap);

Related

BitmapFactory returns difference sizes of Bitmap from drawable and from file

I have two copies of same image. One of them is inside the resource folder (default drawable) of the app and the other one is on the external storage.
I get the Bitmap with the following codes:
// Get from storage
BitmapFactory.decodeFile(image.getAbsolutePath());
// Get from resource
BitmapFactory.decodeResource(getResources(), R.drawable.image);
However, they result in different sizes in ImageView with wrap_content in height and width. How can I solve this?
This behavior is because of the implementation of BitmapFactory. During the call in decodeResourceStream from decodeResource, it will assign a BitmapFactory.Options wtih inDensity set to DisplayMetrics.DENSITY_DEFAULT if BitmapFactory.Options is null.
On the other hand, decodeFile is passed through setDensityFromOptions which return immediately if BitmapFactory.Options is null.
Therefore, one of the solutions is to scale the density of decodeFile by the following code.
BitmapFactory.Options option = new BitmapFactory.Options();
option.inDensity = DisplayMetrics.DENSITY_DEFAULT;
Bitmap bitmap = BitmapFactory.decodeFile(image.getAbsolutePath(), option);
If you want to do it in reverse, you can use the following code.
InputStream inputStream = context.getResources().openRawResource(R.drawable.image);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
Notice that there will be "Constants and Resource Type Mismatches", but it can still be compiled. decodeResource also call openRawResource as InputStream, so this is fine.

Unable to display image after loading it in a Bitmap

First I save the image using FileOutPutStream etc..
This should be working since I am able to see the image in the SDCard using 'Astro File Manager'. (The path is also correct according to AFM)
However when I try to load this image as a Bitmap and display it in an ImageViewer I get nothing.
ImageView image = (ImageView) findViewById(R.id.IMAGE);
Bitmap bitmap = BitmapFactory.decodeFile(requestList.get(0).getImage());
image.setImageBitmap(bitmap);
I've checked the byteCount() on the bitmap and it returns a large number so I'm guessing that's fine.
So as I am able to load the file in AFM my guess is that it should be loadable by me as well, but maybe in another way that I'm currently attempting?
The Image is taken from another phones camera, uploaded to a server and then downloaded and stored by my phone. (I believe all of this works though)
Try this :
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(photoPath, options);
selected_photo.setImageBitmap(bitmap);

Following the tutorial on using bitmaps to make android images smaller

I am learning how to use Bitmap to scale down images instead of having them crash the app. I am following the developer page for android at http://developer.android.com/training/displaying-bitmaps/load-bitmap.html. I have a couple of questions about the 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;
String imageType = options.outMimeType;
For the code above it creates a new bitmapFactory and decodes the widget. Why use R.id.myimage over R.drawable.image? I am assuming that R.id.myimage refers to a image view while R.drawable.image I added and it directly refers to the image I want rescaled. Finally what does outMimeType refer too?
You know, I'm pretty sure that's a mistake. The resource you want is indeed a drawable, referenced by R.drawable.image.
The options.outMimetype just tells you what the mimetype of the decoded resource is (a PNG, a JPEG, etc.), if that information is available.

Incorrect image dimensions in android when using Bitmap

I have.png image file stored as a resource in my android application.
In my code, i am allocationg new Bitmap instance from that image as follow:
Bitmap img = BitmapFactory.decodeResource(getResources(), R.drawable.imgName);
But when I read the image dimensions from the Bitmap object using getWight() and getHeight() methods,
int width = img.getWidth();
int height = img.getHeight();
I am getting different results from the original image... Can some one explain me what am I missing, and how can I retreive the image size?
(My project is complied with android 2.2 - API 8)
Edit:
Ok - found out how to get the real dimensions:
setting inJustDecodeBounds property of the BitmapFactory.Options class to true as follow:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.imgName, options);
width = options.outWidth;
height = options.outHeight;
The problem now is that the decoder returns null when we send Options argument, so I need to decode again like I did before (without Options argument...) to retrieve Bitmap instance -bizarre, isnt it?
To get exact resource image use:
BitmapFactory.Options o = new Options();
o.inScaled = false;
Bitmap watermark = BitmapFactory.decodeResource(context.getResources(), id, o);
This turns off the automatic screen density scaling.
Update:
I'm sure you realized this by now, but inJustDecodeBounds does just that, it finds the dimensions. You will not get an image. That option is generally for doing custom scaling. You end up calling decodeResource twice, the second time setting:
options.inJustDecodeBounds = false;
and making any adjustments to the options based on your:
width = options.outWidth;
height = options.outHeight;
Android scales your image for different densities (in a way for different screen resolutions and sizes). Place a separate copy of your image in drawable-ldpi, drawable-hdpi,drawable-xhdpi , drawable folders.

Display big image from SD card in Android

In Android, how do you display an image (of any size) from the SD card, without getting an out of memory error?
Is it necessary to put the image in the Media Store first?
A pseudo-code example would be greatly appreciated. Extra points if the displayed image is as big as the memory level of the device allows.
Edit: this question has actually been already answered at Strange out of memory issue while loading an image to a Bitmap object (the two highest voted answers). It does also use the inSampleSize option, but with a small method to automatically get the appropriate value.
My original answer:
The inSampleSize of the BitmapFactory.Options class can solve your issue (http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize). It works by making a bitmap with the resulting width and height 1/inSampleSize than the original, thus reducing memory consumption (by inSampleSize^2?). You should read the doc before using it.
Example:
BitmapFactory.Options options = new BitmapFactory.Options();
// will results in a much smaller image than the original
options.inSampleSize = 8;
// don't ever use a path to /sdcard like this, but I'm sure you have a sane way to do that
// in this case nebulae.jpg is a 19MB 8000x3874px image
final Bitmap b = BitmapFactory.decodeFile("/sdcard/nebulae.jpg", options);
final ImageView iv = (ImageView)findViewById(R.id.image_id);
iv.setImageBitmap(b);
Log.d("ExampleImage", "decoded bitmap dimensions:" + b.getWidth() + "x" + b.getHeight()); // 1000x485
However here it will only work for images up to, I guess, inSampleSize^2 times the size of the allowed memory and will reduce the quality of small images.
The trick would be to find the appropriate inSampleSize.
I'm displaying any sized images using code:
ImageView imageView=new ImageView(this);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setAdjustViewBounds(true);
FileInputStream fis=new FileInputStream(file);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize=2; //try to decrease decoded image
options.inPurgeable=true; //if necessary purge pixels into disk
options.inScaled=true; //scale down image to actual device density
Bitmap bm=BitmapFactory.decodeStream(is, null, options);
imageView.setImageBitmap(bm);
fis.close();
For example:
yourImgView.setImageBitmap(BitmapFactory.decodeFile("/sdcard/1.jpg"));
http://www.developer.com/ws/other/article.php/3748281/Working-with-Images-in-Googles-Android.htm covers all you'll ever need to know on the subject of images, including getting them from an SD card. You'll notice the code to do so there, copied below:
try {
FileOutputStream fos = super.openFileOutput("output.jpg",
MODE_WORLD_READABLE);
mBitmap.compress(CompressFormat.JPEG, 75, fos);
fos.flush();
fos.close();
} catch (Exception e) {
Log.e("MyLog", e.toString());
}

Categories

Resources