I have native C++ library which decodes the picture and provided the
pixel array [unsigned short *mpixelarry]. The image returned by this
class is 16bpp color depth and having 5:6:5 pixel format.
Now I need to pass these Pixels to Android App where I am using canvas
to draw.
Here I am planning to use
canvas.drawBitmap(_myBitmap, pos_X, pos_Y, null);
Now the problem is -> I need to fill _myBitmap[in Java] with the
mpixelarry[from C++ Library].
But as am newbie to Android and JNI and Graphics....... Not very sure
how to proceed here.
Q1: mpixelarry I am getting from C++ library , is it compatible with
myBitmap?
Q2: Can I copy the pixels directly on to Bitmap?will it work.?are they
compatible ?
Q3:What is the Best way to pass the Pixel array from jni to JAVA.i.e
shall i have to create the myBitmap in Java and pass it to JNI
function and fill it with copyPixelsToBuffer API in JNI
or
Pass the bare Pixel array as it is from JNI to Java and do the stuff
in Java.
I had come across some threads, which are discussed on the same
subject, but could not follow them.[
http://groups.google.com/group/android-ndk/browse_thread/thread/a56eb182f70d2c0f
http://groups.google.com/group/android-ndk/browse_thread/thread/03cb3bc771fd3a1d
]
Q4: Can I get a sample piece of code to do this stuff.
Q5: Is the method I am following good[in performance perspective] or
do I need to look into OpenGL texture as suggested in the above
threads.
Thank you for your support
On the java side:
Bitmap screen = Bitmap.createBitmap(width,height,
Bitmap.Config.RGB_565);
ShortBuffer bufferAsShort = ByteBuffer.allocateDirect(width * height *
2).asShortBuffer(); // allocateDirect is important
and in a main graphic thread loop between the surface's lock and
unlock:
bufferAsShort.position(0); // rewind the buffer to the start
mainScreen.copyPixelsFromBuffer(bufferAsShort); // copy the buffer
inside the bitmap
Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY); // scaleX = scaleY = 1.0 for no
scaling
canvas.drawBitmap(mainScreen, matrix, null); // copy the bitmap into
the canvas
on the JNI side, I send the bufferAsShort reference to get the buffer
pointer, here's an example:
extern "C"
jint Java_org_abc_Test1_getBufferAsShort( JNIEnv* env, jobject thiz,
jobject bufferAsShort, jint width, jint height) {
jshort* buffer = (jshort*) (env)->GetDirectBufferAddress
(bufferAsShort);
// then you can mess with the buffer pointer to populate it with some
bitmap data
}
On Jan 1, 5:35 am, RangaRao <sujatha.gul...@gmail.com> wrote:
> Hi All,
>
> I have native C++ library which decodes the picture and provided the
> pixel array [unsigned short *mpixelarry]. The image returned by this
> class is 16bpp color depth and having 5:6:5 pixel format.
>
> Now I need to pass these Pixels to Android App where I am using canvas
> to draw.
> Here I am planning to use
> canvas.drawBitmap(_myBitmap, pos_X, pos_Y, null);
>
> Now the problem is -> I need to fill _myBitmap[in Java] with the
> mpixelarry[from C++ Library].
>
> But as am newbie to Android and JNI and Graphics....... Not very sure
> how to proceed here.
>
> Q1: mpixelarry I am getting from C++ library , is it compatible with
> myBitmap?
> Q2: Can I copy the pixels directly on to Bitmap?will it work.?are they
> compatible ?
> Q3:What is the Best way to pass the Pixel array from jni to JAVA.i.e
> shall i have to create the myBitmap in Java and pass it to JNI
> function and fill it with copyPixelsToBuffer API in JNI
> or
> Pass the bare Pixel array as it is from JNI to Java and do the stuff
> in Java.
>
> I had come across some threads, which are discussed on the same
> subject, but could not follow them.[http://groups.google.com/group/android-ndk/browse_thread/thread/a56eb...
>
> http://groups.google.com/group/android-ndk/browse_thread/thread/03cb3...
my problem:
- I'm painting map tiles onto screen (tiles are 120 x 120px -
14400px)
- from file with tiles I obtain
1. palette - array of int int[256] - 256 colors
2. image data, deflated by zlib, after decopress (by Inflater) i
receive 14400b array of byte[], that contain indexes of colors in
color array
currently i'm not using JNI so to create Bitmap I use this code:
[code]
// variables
private byte[] imageBuffer = new byte[120 * 120];
private int[] imageData = new int[120 * 120];
// part of code that create image
byte[] buffer = new byte[4];
is.read(buffer, 0, 4);
int size = UtilsIO.readInt(buffer, 0, 4); // get size of compressed
image data
// load and decompress data
buffer = new byte[size];
is.read(buffer, 0, size);
Inflater inflater = new Inflater();
inflater.setInput(buffer);
inflater.inflate(imageBuffer);
// 12 ms / image - stupid and very slow cycle to fill image data
with right colors
for (int i = 0; i < 14400; i++) {
imageData[i] = palette[imageBuffer[i] & 0xFF];
}
Bitmap bitmap = Bitmap.createBitmap(imageData, 120, 120,
Bitmap.Config.RGB_565);
[/code]
- so, after loading image data, I have to create new array filled
with right color for every pixel. This is very slow (cycle with 14400
computes for every image). I'm testing it on motorola milestone and
cause of big resolution, I need around 40 images to cover whole
screen. Because this is map application, so you move with tiles, this
method is very slow. Because I'm not much familiar with C++, I'm
asking if anyone have any idea how to make it faster, probably with
using of JNI.
thank you very much for answers and hope, that you RangaRao, will
find answer on your problem as well.
Menion
Thank you for your suggestion. We are able to see the image now on the
Android emulator.
extern "C"{
#include "test.h"
}
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#define LOG_TAG "PicoDriveJNI"
#include <utils/Log.h>
#include <jni.h>
#include <JNIHelp.h>
#include <utils/SortedVector.h>
#include <ui/Surface.h>
#include <core/SkBitmap.h>
#include <core/SkPixelRef.h>
#include "android_runtime/AndroidRuntime.h"
#include <dlfcn.h>
using namespace android;
#define gClassName "com/android/myfirstnative/Jni_Cross"
//
static jfieldID jfVideoBuffer;
static jfieldID jfNativeBitmap;
static jclass jclassBitmap;
static SkBitmap *pVideoBuffer;
static char *pVideoRam = NULL;
jclass mClass;
static int SayHello(JNIEnv *env, jclass clazz,jcharArray
Ary_Printout)
{
mClass = (jclass)env->NewGlobalRef(clazz);
jchar* Printout= env->GetCharArrayElements(Ary_Printout,0);
memcpy(Printout,"hello world",12);
jint temint = GetValue();
return temint;
// env->ReleaseArrayElements(Ary_Printout, Printout, 0);
}
//
extern "C" void CCallJavaFun(int x, int y)
{
JNIEnv *j_env = AndroidRuntime::getJNIEnv();
jclass gclazz = j_env->FindClass(gClassName);
jmethodID jMid = j_env->GetMethodID(gclazz, "JavaFun", "(II)V");
if(jMid == NULL)
{
return ;
}
j_env->CallVoidMethod(mClass,jMid,x,y);
}
static void Set_ScrBitmap(JNIEnv *env, jclass clazz,jint w,jint h)
{
jclass gclazz = env->FindClass(gClassName);
jfVideoBuffer = env->GetFieldID(gclazz, "g_MapBitmap", "Landroid/
graphics/Bitmap;");
jclassBitmap = env->FindClass("android/graphics/Bitmap");
jfNativeBitmap = env->GetFieldID(jclassBitmap, "mNativeBitmap",
"I");
jclass jvb = (jclass)env->GetObjectField(clazz, jfVideoBuffer);
if ( jvb == NULL ) {
LOGE("Can't get mVideoBuffer");
return ;
}
pVideoBuffer = (SkBitmap *)env->GetIntField(jvb, jfNativeBitmap);
if ( pVideoBuffer == NULL )
{
LOGE("Can't get mVideoBuffer");
return;
}
pVideoRam = (char*) pVideoBuffer->getPixels();
if ( pVideoRam == NULL ) {
pVideoBuffer->allocPixels();
pVideoRam = (char*) pVideoBuffer->getPixels();
if ( pVideoRam == NULL ) {
LOGE("Can't get Video RAM");
return ;
}
}
refresh(pVideoRam);
}
/**** Native android method register ****/
static JNINativeMethod gMethods[] = {
{ "SayHello", "([C)I", (void *)SayHello },
{ "Set_ScrBitmap", "(II)V", (void *)Set_ScrBitmap},
};
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *env;
if ( vm->GetEnv((void **)&env, JNI_VERSION_1_6) ) return JNI_ERR;
jclass clazz = env->FindClass(gClassName);
env->RegisterNatives(clazz, gMethods, NELEM(gMethods));
return JNI_VERSION_1_6;
}
void JNI_OnUnload(JavaVM* vm, void* reserved)
{
JNIEnv *env;
if (vm->GetEnv((void **)&env, JNI_VERSION_1_6)) return;
jclass cls = env->FindClass(gClassName);
env->UnregisterNatives(cls);
}
so ,you can get the buffer of the bitmap created by java through c/c+
+ code,here the buffer is
:
pVideoBuffer = (SkBitmap *)env->GetIntField(jvb, jfNativeBitmap);
pVideoRam = (char*) pVideoBuffer->getPixels();
then fill the buffer [pVideoRam] as you like.
any questions? please feel free to contact me.