second HttpURLConnection for image loading optimization - android

I have read that HttpUrlConnection sends GET request when connection is made. Also then I can retrieve an instance of InputStream to read that resource. Does this mean that whole resource file is downloaded as the connection is made?
What I want to achieve is to set an ImageView image to remote image from the web. However my idea is to do this in memory-friendly way and calculate inSampleSize for BitmapFactory. In order to calculate that size - I need view dimensions and remote image dimensions. Remote image dimensions may be retrieved this vay (basically it should not load an image into memory):
BitmapFactory.Options options = new BitmapFactory.Options ();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream (inputStream, null, options);
However once read inputStream can not be reused in this case (or can it?). Also HttpUrlConnection returns the same instance of InputStream which means that if I want to read an image again (and load only the size I need using inSampleSize option) - I have to re-connect.
I want to be able to load large images, however as I have heard - HTTP requests are slow so is it worth it to send a second request? Also I don't know if the whole image is downloaded anyway even if I am reading only image info for the first time and not loading the whole thing.
If it is not worth it I think the only way will be to copy whole image into memory, get it's dimensions, read only the size I need and finally clean up the memory. Witch would be pretty memory expensive for the short period of time.

For loading images from remote web use Android Smart Image View..
it Load Images from URLs in memory friendly way
http://loopj.com/android-smart-image-view/

Related

Android - does setting bitmap request Options.inJustDecodeBounds to true reduce request time?

I am coding an app where I am going to acquire bitmaps from URLs using inputstreams. Before they have been loaded, however, I require a placeholder. My current plan is to first get the bounds of the bitmap (using Options and inJustDecodeBounds) and use this to set the placeholder aspect ratio and size.
However, if it takes the same amount of time to do this kind of request as it takes to simply request the actual bitmap, then I may as well simply request the actual bitmap.
So does setting inJustDecodeBounds to true in an instance of BitmapFactory.Options reduce the time taken for the request?
The using of inJustDecodeBounds reduce the required amount of memory to get only the bitmap information.
It's not a question about speed.

Given a full path of an image file, how to get its thumbnail?

It seems the answers I searched online (including stackoverflow.com) get the image file id through gallery selection.
I have created my own file explorer.
Then how to do that?
I can create my own small size image; but I think it would be faster if we can make use of an exisiting thumbnail; and if it does not exist, I would prefer to create a thumbnail that is saved for later use.
[Update:]
OK, thanks for advice. So I will not create a thumbnail in the device, to avoid to use too much space.
Then is is better to do two steps:
Step 1: look for an exisiting thumbnail for the image file if it exists.
Step 2: if no thumbnail exists, then create my own small size bitmap (not save the it).
Then how to do Step 1, if I do not use the Gallery intent?
[Update 2:]
I also want to get the thumbnail of a video file.
I can use MediaMetadataRetriever to get a frame at any point of time, and rescale the image to a thumbnail. But I find it is very slow: I have 4 video files in the folder, and I can sense the delay.
So I think the better way to retrieve an existing thumbnail.
If I only know the file path and file name, how can I get it?
I think this question is the same as my original one, just it has more sense to do so.
You shouldn't be using specific files for tumbnail, especially not creating tumbnails. What if the user has a lot of images and you store a tumbnail of each picture which gets viewed in your explorer. That would generated a whole lot of duplicated and unwanted data. The calculations from resizing the images each time overweighs the amount of data that would need to be stored.
I would suggest you have a default icon on images in the explorer and then resizing the images in a diffrent thread, replacing your default tumbnail as they are resized.
You could downsize the existing images on the fly:
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image_path, opts);
int width = opts.outWidth;
int height = opts.outHeight;
then
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
opts.inDither = true;
opts.inJustDecodeBounds = false;
opts.inSampleSize = (int)Math.pow(2.0,Math.floor(Math.log(scale_factor)/Math.log(2)));//for example double scale_factor=(double)width/desired_dimension;
and finally:
Bitmap bm = BitmapFactory.decodeFile(image_path,opts);
You could load in a separate thread ranges of existing files and update only those ones when needed.
You can use ThumbnailUtils. Look up the this utility method. Probably fits your need without much hassles. Creating duplicate downsized images is a bad design as that it will end up unnecessary data.
Bitmap resizedImage = ThumbnailUtils.extractThumbnail(rescaledImage, imagePixel, imagePixel);

How to speed up loading images as small previews?

