I had to work on a bitmap intensive app last year and ran into all these 
problems. First of all, you are right. You can allocate almost whatever 
native heap you want. On our test devices it was almost up to a GB for 
example.

No matter what Google says, by my own and obviously your observation 
bitmaps behave differently though. I was curious and just looked up the 
source code for the native pixel data allocation. It looks like a method 
called 
GraphicsJNI::allocateJavaPixelRef<http://source-android.frandroid.com/frameworks/base/core/jni/android/graphics/Graphics.cpp>is
 to blame for that. Allocation is not really completely done in native 
heap, but Java memory is being requested via the JNI method NewByteArray. 
As far as I know that allocated array resides on the native heap until it 
is released and copied back to Java. That probably only happens when you 
alter the pixel data from Java. Which means that the get and setPixel 
methods must be really slow because in worst case they can cause heavy copy 
operations between JVM and native code for each access.

In any case, allocation of bitmaps does depend on the available Java heap 
space, even though that space is not necessarily claimed when your Java 
code does not access the raw pixel data.

The only other option that comes to my mind for speeding up things would be 
writing some NDK code and using a PNG library for encoding the pixel data 
in native code. Passing that int array to that native code is 
straightforward. With a trick you can even access the original Java int 
array directly without waiting for a copy. This is possible with the JNI 
function 
GetPrimitiveArrayCritical<http://docs.oracle.com/javase/1.4.2/docs/guide/jni/jni-12.html#GetPrimitiveArrayCritical>.
 
There is no guarantee, though that direct access works in any case. The 
documentation of that function explains the limits pretty well.

On Monday, July 9, 2012 10:26:57 AM UTC-5, Latimerius wrote:
>
> On Mon, Jul 9, 2012 at 4:53 PM, Nobu Games <[email protected]> 
> wrote: 
> > Bitmap behaves like that because it allocates memory on the native heap 
> for 
> > storing its bitmap data, meaning: it cannot use your Java int array and 
> must 
> > make a copy instead. 
>
> One thing though that puzzles me about this is, there have been 
> discussions indicating that the native Bitmap memory doesn't count 
> towards an application's heap limit (I think someone from Google 
> mentioned it too at last year's I/O?).  However, I'm still getting 
> OOM, and I'm pretty sure it my app's heap limit and not the lack of 
> RAM in the device that I'm having trouble with (the device is HTC 
> Desire with pretty much nothing else running on it so there should be 
> plenty of RAM available to the OS). 
>
> I wouldn't mind the copy if it didn't contribute to my app's heap size... 
>
> > For getting around that problem you should reconsider 
> > what you are doing. Try to break your big (memory) problem into several 
> > smaller sub-problems. 
>
> I tried to approach it like that but the ultimate goal is a .png 
> stored on internal/external storage.  It's mainly the 
> encoding-into-PNG step that I don't know how to handle in a piecemeal 
> fashion.  I'm no PNG expert but I think that in order to produce a 
> .png file, all image data that are supposed to go into it need to be 
> in-core at the same time. 
>
> > I don't know where your pixel int array originally 
> > comes from, but at some point you must have it either loaded from 
> somewhere 
> > or constructed. 
>
> It's read in from a GL ES off-screen rendering surface. 
>
> > You could instead operate directly on an already allocated Bitmap object 
> and 
> > modify its pixel data instead of having you int array as a step in 
> between. 
>
> That's the only way I see at this point to achieve the goal at all - 
> I'd *love* to avoid this though as we're discussing image resolutions 
> like 2400x1440 here - filling each of those pixels by calling 
> setPixel() on it is going to take forever (and that adds to the fact 
> that off-screen rendering in ES 1.1 doesn't seem to be fast by 
> itself). 
>
> That's why I wanted an int[], so that I can do bulk blits. 
>
> > So if you are loading your int array from a file for example, just apply 
> > that data directly to the Bitmap. 
>
> As an ugly work-around, I considered taking my int[], writing it out 
> to a file and releasing its memory.  Then use one of the 
> decodeBitmap() functions to turn the file into a Bitmap.  Not sure 
> though if decodeBitmap() handles "raw" pixel data, or if it insists on 
> a PNG, JPEG or similar. 
>
> Thanks for your reply! 
>

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to