Is it possible to chop a bitmap to small pieces without loading the entire thing into memory?
Asked Answered
I

3

19

I'm working on an image processing application for Android that recognizes music notation from pictures taken of music sheets.

I tried to load the entire image into a Bitmap using the BitmapFactory.decodeFile(imgPath) method, but because my phone doesn't have enough memory I get a "VM heap size" error. To work around this, I'd like to chop the full image into smaller pieces, but I'm not sure how to do that.

I also saw that it was possible to reduce the memory size of the Bitmap by using the inSampleSize property of the BitmapFactory.Option class, but if I do that I won't get the high resolution image I need for the music notation recognition process.

Is there anyway to handle this without going to NDK?

Interfertile answered 27/1, 2011 at 10:29 Comment(5)
Is your file really encoded as a bitmap? Can you just compress the source image so it's not as big? For just music, you shouldn't need many colors... How big in bytes and resolution are the images you're working with?Raeraeann
Is the bitmap yours or user's? If yours, consider storing it pre-chopped up, and/or in less colors. If user's, is this a borderline case or typical input? If borderline, implement validation/graceful error handling. If typical, reconsider your choice of platform.Gink
The bitmap is from user. He will take the picture from mobile camera. I have to use the biggest bitmap as possible because in recognition process the effectiveness is from this. Thank you for editing and sorry for my poor English.Interfertile
I try to resolve this problem too. But i'm want to recognize printed text from image. I've been doing this for two weeks but nothing has been able to find. Is it possible with NDK?Leukemia
possible duplicate of How to load tiles from a large bitmap in Android?Baddie
F
30

Android 2.3.3 has a new API called android.graphics.BitmapRegionDecoder that lets you do exactly what you want.

You would for instance do the following:

BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(myStream, false);
Bitmap region = decoder.decodeRegion(new Rect(10, 10, 50, 50), null);

Easy :)

Flophouse answered 4/2, 2011 at 22:8 Comment(6)
This class is in 2.3.3, and this is fine if you are OK with your app only working on 2.3.3 and above, but what about previous versions?Bony
You could grab the code from the git repository and use it in your app :)Flophouse
@RomainGuy, could you elaborate a little on how to do that? It seems the code references native methods.. do we also need to grab those native methods from git, and compile with NDK, or is the java class sufficient on it's own?Barm
@RomainGuy, nevermind.. I have added it as a stand-alone question because I think the general idea could be useful for many other cases.Barm
I cooked up an example of how to use the BitmapRegionDecoder API. The example has a large (6000,4000) image of the world that the user can scroll around in full resolution.Voidance
what if i need to use a matrix when decoding a region? should i use mapRect on the rect ?Slim
P
1

If it's from a camera the image will likely be jpeg format. You could use an external jpeg library - either in java or via the NDK, whatever you can find - to give you better control and load it a piece at a time. If you need it as an android.graphics.Bitmap then I suspect you will then need to re-encode the subimage as PNG or JPEG and pass it to BitmapFactory.decodeByteArray(). (If memory is a concern then do be sure to forget your references to the pieces of the bitmap promptly so that the garbage collector can run effectively.)

The same technique will also work if the input graphic is PNG format, or just about anything else provided you can find suitable decode code for it.

I think that by loading the image piecewise you are setting yourself an algorithmic challenge in deciding what parts of it you are really interested in the full detail of. I notice that BitmapFactory.Options includes the option to subsample, that might be useful if you want to analyse an overview of the image to decide what regions to load in full detail.

Plumbaginaceous answered 29/1, 2011 at 14:50 Comment(0)
B
1

If you're dealing with JPEG images, see my answer to this question as well as this example.

I don't know how possible it is to get libijg on Android, but if it is, then it's worth a shot.

Bills answered 30/1, 2011 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.