I have 3 or 4 image paths that I use to load an image so I set it to an imageview. Why does it take long? Or better asking is there a way to make it faster? At the end of the day I am loading to fit an imageview of less than 60 dp hight and width
Uri mainImgeUri = Uri.parse(imagePath);
InputStream imageStream;
try {
imageStream = mActiviy.getContentResolver().openInputStream(mainImgeUri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream, null, options);
mainImageIV.setImageBitmap(yourSelectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
USE CASE:
What happens is that a user will add 5 images (and he get to choose them from Gallery which is mostly taken by phone camera). He hit save and my app stores the path to them in an sqlite database. Then when the user opens the app again to see them, my app query the db to get the paths to all the images and executes the code above x number of times so all the image views are loaded with the intended images
Take a look at http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
It explains how to calculate the correct inSampleSize based on the required dimensions of the output image. It also explains how to reference large bitmaps without having to load all their pixel data into memory.
The idea is that you resample bigger images and only load the smaller ones into memory making the whole process much more efficient. The example code is accessing a bitmap from resources, but this can easily be modified for your needs.
The important things to look out for in the example are inJustDecodeBounds and calculateInSampleSize.

Android: load only detail of large image

I'm working on a project that needs to use a large image as a map. The image is about 95MB and has a resolution of 12100 x 8000 pixels.
I don't need the whole image at once, I just need a detail of 1000 x 1000 Pixel (it's not always the same detail, just grabbing the same part is not a solution I can use). So I can't just sample it down with the BitmapOptions.
I looked around and found the idea to create a FileInputStream (the image is on the SD-Card) and then I can just load the detail with decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts). That way I wouldn't load the whole thing into the memory. I tried it, but it's just crashing when I try to load the image. Here's my code:
FileInputStream stream = null;
try {
stream = new FileInputStream(path);
} catch(Exception e) {
Log.e("inputstream",e.toString());
}
Rect rect = new Rect(a,b,c,d);
return BitmapFactory.decodeStream(stream, rect, null);
When I try to load the image, the activity closes and LogCat tells me java.lang.outOfMemoryError. Why does it crash? I thought with the stream it should work on the image "on-the-fly", but the only explication I have for the Error is the it trys to load the hole image into the memory. Does anybody have an idea how I can load the detail out of the image, or why this idea doesn't work?
It crashed because all these 95M are sucked into memory for processing. This call will not ignore parts of the stream - it will put the whole thing to memory and then try to manipulate it. The only solution you can have is to have some sort of server side code that does the same sort of manipulation or if you don't want to do it on server - provide thumbnails of your large image. And I would strongly advise against pulling whole 95M at any time anyways
Does BitmapRegionDecoder not help (I realise its level 10)?

android how to load/save original size Bitmap with no OutOfMemory

I read many discussions about the inSampleSize OutOfMemory dilemma.
Cannot get a good solution so i ask a question about it.
Im currently loading a bitmap with inSampleSize=4.
That will give me a Bitmap with the size 648x388.
Original On disk size is 2592x1592.
Im writing text on 648x388 bitmap and saving it back to disk.
Im writing on the 648x388 because the 2592x1592 give me OutOfMemory .
The way it works is that there can be 1-10 648x388 Bitmaps to be saved in a while loop.
I want to change this loop to save 1-10 2592x1592 Bitmaps.
How can i securely load the 2592x1592?
I don care about the resolution going down 60% or more.
As long as the Bitmap has the same size 2592x1592.
Is there a way to maybe keep the size but make Bitmap thinner,
removing color without making quality bad.
My first thought was going something like this to get the biggest bitmap i could get:
I have not tested this but get a feeling it's a bad way
boolean work = true;
int insample = 2;
BitmapFactory.Options options = new BitmapFactory.Options();
while(work){
try{
options.inSampleSize = insample;
bitmap = BitmapFactory.decodeFile(filePath,options);
work = false;
}catch(Exception e){
insample++;
}
}
any help would be grate.
Image processing requires a lot of memory. you cant use the whole bitmap and just modify it on your phone. use a web service for that. upload, process, download. sorry there is no other way a decoded bitmap just takes a lot of memory.
And by the way you cant catch an outOFMemory Exception. the app just crashes.
There's a hard limit on process size in Android and a 4 mega-pixel image at four bytes a pixel will hit it all by itself (on many devices), without any room for your program.
I think you are going to need to do one of two things: Create a web service to do the image processing on a server/in the cloud; or learn to do your image processing "on-the-fly" by manipulating the data directly instead of using a bitmap.

Categories

Resources