[android-developers] Re: creating Bitmap from pixel data *without* copying the data
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
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
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
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
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
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
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
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
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
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