Bitmap over JNI

1,923 views
Skip to first unread message

George

unread,
Oct 16, 2009, 3:46:34 PM10/16/09
to android-ndk
What is the best way (in terms of memory and performance) to pass a
Bitmap from Java to native? I am passing a Bitmap to create an openGL
texture.
One way would be to use Bitmap.getPixels to get a byte array and use
getIntArrayElements in native and then use texImage2D. Is there any
other way?

Dan Sherman

unread,
Oct 16, 2009, 3:51:20 PM10/16/09
to andro...@googlegroups.com
I'd be very interested in hearing whatever solution people come up with as well :)

- Dan

Jack Palevich

unread,
Oct 16, 2009, 3:55:23 PM10/16/09
to andro...@googlegroups.com
The best (and fastest) way is to use the Android Java API android.opengl.GLUtils.texImage2D.

This API will create an OpenGL texture from the Android Bitmap without making a copy of the bitmap data.

There's also texSubImage2D if you need that.

Bipin George Mathew

unread,
Oct 16, 2009, 4:53:51 PM10/16/09
to andro...@googlegroups.com
Well, that won't work for me since I am doing all my openGl rendering
in native.

I guess, my question becomes that same as here
-http://groups.google.com/group/android-ndk/browse_thread/thread/59ef8f2ad50659b0/dd59f9c92ffbf1db?lnk=gst&q=bitmap#dd59f9c92ffbf1db

-Bipin

Pawel Veselov

unread,
Oct 16, 2009, 5:01:28 PM10/16/09
to andro...@googlegroups.com

I think it would be creating a direct byte buffer, and writing out content of the bitmap to the buffer (there is a method for that). The best is using RGB_565 format, on most platforms, at least.

On Fri, Oct 16, 2009 at 12:46 PM, George <bip...@gmail.com> wrote:



--
With best of best regards
Pawel S. Veselov

Jack Palevich

unread,
Oct 16, 2009, 5:14:49 PM10/16/09
to andro...@googlegroups.com
Unfortunately there is no API for getting at the raw bits of a Bitmap, because we want to be free to change the internal representation without breaking existing programs.

Could you explain in more detail why you don't you think android.opengl.GLUtils.texImage2D will work for you?

You can freely intermix Java-level and native OpenGL calls. There's only one OpenGL ES context per thread, and it's used by both the Java level and native libraries.

If you don't want to use Java at all, then why is your texture in a Bitmap object? Why not just port libjpeg or libpng and decode the data yourself in native code?

Bipin George Mathew

unread,
Oct 16, 2009, 6:20:30 PM10/16/09
to andro...@googlegroups.com
On Fri, Oct 16, 2009 at 2:14 PM, Jack Palevich <jac...@google.com> wrote:
> Unfortunately there is no API for getting at the raw bits of a Bitmap,
> because we want to be free to change the internal representation without
> breaking existing programs.
> Could you explain in more detail why you don't you
> think android.opengl.GLUtils.texImage2D will work for you?
> You can freely intermix Java-level and native OpenGL calls. There's only one
> OpenGL ES context per thread, and it's used by both the Java level and
> native libraries.

