feature request: draw image to Canvas without temporary bitmap

1,019 views
Skip to first unread message

foo64

unread,
Dec 4, 2013, 9:08:01 PM12/4/13
to andro...@googlegroups.com
I'm using the NDK to stream images to an ImageView. My refresh rate is at least 20hz so rendering performance is very important to me.

On startup I create a temporary Bitmap object to draw frames into, since that's the most efficient way I'm aware of to draw frames onto the canvas. When it comes time to draw the next frame, I must do these steps:

  1. copy frame from native memory to temporary bitmap using AndroidBitmap_lockPixels()
  2. draw temporary bitmap via JNI with http://developer.android.com/reference/android/graphics/Canvas.html#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint)

There's an interesting Canvas function to draw a "color array": http://developer.android.com/reference/android/graphics/Canvas.html#drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint). Maybe this can get rid of my temporary bitmap? Unfortunately not. In practice it's a bad function (especially from native code) because:

  • it only accepts a Java int array. That means you must use JNI to create a temporary jintArray, copy your frame from native memory, before calling this function.
  • it actually creates a temporary bitmap, copies your color array to it, then draws the bitmap. That's even worse than my current setup! (at least I reuse the temporary bitmap)

I wish I could just store frames directly as Bitmaps (and not worry about copying native memory into a temporary Bitmap object), but that's not a viable option because Bitmap memory is stored on the VM heap, not native memory. I would quickly blow through the VM heap if I just created Bitmaps. Keep in mind when streaming, you buffer the next few frames, and that each ImageView has its own buffer. It adds up. One of the advantages of using the NDK is that I can allocate a lot more memory than I could from Java, and my allocations don't come out of the VM heap.

What would be great is to skip the "copy frame from native memory to temporary bitmap" step above, and draw directly from native memory to the canvas using an NDK function. The API might look like this:

<android/canvas.h>
int AndroidCanvas_drawBitmap( jobject canvas, const void* colors, AndroidBitmapFormat format, etc. );

The NDK already provides raw bitmap pixel access via AndroidBitmap_lockPixels(), so this wouldn't be much of a leap. 

Thanks!

Philippe Simons

unread,
Dec 5, 2013, 3:23:09 AM12/5/13
to android-ndk
mmmh an ImageView might not be the best component to display a stream of images...

why not using a SurfaceView and ANativeWindow_lock / ANativeWindow_unlockAndPost or a GLSurfaceView and draw in it using OpenGL ES

you can retrieve a ANativeWindow* with ANativeWindow_fromSurface()

Philippe


--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk...@googlegroups.com.
To post to this group, send email to andro...@googlegroups.com.
Visit this group at http://groups.google.com/group/android-ndk.
For more options, visit https://groups.google.com/groups/opt_out.

foo64

unread,
Dec 5, 2013, 3:34:39 AM12/5/13
to andro...@googlegroups.com
SurfaceView is not an option because of this:

Because a SurfaceView’s content does not live in the application’s window, it cannot be transformed (moved, scaled, rotated) efficiently. This makes it difficult to use a SurfaceView inside a ListView or a ScrollView

Philippe Simons

unread,
Dec 5, 2013, 4:48:00 AM12/5/13
to android-ndk
true, but still, an ImageView is not really designed to display a stream of images.

David Turner

unread,
Dec 5, 2013, 5:27:48 AM12/5/13
to andro...@googlegroups.com
On Thu, Dec 5, 2013 at 9:34 AM, foo64 <brian...@gmail.com> wrote:
SurfaceView is not an option because of this:

Because a SurfaceView’s content does not live in the application’s window, it cannot be transformed (moved, scaled, rotated) efficiently. This makes it difficult to use a SurfaceView inside a ListView or a ScrollView

May I ask you what are you trying to achieve exactly? I'm pretty sure that ListView / ScrollView are not designed to support displaying animated images at high framerates.

Brian Segall

unread,
Dec 5, 2013, 1:29:02 PM12/5/13
to andro...@googlegroups.com
Well, the Android UI as a whole isn't designed to display animated images at high framerates, but it doesn't mean we can't make it work. The NDK goes a long way towards alleviating some of the bottlenecks. Drawing natively to the canvas would be an incremental improvement in this direction.

For the record, TextureView is the perfect choice for my purposes, but it's only available in API 14 so ImageView is still needed for backwards compatibility. TextureView has the same issue of needing to use a temporary bitmap in order to draw to its canvas.



--
You received this message because you are subscribed to a topic in the Google Groups "android-ndk" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/android-ndk/wtc6CoGUWcQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to android-ndk...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages