Get scaled Image from URL - android

I am using the following method to get an image from a given URL.
protected Bitmap doInBackground(String... urls) {
String urlDisplay = urls[0];
Bitmap scaledImage = null;
try {
InputStream in = new java.net.URL(urlDisplay).openStream();
scaledImage = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in), 380, 250, false);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return scaledImage;
}
Is there anyway to get a scaled image without having to download the full sized image first? It would greatly increase load times.

Sadly, server side manipulations can't be done and before downloading, there's no way to scale it. However, if you still want to save the load time on consecutive refreshes, then you probably can go ahead with saving the bitmap received in a shared preference. This way if the image is already stored in the shared preference, you don't need to download it again and apply scaling to it.
CAUTION: In case the image you are downloading is changing after a while, you can put a check to download it after every "n" (say 7) days and replace the existing stored image with this one.
NOTE: Though there are many answers already available which tells you how to store the image bitmap in Shared Preference / local storage, let me know in case you need that info/ code-snippet too.

You can not perform bitmap operations on a remote image without downloading it first. Therefore there is no way to do what you want to do unless the server you are getting the image from supports different image sizes or a parameter to resize it on the server side.

Related

Android select an image from the gallery and resize it before I pull it in

I'm running into issues with the images in my gallery being much much larger than I need them to be.
I've looked for ways to reduce their size before I actually pull them in, but I'm just not quite putting it together as most of what I'm finding deals with BitMap resources and not a BitMap that already exists in the gallery.
So, basically, I am getting the image like so,
imageBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
But before I actually assign it to my BitMap var over there I need to scale it down to a reasonable size for a phone.
Any help with understanding what is going on here better is appreciated.
getBitmap() is a weak convenience method. Its body is a whopping four lines of code:
public static final Bitmap getBitmap(ContentResolver cr, Uri url)
throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
Bitmap bitmap = BitmapFactory.decodeStream(input);
input.close();
return bitmap;
}
This is why I don't bother teaching people about it.
IMHO, the best solution is for you to use one of the many image-loading libraries available for Android, such as Picasso. Most of the good ones can load from a Uri and handle your resizing as part of the operation, doing the heavy lifting on a background thread.
If, for whatever reason, you want to do all that work yourself, call BitmapFactory.decodeStream() with a BitmapFactory.Options object. In particular, set inSampleSize to indicate that you want the image to be resampled as part of reading it, so you wind up with a smaller Bitmap taking up less heap space.

How to load thumbnails of Pic Clicked via Camera Intent

My application takes pictures via camera intent. How should I display their small size version in a grid view for viewing purpose. Should I create their thumbnails and store them in cache or external storage Or should I use the thumbnails created by Default Gallery application. My pictures are stored in external storage so I am expecting that Default Gallery Application would make their thumbnails automatically. If yes, then how should I map each image with the thumbnail created by Default Gallery Application.
Well, I have found that Async class could handle the memory usage scenario.
The relevant link is: http://developer.android.com/intl/es/reference/android/os/AsyncTask.html
Well, I have got an answer
public Bitmap getbitpam(String path) {
Bitmap imgthumBitmap = null;
try {
final int THUMBNAIL_SIZE =300 ;
FileInputStream fis = new FileInputStream(path);
imgthumBitmap = BitmapFactory.decodeStream(fis);
imgthumBitmap = Bitmap.createScaledBitmap(imgthumBitmap,
THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
ByteArrayOutputStream bytearroutstream = new ByteArrayOutputStream();
imgthumBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytearroutstream);
} catch (Exception ex) {
}
return imgthumBitmap;
}
However, this is taking a lot of RAM. I Have also found a strange behavior. That as I am scrolling in grid view, it is taking more RAM. The growth in memory used is cumulative and finally the app is crashing due to Memory_Low exception. Any workaround for it??
Got answer for second problem too:-- Async class.

save and laod image using universal image loader

