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?

Tim Stone
  • 19,119
  • 6
  • 56
  • 66
OffCS
  • 441
  • 3
  • 15
  • 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? – Matt Jan 28 '11 at 16:39
  • 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. – Seva Alekseyev Jan 28 '11 at 20:31
  • 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. – OffCS Jan 29 '11 at 03:30
  • 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? – Dmitriy Tarasov Jan 29 '11 at 15:20
  • possible duplicate of [How to load tiles from a large bitmap in Android?](http://stackoverflow.com/questions/4753013/how-to-load-tiles-from-a-large-bitmap-in-android) – Mark Ingram Feb 23 '11 at 09:55

3 Answers3

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 :)

jakebasile
  • 8,084
  • 3
  • 28
  • 34
Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • 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? – jakebasile Apr 11 '11 at 17:20
  • 3
    You could grab the code from the git repository and use it in your app :) – Romain Guy Apr 22 '11 at 07:35
  • @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? – snapfractalpop Apr 02 '12 at 15:15
  • @RomainGuy, nevermind.. I have added it as [a stand-alone question](http://stackoverflow.com/q/10035169/882146) because I think the general idea could be useful for many other cases. – snapfractalpop Apr 05 '12 at 20:04
  • 3
    I cooked up [an example](https://github.com/johnnylambada/WorldMap) 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. – JohnnyLambada Apr 10 '12 at 17:31
  • what if i need to use a matrix when decoding a region? should i use mapRect on the rect ? – android developer Jul 24 '13 at 13:42
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.

crazyscot
  • 11,819
  • 2
  • 39
  • 40
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.

Community
  • 1
  • 1
mpenkov
  • 21,621
  • 10
  • 84
  • 126