bitmap getPixels()/setPixels() color problem

1,895 views
Skip to first unread message

Lukas Adamec

unread,
Aug 9, 2010, 6:23:13 AM8/9/10
to android-ndk
Hi,
I'm begginer of Android native code development. I'd like to compare
some methods of bitmap rendering using JNI and native C++ code.
I can't solve why this code doesn't draw white bitmap to screen?

native code:

static void redrawBitmapTwo(int *pix, int jwidth, int jheight) {
int x, y;
uint16_t* line; // pointer to bitmap line
uint16_t color; // 0xXXXX value of color in RGB_565

for(y = 0; y < jheight*jwidth; y++) {
color = 0xFFFF;
pix[y] = color;
}

extern "C" {
JNIEXPORT void JNICALL
Java_cz_xadamec1_apps_bitmap_BitmapViewTwo_renderBitmapTwo(
JNIEnv *env, jobject obj, jintArray buf, jint jwidth, jint
jheight) {

jint *pix = env -> GetIntArrayElements(buf, 0);
redrawBitmapTwo(pix, jwidth, jheight);
env -> ReleaseIntArrayElements(buf, pix, 0);
}
}

Java code:

public class BitmapDrawingTwo extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new BitmapViewTwo(this));
}

static {
System.loadLibrary("bitmapDrawing");
}
}

class BitmapViewTwo extends View {

private Bitmap bitmap;
private long startTime;
private int[] buffer;
private final int width = 256;
private final int height = 128;

public BitmapViewTwo(Context context) {
super(context);

bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
startTime = System.currentTimeMillis();

buffer = new int[width*height];
}

@Override
protected void onDraw(Canvas canvas) {
bitmap.getPixels(buffer, 0, width, 0, 0, width, height);

renderBitmapTwo(buffer, width, height); // call native
method for redraw bitmap

bitmap.setPixels(buffer, 0, width, 0, 0, width, height);

canvas.drawBitmap(bitmap, 0, 0, null);
// force a redraw, with a different time-based pattern.
invalidate();
}

private static native void renderBitmapTwo(int[] buf, int width, int
height);
}

Thanks for all advice.
Lukas

alan

unread,
Aug 9, 2010, 12:24:32 PM8/9/10
to android-ndk
Debug your code bit by bit:
Does buffer contain the expected values when renderBitmapTwo returns?
Does it work if you set the values of buffer in java rather than C?
Does it work with color formats other than 565?

Onur Cinar

unread,
Aug 9, 2010, 1:08:43 PM8/9/10
to andro...@googlegroups.com

Hi Lukas,

I just did a quick test here with your code, and it looks like working fine for me. So you may want to double check your build environment.  I just removed the invalidate() call.

Here is the test project files I used to test your code:

http://www.zdo.com/android/BitmapDrawingTwo.zip

And the APK file:

http://www.zdo.com/android/BitmapDrawingTwo-debug.apk


By the way, since you are evaluating the native drawing capabilities on Android, I would also suggest you to take a look at the new android/bitmap.h file for doing the drawing directly from the native space.

Regards,

-onur



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


Lukas Adamec

unread,
Aug 10, 2010, 2:05:36 AM8/10/10
to android-ndk
It works well for ARGB_8888 and uint32_t color, but for RGB_565 and
ARGB_4444 and uint16_t it doesn't work. Buffer everytime contains
expected values, but bitmap pixels doesn't. In RGB_565 bitmap doesn't
contain RED component and in ARGB_4444 pixels are set to 0.

There are some log records for RGB_565:
08-10 05:59:55.192: DEBUG/Bitmap0(604): ff00ffff
08-10 05:59:55.192: DEBUG/buffer0(604): ff00ffff
08-10 05:59:55.212: INFO/libbitmapDrawing(604): Color in array: ffff
08-10 05:59:55.221: DEBUG/Bitmap1(604): ff00ffff
08-10 05:59:55.221: DEBUG/buffer1(604): ffff
08-10 05:59:55.262: DEBUG/Bitmap2(604): ff00ffff
08-10 05:59:55.262: DEBUG/buffer2(604): ffff

Bitmap0 and buffer0 are values before native method call, Bitmap1/
buffer1 after native method call and Bitmap2/buffer2 after
bitmap.setPixels(...)

Why Bitmap color is represented by 32 bit integer value, when it has
been defined as RGB_565?

alan

unread,
Aug 10, 2010, 9:07:51 AM8/10/10
to android-ndk
Your java buffer is and int[] and the javadocs for setpixels says:
"Replace pixels in the bitmap with the colors in the array. Each
element in the array is a packed int prepresenting a Color"
so each element in the array represents a single pixel. You are then
passing the int array to jni and casting it to an uint16_t array. This
means that you are placing 2 pixels into every element of the int
array. It would seem from the javadoc that setpixels always takes rgb
4444 regardless of the internal storage format for the bitmap.
copyPixelsFromBuffer explicitly states this:
"Copy the pixels from the buffer, beginning at the current position,
overwriting the bitmap's pixels. The data in the buffer is not changed
in any way (unlike setPixels(), which converts from unpremultipled
32bit to whatever the bitmap's native format is."

Lukas Adamec

unread,
Aug 11, 2010, 2:07:56 AM8/11/10
to android-ndk
Could you advise me, how can I solve this problem? Is necessary to use
some conversion functions, which expand 16-bit data to 32 bits?

alan

unread,
Aug 11, 2010, 9:03:02 AM8/11/10
to android-ndk
either use copyPixelsFromBuffer or change your native code to:
static void redrawBitmapTwo(int *pix, int jwidth, int jheight) {
int x, y;
uint32_t* line; // pointer to bitmap line
uint32_t color; // 0xXXXX value of color in RGB_565
Reply all
Reply to author
Forward
0 new messages