Updated
So as suggested earlier, i used Universal image loader. But i am getting some error.
**This is the first time i am playing around with this kind of stuff.
Below are my codes :
Here is the code to save bitmap to internal storage using async:
Uri uri = Crop.getOutput(result);
try {
bmp = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
finally {
new saveDpToDisk().execute(bmp);
}
class saveDpToDisk extends AsyncTask{
#Override
protected Object doInBackground(Object[] params) {
try {
fos = openFileOutput("ProPic", Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
bmp.compress(Bitmap.CompressFormat.JPEG, 60, fos);
return bmp;
}
}
and here is code to load image from storage using UIL:
#Override
protected Object doInBackground(Object[] params) {
FileInputStream fis;
try {
fis = openFileInput("ProPic");
String uri = String.valueOf(fis);
DisplayImageOptions options = new DisplayImageOptions.Builder().cacheOnDisk(true).build();
ImageLoader loader = ImageLoader.getInstance();
loader.displayImage(uri, pro_pic, options);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return pro_pic;
}
}
And this is the error I am getting (app doesnt force close, error just appears in logcat
UIL doesn't support scheme(protocol) by default [java.io.FileInputStream#42987180]. You should implement this support yourself (BaseImageDownloader.getStreamFromOtherSource(...))
java.lang.UnsupportedOperationException: UIL doesn't support scheme(protocol) by default [java.io.FileInputStream#42987180]. You should implement this support yourself (BaseImageDownloader.getStreamFromOtherSource(...))
at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStreamFromOtherSource(BaseImageDownloader.java:235)
at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStream(BaseImageDownloader.java:97)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.downloadImage(LoadAndDisplayImageTask.java:290)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryCacheImageOnDisk(LoadAndDisplayImageTask.java:273)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:229)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:135)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
________x_____________________x___________________________x_______________________
Original Question
My app has to load only one image (which user can select from gallery to set as his dp for that app).
So, What I did is I saved the selected pic to storage using FileOutputStream and then load the pic using FileInputStream in activity's onResume method.
But, what happens is that when the selected pic is too large, the app starts up too slowly (takes time to inflate view) and logcat shows memory heap of 30-60 MB.
So, i thought of storing the image in cache and load but dont exactly find a way to do so.
Shall i use picasso? If yes, how to use it for saving and laoding from cache.
Or are there any other ways to achieve what i need?
If you read this post on G+ by Koush you will get clear solutions for your confusions, I have put the summery of that, in that Android-Universal-Image-Loader is the winner for your requirement!
Picasso has the nicest image API if you are using network!
UrlImageViewHelper + AndroidAsync is the fastest. Playing with these
other two great libraries have really highlighted that the image API
is quite dated, however.
Volley is slick; I really enjoy their pluggable backend transports,
and may end up dropping AndroidAsync in there. The request priority
and cancellation management is great(if you are using network)
Android-Universal-Image-Loader is the most popular one out there
currently. Highly customizable.
This project aims to provide a reusable instrument for asynchronous
image loading, caching and displaying. It is originally based on Fedor
Vlasov's project and has been vastly refactored and improved since
then.
Considering all this Android-Universal-Image-Loader suites your requirement (Loading the images are on disk locally)!

Setting up remote bitmap faster in UI(ImageView)

I am writing an app that is essentially a flipcard that shows word/hint on one side and picture on other side relevant to it.I am using viewflipper for the two views.Problem is that the picture loads from internet.App access the db,extracts url and then loads picture.That means the change in view takes as much time as it takes to download the picture.I want to flip card immediately and load picture so that user do not thinks that app is slow.Rather they should know that picture is being loaded,hence the delay.Pls suggest improvement in code.My code for loading picture in flipcard is:
public void setBMP(String s) //String passed is url extracted from column of db uing
{ //internal db
try{
//String url1 = "c.getString(3)";
String url1= s;
System.out.println(url1);
URL ulrn = new URL(url1);
HttpURLConnection con = (HttpURLConnection)ulrn.openConnection();
InputStream is = con.getInputStream();
Bitmap bmp = BitmapFactory.decodeStream(is);
if (null != bmp)
{
im.setImageBitmap(bmp);
}
else
System.out.println("The Bitmap is NULL");
}catch(Exception e){}
}
}
For changing view, i have set up actionListener.As soon as user touches screen card flips and image loads.
Also is it possible to preload the images in background while user is viewing some other card.Or is it possible to cache the cards viewed?
I would go the asnyctask route, because that way you can load/disable spinners (or wahtever loading animations) as well. Check out this answer for a really simple example. If you want to add spinners you need to start them in the onPreExecute() of the asnyctask (just add it to the example) and disable them in onPostExecute after you image is downloaded.
Using AsyncTask to load Images in ListView
it seems to me that creating a Runnable that gets the bmp and saves it to a hash map file and then, when it's needed if downloaded, it opens the file, and if not it downloads it from the web.
try looking at fedorvlasov's Lazy adapter for reference.
you can use his Image loader

how to load internet images in gridview efficiently?

I am using following example to display internet images in my activity.
http://developer.android.com/resources/tutorials/views/hello-gridview.html
In custom image adapter I'm directly loading images from internet and assigning it to imageview.
Which shows images in gridview and every thing works fine but it is not efficient way.
When ever i scroll gridview it again and again loads images and thats why gridview scrolls very slow
Is there caching or some useful technique available to make it faster?
Create a global and static method which returns a Bitmap. This method will take parameters: context,imageUrl, and imageName.
in the method:
check if the file already exists in the cache. if it does, return the bitmap
if(new File(context.getCacheDir(), imageName).exists())
return BitmapFactory.decodeFile(new File(context.getCacheDir(), imageName).getPath());
otherwise you must load the image from the web, and save it to the cache:
image = BitmapFactory.decodeStream(HttpClient.fetchInputStream(imageUrl));
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File(context.getCacheDir(), imageName));
}
//this should never happen
catch(FileNotFoundException e) {
if(Constants.LOGGING)
Log.e(TAG, e.toString(), e);
}
//if the file couldn't be saved
if(!image.compress(Bitmap.CompressFormat.JPEG, 100, fos)) {
Log.e(TAG, "The image could not be saved: " + imageName + " - " + imageUrl);
image = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_cached_image);
}
fos.flush();
fos.close();
return image;
preload a Vector<SoftReference<Bitmap>> object with all of the bitmaps using the method above in an AsyncTask class, and also another List holding a Map of imageUrls and imageNames(for later access when you need to reload an image), then set your GridView adapter.
i recommend using an array of SoftReferences to reduce the amount of memory used. if you have a huge array of bitmaps you're likely to run into memory problems.
so in your getView method, you may have something like(where icons is a Vector holding type SoftReference<Bitmap>:
myImageView.setImageBitmap(icons.get(position).get());
you would need to do a check:
if(icons.get(position).get() == null) {
myImageView.setImageBitmap(defaultBitmap);
new ReloadImageTask(context).execute(position);
}
in the ReloadImageTask AsyncTask class, simply call the global method created from above with the correct params, then notifyDataSetChanged in onPostExecute
some additional work may need to be done to ensure you don't start this AsyncTask when it is already running for a particular item
You will need to implement the caching yourself. Create a proxy class that will download the images. In the getView ask this class to download an image by passing a url. In the proxy class create a HashMap that will map a url to a Bitmap. If the key for the passed url doesn't exist, download the image and store it. Otherwise returned the stored bitmap converted to an imageView.
Of course you can't afford to store as many images as you like. You need to set a limit, for example 10 images, based on the image size you expect to have. When the limit is exceeded, you need to discard old images in the favor of new ones.
You could try DroidFu. My app uses the ImageCache. There's also some manner of web-based imageview or something of the sort in the library. See in particular WebImageView and WebGalleryAdapter: http://mttkay.github.com/droid-fu/index-all.html
Edited to add: The droid-fu project is deprecated in favor of Ignition. https://github.com/mttkay/ignition

Categories

Resources