0

By following this link, I have written the following code to show a large image bitmap from sdcard.

try { InputStream lStreamToImage = context.getContentResolver().openInputStream(Uri.parse(imagePath)); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(lStreamToImage, null, options); options.inSampleSize = 8; //Decrease the size of decoded image options.inPreferredConfig = Bitmap.Config.ARGB_4444; options.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeStream(lStreamToImage, null, options); } catch(Exception e){} image.setImageBitmap(bitmap); 

But it is not returning the bitmap(I mean it returns null). In logcat it is showing the below message repeatedly

08-02 17:21:04.389: D/skia(19359): --- SkImageDecoder::Factory returned null 

If I will comment the options.inJustDecodeBounds line and rerun it, it works fine but slowly. The developer guide link I provided above says to use inJustDecodeBounds to load bitmaps efficiently.

Please tell me where I am doing wrong.

1 Answer 1

2

inJustDecodeBounds does not load bitmaps. That's the point of it. It loads the dimensions of the bitmap without loading the actual bitmap so you can do any pre-processing or checking on the bitmap before you actually load it. This is helpful is you, say, were having memory issues and you needed to check if loading a bitmap would crash you program.

The reason your bitmap might be loading slowly is because it's probably very large and SD cards are very slow.

EDIT:

From the documentation:

If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.

Edit 2:

Looking at your code with the example provided by Google, it looks like you are doing relatively the same thing. The reason it's returning null is possibly your InputStream has been modified in the first decoding and thus not starting at the beginning of the bitmap's memory address (they use a resource ID rather than InputStream.

From the code you supplied here, here's what I've figured. You are ALWAYS setting a sample size to 8 regardless of what the first decoding gives you. The reason Google decodes the first time is to figure out what the actual size of the bitmap is versus what they want. They determine that the bitmap is ZxZ dimensions and they want YxY dimensions, so they calculate the samplesize that they should use from the second decoding. You are not doing this. You are simply retrieving the dimensions of the bitmap and not using them. THEN, you set the sample size to a hard-coded 8, swapping it to a hard-coded ARGB_4444 bitmap, then decoding the full bitmap in to memory. In other words, these three lines are not being used:

BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(lStreamToImage, null, options); 

Setting inJustDecodeBounds merely gives you the bitmap's dimensions without putting the bitmap in to memory. It doesn't make it more efficient. It's meant to allow you to load bitmaps in a smaller memory space if they are too big because you can pre-decide what size it should be without decoding the whole thing).

The reason decoding the bitmap is slow might merely be a CPU thing. Depending on the size of your bitmap, you're loading the bitmap from an InputStream from the SDcard which is a slow operation in itself.

Sign up to request clarification or add additional context in comments.

5 Comments

dear DeeV the documentation says if that set to true, it will return null but it will preprocess it. But if you want to get the preprocessed bitmap, then set it to false and reget it. What I have done in above. Please see the documentation link given above, which also does the same thing.
I think they mispoke when they said "process it". It "Processes" the image in the sense that it will give you the size of the image without fully decoding it. Side note, I also seem to recall a question about a month ago where someone was trying to re-use the same Options object and it kept crashing on him. In the end, he had to create a new one.
Did this ever work? I'm looking at your code again and trying to figure out what went wrong. I see nothing with the provided segment other than re-using the BitmapFactory.Options object (which causes problems for some reason).
Please provide a solution for this. Actually it always returns null. What should I need to change in the above code.
See my edit. I'm thinking it's returning null because the InputStream is being modified.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.