I am fetching list of urls of images from my server and setting them in recyclerview using adapter.My requirement is to fetch the color from the image and set that color to the background of the textview,for that i am using palette library as below.But i am getting the error InputStream line unable to sort the problem,any help will be appreciated.
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
Album albm=malbumlist.get(position);
holder.title.setText(albm.getProductName());
System.out.println("Displaying the image on Recycleview");
Glide.with(mcontext).load(albm.getImageUrl()).into(holder.thumbnail);
try {
URL url=new URL(albm.getImageUrl());
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream is=connection.getInputStream(); /* Getting error here */
bmp=BitmapFactory.decodeStream(is);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Palette.generateAsync(bmp, new Palette.PaletteAsyncListener() {
#Override
public void onGenerated(Palette palette) {
int bgcolor=palette.getVibrantColor(mcontext.getResources().getColor(android.R.color.black));
holder.linearLayout.setBackgroundColor(bgcolor);
}
});
}
check this... i am using this one..if its helpful please make this answer as right.
String path = imageToUploadUri.getPath();
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap b = BitmapFactory.decodeFile(path, options);
int bmpHeight = b.getHeight();
int bmpWidth = b.getWidth();
if (bmpHeight > 1500) {
bmpHeight = bmpHeight / 4;
bmpWidth = bmpWidth / 4;
}
Bitmap out = Bitmap.createScaledBitmap(b, bmpWidth, bmpHeight, false);
File file = new File(dir, "resize.png");
FileOutputStream fOut;
try {
fOut = new FileOutputStream(file);
out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
b.recycle();
out.recycle();
} catch (Exception e) {
}
try this code
/**
* load image from url and fill it in image view
*
* #param context
* #param imageView the view which will be filled by the bitmap result
* #param imageUrl the image link
* #param imageHolder this drawable for place holder image
*/
public Request loadImage(Context context, ImageView imageView, String imageUrl, #DrawableRes int imageHolder) {
GlideUrl glideUrl = new GlideUrl(imageUrl, new LazyHeaders.Builder()
.build());
(imageHolder == 0)
imageHolder = R.drawable.error_image;
return Glide.with(context)
.load(glideUrl)
.error(imageHolder)
.into(imageView).getRequest();
}
here is my call to the method
loadImage(context, imageView,imageUrl, 0)
Example with Glide library, here you have an example:
Bitmap bitmap = Glide.
with(MainActivity.this).
load("https://YourLink").
asBitmap().
into(50, 50).
get();
Glide Second Example:
Glide.with(getApplicationContext())
.load("https://YourLink")
.asBitmap()
.into(new BitmapImageViewTarget(imgView) {
#Override
protected void setResource(Bitmap resource) {
//Your bitmap here!
super.setResource(resource);
}
});
Another solution here is with Android-Universal-Image-Loader library for loading images from URL, 1) than when image loaded successfully the library callback will return for you Bitmap of that image OR 2) you can get only Bitmap synchronously.
Example with Universal Image Loader library (from library documentation):
ImageLoader imageLoader = ImageLoader.getInstance(); // Get singleton instance
case1:
// Load image, decode it to Bitmap and return Bitmap to callback
imageLoader.loadImage(imageUri, new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
// Do whatever you want with Bitmap
}
});
case2:
// Load image, decode it to Bitmap and return Bitmap synchronously
Bitmap bmp = imageLoader.loadImageSync(imageUri);
Related
I am using the following code to download an image from an url, then saving to sqlite and then view in imageview in an activity.
new LoadProfileImage().execute(jsonObject.getString("image"), id, title, promoexpdate, String.valueOf(i),flag,promostartDate);
The above code is used to call the function to do the above work.
private class LoadProfileImage extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
String x,y,z,a,w,s;
protected Bitmap doInBackground(String... uri) {
String url = uri[0];
Log.d("ImageURL",url);
x = uri[1];
y = uri[2];
z = uri[3];
a = uri[4];
w = uri[5];
s = uri[6];
Log.d("LogValue",url+x+y+z+a+w+s);
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(url).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (IOException e) {
Log.e("ErroronImageParsing", e.getLocalizedMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
if (result != null) {
int width = result.getWidth();
int height = result.getHeight();
Bitmap newBitmap = Bitmap.createScaledBitmap(result, width / 2, height / 2, true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
newBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
buffer = out.toByteArray();
if (result!= newBitmap){
result.recycle();
}
Log.d("ImageUploaded", "Success");
}
try {
dbManager.open();
Cursor cursor = dbManager.fetch_PromsID(x);
if (cursor.getCount() > 0){
String fla = cursor.getString(cursor.getColumnIndex(DatabaseHelper.PRO_FLAG));
String pri_ID = cursor.getString(cursor.getColumnIndex(DatabaseHelper.PRO_ID));
if (!w.equals(fla)) {
dbManager.update_Promotions(pri_ID,y,z, buffer,w,s);
}
}else {
dbManager.insertPromotions(x,y,z,buffer,w,s);
}
} catch (SQLException e) {
e.printStackTrace();
}
SqliteData();
panel.setVisibility(View.GONE);
dbManager.close();
}
}
Here, when the code below is executed, image from the url is saved into internal storage. I wish to disable the auto saving while maintaining my intention. Thanks in advance...
Bitmap newBitmap = Bitmap.createScaledBitmap(result, width / 2, height / 2, true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
newBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
buffer = out.toByteArray();
Try to use third library like Picasso or Glid
that offer
loading without caching
loading with memory or storage caching
you can do it with single line of code
Picasso.with(context).load(imageUrl)
.error(R.drawable.error)
.placeholder(R.drawable.placeholder)
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
.into(imageView);
I am working to add an image from the gallery horizontally using recycler view as follows. I could able to add images next to each other.
The following code works but crashes sometimes because of out of memory concerns.
RecyclerViewAdapter, I am calling setSelectedPic method to load the image.
#Override
public void onBindViewHolder(final ListViewHolder holder, int position) {
PostProductImageLIst item = mItems.get(position);
ImageUtil.setSelectedPic(holder.imgViewIcon, item.getPath());
}
ImageUtil Class
public static void setSelectedPic(CustomNetworkImageView view, String url) {
Context context = view.getContext();
ImageLoader imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
if (!TextUtils.isEmpty(url)) {
if (url.startsWith("http")) {
imageLoader.get(url, ImageLoader.getImageListener(view,
R.drawable.image, android.R.drawable
.ic_dialog_alert));
view.setImageUrl(url, imageLoader);
} else {
try {
Uri uri = Uri.parse(url);
InputStream is = context.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
view.setLocalImageBitmap(bitmap);
if (is!=null) {
is.close();
}
} catch (Exception ex) {
Log.e("Image", ex.getMessage(), ex);
}
}
} else {
view.setImageUrl("", CustomVolleyRequest.getInstance(view.getContext()).getImageLoader());
}
}
And then I decide to resize the images to solve the aferomentioned issue, out of memory-.The following code works. BUT, when I scroll back to first image, that image shows blank or white, but when I delete the second image, then I could able to see first image. I could not able to figure out the root of the problem. I am using NetworkImageView.
RecyclerViewAdapter, I am calling setSelectedPic method to load the image.
#Override
public void onBindViewHolder(final ListViewHolder holder, int position) {
PostProductImageLIst item = mItems.get(position);
ImageUtil.setSelectedPic(holder.imgViewIcon, item.getPath());
}
ImageUtil Class
public static void setSelectedPic(CustomNetworkImageView view, String url) {
Context context = view.getContext();
ImageLoader imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
if (!TextUtils.isEmpty(url)) {
if (url.startsWith("http")) {
imageLoader.get(url, ImageLoader.getImageListener(view,
R.drawable.image, android.R.drawable
.ic_dialog_alert));
view.setImageUrl(url, imageLoader);
} else {
try {
int targetW = view.getWidth();
int targetH = view.getHeight();
Uri uri = Uri.parse(url);
InputStream is = context.getContentResolver().openInputStream(uri);
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(url, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
Bitmap bitmap = BitmapFactory.decodeStream(is);
Matrix matrix = new Matrix();
matrix.postRotate(getImageOrientation(url));
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, true);
view.setLocalImageBitmap(rotatedBitmap);
if (is!=null) {
is.close();
} catch (Exception ex) {
Log.e("Image", ex.getMessage(), ex);
}
}
} else {
view.setImageUrl("", CustomVolleyRequest.getInstance(view.getContext()).getImageLoader());
}
}
You should scale your Bitmap and use caching for reducing loading time. Here on this repository I've put reference code for approaching image loading with scaling and caching.
I report here code to be used for setPic method. This essentially uses an LruCache for improving Bitmap loading while scrolling. This could be a good starting point. Notice also that Bitmap are scaled before putting them in cache.
private static final int WIDTH = 100;
private LruCache<String, Bitmap> mMemoryCache;
public void setPic(MyImageView view, String url) {
Context context = view.getContext();
if (!TextUtils.isEmpty(url)) {
if (url.startsWith("http")) {
view.setImageUrl(url, VolleyHandler.getInstance(context).getImageLoader());
} else {
try {
Uri uri = Uri.parse(url);
Bitmap bitmap = mMemoryCache.get(url);
if (bitmap == null) {
InputStream is = context.getContentResolver().openInputStream(uri);
bitmap = BitmapFactory.decodeStream(is);
Bitmap scaled = ImageUtils.getInstance().scaleBitmap(bitmap);
mMemoryCache.put(url, scaled);
if (is!=null) {
is.close();
}
}
view.setLocalImageBitmap(bitmap);
} catch (Exception ex) {
Log.e("Image", ex.getMessage(), ex);
}
}
} else {
view.setImageUrl("", VolleyHandler.getInstance(view.getContext()).getImageLoader());
}
}
public Bitmap scaleBitmap(Bitmap bitmap) {
int width = WIDTH;
int height = (WIDTH * bitmap.getHeight()) / bitmap.getWidth();
return Bitmap.createScaledBitmap(bitmap, width, height, false);
}
I suggest also to refer to Android Developers documentation here (for efficient Bitmap loading) and here (for Bitmap caching with Volley).
I have tried almost everything mentioned anywhere but still i am unable to get the profile pic of the logged in user in my android app.
Following is the code which I am using :-
new AsyncTask<String, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(String... params) {
try {
URL url = new URL(params[0]);
return BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (Exception e) {
Log.d("ERROR", "Unable to get Image");
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if(saveFlag) {
saveImage(bitmap);
}
imageView.setImageBitmap(bitmap);
}
}.execute(url);
Url for the image is :- http://graph.facebook.com/{ID}/picture.
I am able to see the image when I go the url from browser.
I have tried both http and https.
Someone help.
Edit: I dont want to use any other api other than fb or normal android's.
you can use picasso and set image using picasso like this:
URL url = new URL(params[0]);
Picasso.with(context).load(url.toString()).into(imageView);
http://square.github.io/picasso/
OR
call the below method in async task and set the returned bitmap as image.
private Bitmap getImage(String imageUrl, int desiredWidth, int desiredHeight)
{
private Bitmap image = null;
int inSampleSize = 0;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = inSampleSize;
try
{
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
InputStream stream = connection.getInputStream();
image = BitmapFactory.decodeStream(stream, null, options);
int imageWidth = options.outWidth;
int imageHeight = options.outHeight;
if(imageWidth > desiredWidth || imageHeight > desiredHeight)
{
System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight);
inSampleSize = inSampleSize + 2;
getImage(imageUrl);
}
else
{
options.inJustDecodeBounds = false;
connection = (HttpURLConnection)url.openConnection();
stream = connection.getInputStream();
image = BitmapFactory.decodeStream(stream, null, options);
return image;
}
}
catch(Exception e)
{
Log.e("getImage", e.toString());
}
return image;
}
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'm new to android and I'm confused about how to deal with Bitmaps.
I want to download a Bitmap, it could be quite large, and save it to a temporary internal file. I'm then going to draw this Bitmap to a Canvas later.
My current method is to
1. Download the input stream
2. copy the stream
3. use one stream to work out bounds using bitmapFactory.options
4. use the other stream to decode the full bitmap with the sample size
However, I need landscape and portrait versions, so now I will have to do this twice and save two images.
Or - I have seen people use bm.compress(Bitmap.CompressFormat.JPEG, 50, bos); to save a file instead. This by-passes the decoding with sample size as its saved direct from a stream. I guess then I would use a matrix to scale when I draw to my Canvas.
Basically, I am confused as the best approach for this task , which method is less likely to run into out of memory and is the more commonly used approach?
Cheers
byte[] imagesByte = getLogoImage(Your url);
set to imageview...
imgView.setImageBitmap(BitmapFactory.decodeByteArray( imagesByte, 0, imagesByte.length));
Method for Download
public static byte[] getLogoImage(String url){
try {
URL imageUrl = new URL(url);
URLConnection ucon = imageUrl.openConnection();
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(500);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
return baf.toByteArray();
} catch (Exception e) {
Log.d("ImageManager", "Error: " + e.toString());
}
return null;
}
In Android you have to e aware of limited memory, so large images would't fit in memory and you will have OutOfMemory exceptions.
The key is, after saving te image in internal storage, load it at the display resolution:
First download te image, this should be done outside the UI thread, let _url an URL intance with the image addres and _file the String containing destination file :
URLConnection conn = _url.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
boolean success = false; //track succesful operation
if( _file != null)
{
try
{
FileOutputStream fos = new FileOutputStream(_file);
byte data[] = new byte[4086]; //use 4086 bytes buffer
int count = 0;
while ((count = is.read(data)) != -1)
{
fos.write(data, 0, count);//write de data
}
is.close();
fos.flush();
fos.close();
int len = conn.getContentLength();
File f = new File( _file);//check fie length is correct
if( len== f.length())
{
success = true;
}
else
{
//error downloading, delete de file
File tmp = new File( _file);
if( tmp.exists())
{
tmp.delete();
}
}
}catch (Exception e )
{
try
{
e.printStackTrace();
//delete file with errors
File tmp = new File( _file);
if( tmp.exists())
{
tmp.delete();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
finally
{
is.close();//cleanup
}
Then when you have to load the image at the desired resolution, here the key is use BitmapFactory to read bitmap info and get scaled bitmap:
public static Bitmap bitmapFromFile(int width, int height, String file)
{
Bitmap bitmap = null;
final BitmapFactory.Options options = new BitmapFactory.Options();
if( height >0 && width > 0 ) {
options.inJustDecodeBounds = true;//only read bitmap metadata
BitmapFactory.decodeFile(file,options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, width, height);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
}
try
{
bitmap = BitmapFactory.decodeFile(file, options);//decode scaled bitmap
}catch (Throwable t)
{
if( bitmap != null)
{
bitmap.recycle();//cleanup memory, very important!
}
return null;
}
return bitmap
}
The final step is to calculate the scale factor:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height;
final int halfWidth = width;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((couldShrink(halfWidth, reqWidth, inSampleSize)&&
couldShrink(halfHeight,reqHeight, inSampleSize))
//&&(halfHeight*halfWidth)/inSampleSize > maxsize)
)
{
inSampleSize *= 2;
}
}
return inSampleSize;
}
private static boolean couldShrink ( int dimension, int req_dimension, int divider)
{
int actual = dimension / divider;
int next = dimension / (divider*2);
int next_error = Math.abs(next - req_dimension);
int actual_error = Math.abs(actual-req_dimension);
return next > req_dimension ||
(actual > req_dimension && (next_error < actual_error) )
;
}
That is if you want to do it by hand, I recommend you to use Picasso that will handle donwloading, disk caching and memory caching of your image:
To load into a ImageView called image showing a backgroud (R.drawable.img_bg) while downloading :
Picasso.with(image.getContext())
.load(url).placeholder(R.drawable.img_bg).fit()
.into(image, new Callback.EmptyCallback()
{
#Override
public void onSuccess()
{
holder.progress.setVisibility(View.GONE); //hide progress bar
}
#Override
public void onError()
{
holder.progress.setVisibility(View.GONE); //hide progress bar
//do whatever you design to show error
}
});
to handle yourself a bitmap:
//first declare a target
_target = new Target()
{
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from)
{
//handle your bitmap (store it and use it on you canvas
}
#Override
public void onBitmapFailed(Drawable errorDrawable)
{
//handle your fail state
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable)
{//for example for drawing a placeholder while downloading
}
};
Now you just have to load and resize your image:
Picasso.with(context).load(url).resize(192, 192).centerCrop().into(_target);
Hope that helps.