[android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Nobu Games
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. 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 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.

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. So if you are loading your int array from a file for example, just 
apply that data directly to the Bitmap. If that array is constructed by 
your code, then change the algorithm to store its calculations directly in 
the Bitmap object.

But maybe you do not need a Bitmap object at all. If you want to draw on a 
Canvas object, then you could make use of the following method instead, 
which takes a Java int array as argument:

canvas.drawBitmap (int[] colors, int offset, int stride, float x, float y, 
int width, int height, boolean hasAlpha, Paint 
paint)http://developer.android.com/reference/android/graphics/Canvas.html#drawBitmap%28int[],%20int,%20int,%20float,%20float,%20int,%20int,%20boolean,%20android.graphics.Paint%29

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

Re: [android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Latimerius
On Mon, Jul 9, 2012 at 4:53 PM, Nobu Games dev.nobu.ga...@gmail.com 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 android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en


Re: [android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Nobu Games
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::allocateJavaPixelRefhttp://source-android.frandroid.com/frameworks/base/core/jni/android/graphics/Graphics.cppis
 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 
GetPrimitiveArrayCriticalhttp://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 dev.nobu.ga...@gmail.com 
 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 android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Re: [android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Romain Guy
Bitmap allocations always count towards your heap limit. Until Android 3.0,
Bitmaps were allocated on the native heap but counted against your maximum
Dalvik heap. Starting with Android 3.0, Bitmaps are allocated directly on
the native heap.


On Mon, Jul 9, 2012 at 8:26 AM, Latimerius l4t1m3r...@googlemail.comwrote:

 On Mon, Jul 9, 2012 at 4:53 PM, Nobu Games dev.nobu.ga...@gmail.com
 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 android-developers@googlegroups.com
 To unsubscribe from this group, send email to
 android-developers+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/android-developers?hl=en




-- 
Romain Guy
Android framework engineer
romain...@android.com

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

Re: [android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Latimerius
On Mon, Jul 9, 2012 at 6:17 PM, Romain Guy romain...@android.com wrote:
 Bitmap allocations always count towards your heap limit. Until Android 3.0,
 Bitmaps were allocated on the native heap but counted against your maximum
 Dalvik heap. Starting with Android 3.0, Bitmaps are allocated directly on
 the native heap.

Cool, so now we now why I'm running OOM.  However, what are the best
practices handling Bitmap data that don't fit into memory twice?

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


Re: [android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Latimerius
On Mon, Jul 9, 2012 at 6:16 PM, Nobu Games dev.nobu.ga...@gmail.com wrote:
 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.

I tried in the meantime to fill my large Bitmap by calling setPixel()
on each of its pixels and the running time is in the order of tens
seconds.

 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. There is no guarantee, though that direct access
 works in any case. The documentation of that function explains the limits
 pretty well.

I don't use NDK in this app, was meant to be pure Java, however as
there are other (performance) problems with bulk GL data handling that
apparently cannot be solved without native code, I might consider NDK
as well.

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


[android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread RichardC
A quick search turns up quite a few Java PNG encoders with various license 
conditions.

Encoding a PNG will not require copying the PNG again so grab one with 
source, a license you like, and if necessary modify it to write directly to 
an output stream.

On Monday, July 9, 2012 3:31:24 PM UTC+1, Latimerius wrote:

 Hello, 

 I have a bunch of pixel data in an int[] that I want to turn into a 
 Bitmap instance.  The problem is, the pixel data is so big it barely 
 fits into memory.  I thought it would be no problem, surely I can pass 
 the int[] to a Bitmap factory method which simply wraps it in a Bitmap 
 instance.  Unfortunately, this does not seem to be the case - 
 createBitmap(int[] colors, int width, int height, Bitmap.Config 
 config) seems to allocate its own int[] and copy the passed in int[] 
 into it, which fails if there is no memory for another copy. 

 I simply need to turn the image stored in the int[] to a .png on 
 external storage so actually any of the following would be good enough 
 for me: 

 - as mentioned above, a way to create a Bitmap so that it doesn't try 
 to allocate another useless copy of the data 

 - an accessor on Bitmap to return the Bitmap's pixel store as an int[] 
 (that way I wouldn't have to allocate my own int[] and would be able 
 to write directly into the Bitmap-owned memory) 

 - a way of accessing (an equivalent of) Bitmap.compress() 
 functionality without having a Bitmap 

 Amazingly, none of the above seems to be available!  Bitmaps tend to 
 be large objects in memory, surely there must be ways to handle them 
 in a memory-efficient manner... 

 Cheers! 


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

Re: [android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Romain Guy
Could you use setPixels(int[]) instead?


On Mon, Jul 9, 2012 at 9:52 AM, Latimerius l4t1m3r...@googlemail.comwrote:

 On Mon, Jul 9, 2012 at 6:16 PM, Nobu Games dev.nobu.ga...@gmail.com
 wrote:
  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.

 I tried in the meantime to fill my large Bitmap by calling setPixel()
 on each of its pixels and the running time is in the order of tens
 seconds.

  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. There is no guarantee, though that direct
 access
  works in any case. The documentation of that function explains the limits
  pretty well.

 I don't use NDK in this app, was meant to be pure Java, however as
 there are other (performance) problems with bulk GL data handling that
 apparently cannot be solved without native code, I might consider NDK
 as well.

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




-- 
Romain Guy
Android framework engineer
romain...@android.com

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

Re: [android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Latimerius
On Mon, Jul 9, 2012 at 8:22 PM, Romain Guy romain...@android.com wrote:
 Could you use setPixels(int[]) instead?

I considered passing my int[] to setPixels() but (correct me if I'm
wrong) that wouldn't remove the problem where at some point, the
bitmap data has to exist in two copies.

However, I probably could use setPixels(int[]) and pass subimages
several times until the whole bitmap is filled.  Yes, I'll check that
out, sounds like a good idea.

Thanks!

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


Re: [android-developers] Re: creating Bitmap from pixel data *without* copying the data

2012-07-09 Thread Latimerius
On Mon, Jul 9, 2012 at 8:02 PM, RichardC richard.crit...@googlemail.com wrote:
 A quick search turns up quite a few Java PNG encoders with various license
 conditions.

 Encoding a PNG will not require copying the PNG again so grab one with
 source, a license you like, and if necessary modify it to write directly to
 an output stream.

Thanks, this didn't occur to me.  Just took a quick look, haven't
found anything suitable (should be free and take int[] on input) yet
but I'll try a more thorough search later.

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