I am trying to fetch file from device storage and showing it in image view .
Sometimes it is working perfectly fine, but sometimes not. Although bitmap is there but image view remains black.
Kindly suggest.
storage file Location
file:/storage/emulated/0/Download/Full-hd-nature-wallpapers-free-download2.jpg
method which is returning bitmap
public static Bitmap convertToBitmap(File file) {
URI uri = null;
try {
uri = file.toURI();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap bmp = BitmapFactory.decodeStream(uri.toURL().openStream(), new Rect(), options);
//bmp.recycle();
return bmp;
} catch (Exception e) {
return null;
}//catch
}
setting image
imageViewPatientImage.setImageBitmap(convertToBitmap(new File(mImagePath));
Try this:
Bitmap bitmap = getThumbnail(uri);
showImage.setImageBitmap(bitmap);
Pass Bitmap for Optimization:
public Bitmap getThumbnail(Uri uri) throws FileNotFoundException, IOException{
InputStream input = getContext().getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither=true;//optional
onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
input.close();
if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1))
return null;
int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;
double ratio = (originalSize > 500) ? (originalSize / 500) : 1.0;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
bitmapOptions.inDither=true;//optional
bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
input = getContext().getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
input.close();
return bitmap;
}
private static int getPowerOfTwoForSampleRatio(double ratio){
int k = Integer.highestOneBit((int)Math.floor(ratio));
if(k==0) return 1;
else return k;
}
Related
I have the common problem of display a picture in the correct rotation. My images are stored on a server. I call an image and display it in my app. Each image is rotated. So I found a correction with handleSamplingAndRotationBitmap.
public static Bitmap handleSamplingAndRotationBitmap(Context context, Uri selectedImage)
throws IOException {
int MAX_HEIGHT = 1024;
int MAX_WIDTH = 1024;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);
BitmapFactory.decodeStream(imageStream, null, options);
imageStream.close();
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
imageStream = context.getContentResolver().openInputStream(selectedImage);
Bitmap img = BitmapFactory.decodeStream(imageStream, null, options);
img = rotateImageIfRequired(img, selectedImage);
return img;
}
But it's impossible for me to send the correct Uri selectedImage.
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon = null;
final String myUrlStr = urldisplay;
URL url;
try {
url = new URL(myUrlStr);
uri = Uri.fromFile(new File(urldisplay));
uri2 = Uri.parse((urldisplay).toString());
mIcon = handleSamplingAndRotationBitmap(getContext(),uri2);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
I have the error
} catch (FileNotFoundException e) {
InputStream in = null;
try {
in = new URL(DataConstantes.lien_URLEtb + "Aucune_photo_etablissement.png").openStream();
} catch (IOException e1) {
flagError = true;
}
mIcon = BitmapFactory.decodeStream(in);
} catch (Exception e) {
flagError=true;
}
java.io.FileNotFoundException:
/http:/$$$$$$$$$$/appli/android_connect/Etablissement/abordage.jpg (No
such file or directory)
Do you know how I can send the correct URI ?
Thanks
I am writng a code to convert a png file back to bmp and save it on the sdcard. This is my current code.
FileInputStream in;
BufferedInputStream buf;
try {
in = new FileInputStream("File_Path_to_Read.png");
buf = new BufferedInputStream(in);
byte[] bMapArray= new byte[buf.available()];
buf.read(bMapArray);
Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
//Code segment to save on file
int numBytesByRow = bMap.getRowBytes() * bMap.getHeight();
ByteBuffer byteBuffer = ByteBuffer.allocate(numBytesByRow);
bMap.copyPixelsToBuffer(byteBuffer);
byte[] bytes = byteBuffer.array();
FileOutputStream fileOuputStream = new FileOutputStream("File_Path_To_Save.bmp");
fileOuputStream.write(bytes);
fileOuputStream.close();
if (in != null) {
in.close();
}
if (buf != null) {
buf.close();
}
} catch (Exception e) {
}
I am having problem in saving the bMap to the Sdcard. All the examples I found use bMap.compress(). Using this method I can't save as bmp. Can someone give an example on how to save the bitmap on the Sdcard?
Edit:
I can now save the file as .bmp to sdcard. However it won't get to the original size. Any sugguestions on converting the PNG to BMP?
File root = new File(Environment.getExternalStorageDirectory()
+ File.separator + "My_Folder" + File.separator);
root.mkdirs();
File myFile = new File(root, "ABC.jpg");
Bitmap bitmap = decodeFile(myFile, 800, 600);
OutputStream out = null;
File file = new File(mediaStorageDir.getAbsoluteFile() + "/DEF.jpg");
try {
out = new FileOutputStream(file);
bitmap .compress(Bitmap.CompressFormat.JPEG, 80, out);
out.flush();
out.close();
bitmap.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
public static Bitmap decodeFile(File f, int WIDTH, int HIGHT) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// The new size we want to scale to
final int REQUIRED_WIDTH = WIDTH;
final int REQUIRED_HIGHT = HIGHT;
// Find the correct scale value. It should be the power of 2.
int scale = 2;
while (o.outWidth / scale / 2 >= REQUIRED_WIDTH
&& o.outHeight / scale / 2 >= REQUIRED_HIGHT)
scale *= 2;
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {
}
return null;
}
I had used following code to convert inputstream object into bitmap. But it returns "out of memory error", and BitmapFactory Options always returns Zero.
S3ObjectInputStream inputStreamReceiptObject = objectReceiptFromAmazonS3
.getObjectContent();
Bitmap bitmapImageFromAmazon = null;
try {
if (inputStreamReceiptObject != null){
BitmapFactory.Options o = new BitmapFactory.Options();
o.inSampleSize = 8;
o.inJustDecodeBounds = true;
bitmapImageFromAmazon = BitmapFactory.decodeStream(inputStreamReceiptObject,null,o); // o is always null
if(bitmapImageFromAmazon == null){
System.out.println("Bitmap null");
}
}
Advance Thanks for any help !
SOLUTION : ( Lot of thanks to Honourable Don and Honourable Akshat )
ByteArrayOutputStream baos = null ;
InputStream is1 = null,is2 = null;
try {
baos = new ByteArrayOutputStream();
// Fake code simulating the copy
// You can generally do better with nio if you need...
// And please, unlike me, do something about the Exceptions :D
byte[] buffer = new byte[1024];
int len;
while ((len = inputStreamReceiptObject.read(buffer)) > -1 ) {
baos.write(buffer, 0, len);
}
baos.flush();
// Open new InputStreams using the recorded bytes
// Can be repeated as many times as you wish
is1 = new ByteArrayInputStream(baos.toByteArray());
is2 = new ByteArrayInputStream(baos.toByteArray());
bitmapImageFromAmazon = getBitmapFromInputStream(is1,is2);
if(bitmapImageFromAmazon == null)
System.out.println("IMAGE NULL");
else
System.out.println("IMAGE NOT NULL");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
baos.close();
is1.close();
is2.close();
}
public Bitmap getBitmapFromInputStream(InputStream is1,InputStream is2) throws IOException {
Bitmap bitmap = null;
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is1,null,o);
//Find the correct scale value. It should be the power of 2.
int scale=1;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
bitmap = BitmapFactory.decodeStream(is2, null, o2);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
Why dont you try and scale the bitmap image down? Thats mostly the reason why your app showed OOM exception
BitmapFactory.Options o = new BitmapFactory.Options();
o.inScaled = false;
o.inJustDecodeBounds = true;
FileInputStream stream1 = new FileInputStream(f);
BitmapFactory.decodeStream(stream1, null, o);
stream1.close();
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70; //This is the max size of the bitmap in kilobytes
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
FileInputStream stream2 = new FileInputStream(f);
Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
The Out Of Memory error should be as it says: you do not have enough memory on your device to render the entire image. You need to ensure that the image you're downloading from S3 is not too big for the device.
To help you debug, try running downloading a smaller image to see if you are still receiving the OOM errors
URLConnection conn = new URL("http://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Victoria_Parade_postcard.jpg/120px-Victoria_Parade_postcard.jpg").openConnection();
InputStream stream = conn.getInputStream();
Bitmap image = BitmapFactory.decodeStream(stream, null, null);
The o you pass into decodeStream is null because of the OOM error (it must have gone out of scope when you examined it in the debugger).
I am working on a code sample where I have to choose an image from gallery the code is working but after selection of image from gallery I get OutOfMemoryError in my OnActivityResult
I am able to get small images but large images are creating problem.
Here is my code:
try{
Uri selectedImageUri = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImageUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
bitmap = BitmapFactory.decodeFile(filePath);
_profileImage.setImageBitmap(bitmap);
_profileImage.setScaleType(ScaleType.FIT_XY);
Constant._addPhotoBitmap=bitmap;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Bitmap resizedbitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
resizedbitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte [] _byteArray = baos.toByteArray();
String base64 = Base64.encodeToString(_byteArray,Base64.DEFAULT);
Constant._addPhotoBase64 = base64;
}catch (OutOfMemoryError e) {
e.printStackTrace();
Constant.showAlertDialog(Constant.errorTitle,
"Image size is too large.Please upload small image.",
DriverProfileScreen.this, false);
} catch (Exception e) {
e.printStackTrace();
}
You are deirectly decoding the file based on its uri path..thats why it is throwing exception..before loading image set some options..this will reduce the memory for the image loading..Use this method for loading image whatever size you want..
/**
* returns the thumbnail image bitmap from the given url
*
* #param path
* #param thumbnailSize
* #return
*/
private Bitmap getThumbnailBitmap(final String path, final int thumbnailSize) {
Bitmap bitmap;
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, bounds);
if ((bounds.outWidth == -1) || (bounds.outHeight == -1)) {
bitmap = null;
}
int originalSize = (bounds.outHeight > bounds.outWidth) ? bounds.outHeight
: bounds.outWidth;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = originalSize / thumbnailSize;
bitmap = BitmapFactory.decodeFile(path, opts);
return bitmap;
}
In Android Developer document there is Topic called
Displaying Bitmaps Efficiently
So please go through it.
http://developer.android.com/training/displaying-bitmaps/index.html
Hope this will help you.
Generally android device heap size is only 16MB (varies from device/OS see post Heap Sizes), if you are loading the images and it crosses the size of 16MB , it will throw out of memory exception, instead of using the Bitmap for , loading images from SD card or from resources or even from network try to using getImageUri , loading bitmap require more memory , or you can set bitmap to null if your work done with that bitmap.
So,You need to downscale you image using below code:
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
Scale the bitmap first , then load it. It will solve the problem.
You can use the following method to do that.
private Bitmap getScaledBitmap(Uri uri){
Bitmap thumb = null ;
try {
ContentResolver cr = getContentResolver();
InputStream in = cr.openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize=8;
thumb = BitmapFactory.decodeStream(in,null,options);
} catch (FileNotFoundException e) {
Toast.makeText(PhotoTake.this , "File not found" , Toast.LENGTH_SHORT).show();
}
return thumb ;
}
Hope it helps.
try this code:
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.ActivityManager;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
public class UserImageLoaderWithCache implements ComponentCallbacks {
private KCLruCache cache;
public UserImageLoaderWithCache(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass() * 1024 * 1024;
cache = new KCLruCache(memoryClass);
}
public void display(String url, ImageView imageview, int defaultresource) {
imageview.setImageResource(defaultresource);
Bitmap image = cache.get(url);
if (image != null) {
imageview.setImageBitmap(image);
}
else {
new SetImageTask(imageview).execute(url);
}
}
private class KCLruCache extends LruCache<String, Bitmap> {
public KCLruCache(int maxSize) {
super(maxSize);
}
}
private class SetImageTask extends AsyncTask<String, Void, Integer> {
private ImageView imageview;
private Bitmap bmp;
public SetImageTask(ImageView imageview) {
this.imageview = imageview;
}
#Override
protected Integer doInBackground(String... params) {
String url = params[0];
try {
bmp = getBitmapFromURL(url);
if (bmp != null) {
cache.put(url, bmp);
} else {
return 0;
}
} catch (Exception e) {
e.printStackTrace();
return 0;
} catch (OutOfMemoryError o) {
o.printStackTrace();
return 0;
}
return 1;
}
#Override
protected void onPostExecute(Integer result) {
if (result == 1) {
imageview.setImageBitmap(bmp);
}
super.onPostExecute(result);
}
private Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}catch (OutOfMemoryError o) {
o.printStackTrace();
return null;
}
}
}
public void onLowMemory() {
}
/*public void onTrimMemory(int level) {
if (level >= TRIM_MEMORY_MODERATE) {
cache.evictAll();
}
else if (level >= TRIM_MEMORY_BACKGROUND) {
cache.trimToSize(cache.size() / 2);
}
}*/
public void onConfigurationChanged(Configuration arg0) {
// TODO Auto-generated method stub
}
}
I have used below code and used bitmap to store resized Image in local storage and It worked like charm
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap b = BitmapFactory.decodeFile(path, options);
here path is image Uri path in String
I use below code to get the file pathof image in sd card.
File[] f = (Environment.getExternalStorageDirectory()).listFiles();
int i;
for(i = 0; i < f.length; i++) {
if(f[i].isFile()) {
if(isPhoto(f[i].getName())) {
Filepath.add(f[i].getAbsolutePath());
}
}
else {
//recursive
}
}
I want to get the path of the thumbnail of image by know original image path.
How to do it?
You can get the Uri from a file like this:
Uri uri = Uri.fromFile(new File("/mnt/images/abc.jpg"));
Bitmap thumbnail = getPreview(uri);
And the following function gives you the thumbnail:
Bitmap getPreview(URI uri) {
File image = new File(uri);
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image.getPath(), bounds);
if ((bounds.outWidth == -1) || (bounds.outHeight == -1))
return null;
int originalSize = (bounds.outHeight > bounds.outWidth) ? bounds.outHeight
: bounds.outWidth;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = originalSize / THUMBNAIL_SIZE;
return BitmapFactory.decodeFile(image.getPath(), opts);
}
You can make your own thumbnail image:
byte[] imageData = null;
try
{
final int THUMBNAIL_SIZE = 64;
FileInputStream fis = new FileInputStream(fileName);
Bitmap imageBitmap = BitmapFactory.decodeStream(fis);
imageBitmap = Bitmap.createScaledBitmap(imageBitmap, THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
imageData = baos.toByteArray();
}
catch(Exception ex) {
}