I may have misunderstood you initial suggestion. Was it to do
something like this in my native code:
void
Java_com_Sample_nativeOpenGLRender( JNIEnv* env, jobject thiz, jobject bitmap)
{
jclass GLUtilsClass = env->FindClass("android/opengl/GLUtils");
jmethodID methodID = env->GetMethodID(GLUtilsClass, "texImage2D", ...);
jint target, level, border; // obtain these values appropriately
env->CallVoidMethod(env, obj, target, level, bitmap, border);
...

Jack Palevich

unread,
Oct 16, 2009, 6:37:06 PM10/16/09
to andro...@googlegroups.com
Well, yeah, sure, you could do that.

I was thinking more along the lines of you calling GLUtils.texImage2D from your Java code, right next to where you created or obtained the Bitmap object. I figured there had to be some Java code somewhere, or else you wouldn't have a Bitmap object to begin with.

Bipin George Mathew

unread,
Oct 16, 2009, 6:57:31 PM10/16/09
to andro...@googlegroups.com
Right, it is definitely an option I will consider. Thanks.

fadden

unread,
Oct 16, 2009, 7:38:49 PM10/16/09
to android-ndk
On Oct 16, 3:20 pm, Bipin George Mathew <bipi...@gmail.com> wrote:
> void
> Java_com_Sample_nativeOpenGLRender( JNIEnv*  env, jobject  thiz, jobject bitmap)
> {
> jclass GLUtilsClass = env->FindClass("android/opengl/GLUtils");
> jmethodID methodID = env->GetMethodID(GLUtilsClass, "texImage2D", ...);
> jint target, level, border; // obtain these values appropriately
> env->CallVoidMethod(env, obj, target, level, bitmap, border);
> ...

I expect the above is just for illustration rather than actual code,
but just in case: be sure to cache the results from FindClass and
GetMethodID, rather than calling them every time. They can be
expensive calls. If you do, be sure to store a global reference to
the class object, rather than the result of FindClass (i.e. keep the
result of calling NewGlobalRef).

Bipin George Mathew

unread,
Oct 16, 2009, 7:57:08 PM10/16/09
to andro...@googlegroups.com
yep, it was just for illustration :) Thanks anyway.

Anders Johansson

unread,
Oct 17, 2009, 8:21:18 AM10/17/09
to android-ndk
This is a very interesting thread.

In some of my apps I use a C library for 2D image manipulation, i.e.
no need for GL.
The best way I've found so far is to use a direct ByteBuffer, and on
that I use Bitmap.copyPixelsToBuffer and copyPixelsFromBuffer in java
code, and then get the data ptr in C code to access the ByteBuffer...
Are you suggesting that using the GL APIs might be even more
efficient? Personally I thought getting access to SkBitmap in the NDK
would be super, as I could then directly access the data buffer in the
Bitmap object and circumvent the need for copying...

regards
Anders



On Oct 17, 12:37 am, Jack Palevich <jack...@google.com> wrote:
> Well, yeah, sure, you could do that.
> I was thinking more along the lines of you calling GLUtils.texImage2D from
> your Java code, right next to where you created or obtained the Bitmap
> object. I figured there had to be some Java code somewhere, or else you
> wouldn't have a Bitmap object to begin with.
>
> On Fri, Oct 16, 2009 at 3:20 PM, Bipin George Mathew <bipi...@gmail.com>wrote:
> > > On Fri, Oct 16, 2009 at 1:53 PM, Bipin George Mathew <bipi...@gmail.com>
> > > wrote:
>
> > >> Well, that won't work for me since I am doing all my openGl rendering
> > >> in native.
>
> > >> I guess, my question becomes that same as here
>
> > >> -
> >http://groups.google.com/group/android-ndk/browse_thread/thread/59ef8...
>
> > >> -Bipin
>
> > >> On Fri, Oct 16, 2009 at 12:55 PM, Jack Palevich <jack...@google.com>
> > >> wrote:
> > >> > The best (and fastest) way is to use the Android Java API
> > >> > android.opengl.GLUtils.texImage2D.
> > >> > This API will create an OpenGL texture from the Android Bitmap without
> > >> > making a copy of the bitmap data.
> > >> > There's also texSubImage2D if you need that.
>

Jack Palevich

unread,
Oct 17, 2009, 9:31:29 AM10/17/09
to andro...@googlegroups.com
The GLUtils APIs are only more efficient if you want to transfer the data from a Bitmap to an OpenGL texture. The reason they are more efficient in that case is because they avoid making an extra copy of the Bitmap pixel data. (The data is still copied once, from the Bitmap's internal storage to the OpenGL driver's storage.)

Eric Wang

unread,
Oct 17, 2009, 10:54:01 AM10/17/09
to andro...@googlegroups.com
Hi Jack, that sounds very cool, can you post a piece of code to illustrate rendering a Bitmap to screen via GL stuff?
Thanks so much!

2009/10/17 Jack Palevich <jac...@google.com>

Jack Palevich

unread,
Oct 17, 2009, 11:29:13 AM10/17/09
to andro...@googlegroups.com
Please look at the Sprite Text sample in the SDK. You can download the SDK here:

http://developer.android.com/sdk/1.6_r1/index.html

And then look at

platforms/android-1.6/samples/ApiDemos/src/com/example/android/apis/graphics/spritetext

Pawel Veselov

unread,
Oct 17, 2009, 2:59:18 PM10/17/09
to andro...@googlegroups.com
On Sat, Oct 17, 2009 at 5:21 AM, Anders Johansson <svi...@gmail.com> wrote:

This is a very interesting thread.

In some of my apps I use a C library for 2D image manipulation, i.e.
no need for GL.
The best way I've found so far is to use a direct ByteBuffer, and on
that I use Bitmap.copyPixelsToBuffer and copyPixelsFromBuffer in java
code, and then get the data ptr in C code to access the ByteBuffer...
Are you suggesting that using the GL APIs might be even more
efficient? Personally I thought getting access to SkBitmap in the NDK
would be super, as I could then directly access the data buffer in the
Bitmap object and circumvent the need for copying...

Copying a bitmap into direct buffer is effective, since it's done in native code, and bitmap realizes that it is being written into a direct buffer, so memcpy() is called.

Trying to hook to SkBitmap would be a bad idea because it's not public API, and is not guaranteed to exist at all long term.

shagrath

unread,
Oct 18, 2009, 7:33:29 AM10/18/09
to android-ndk
I concur that the OpenGL stuff is faster than the copyPixelsFromBuffer
method. I've tested both ways and I get roughly 35 fps in my little
game emulator using the bitmap method and more than 45 fps using
texImage2D (those numbers are arbitrary, it depends obviously of the
nature of the native process doing the render, and the size of the
bitmap). I've spend a couple hours to learn how to set up a 2D GL
scene though :p Also, don't forget to use GL_UNSIGNED_SHORT_5_6_5 for
the palette color, it's more efficient
Reply all
Reply to author
Forward
0 new messages