Reputation: 275
I need to pass a image data like drawable from java side to cocos2d-x through JNI. How do i implement it?. What should be the parameter for JNI function and how to cast in cocos2d-x side?
Upvotes: 2
Views: 1817
Reputation: 625
create a Java interface forJNI like:
public static native void setBG(int[] raw, int width, int height);
in c++ code do:
//Use static variable here for simplicity
int *imagedata;
int staticwidth;
int staticheight;
Texture2D *userBackgroundImage;
void Java_com_my_company_JniHelper_setBG(JNIEnv* env, jobject thiz, jintArray raw, jint width, jint height)
{
jint *carr;
carr = env->GetIntArrayElements(raw, 0);
if(carr == NULL) {
return; /* exception occurred */
}
ssize_t dataLen = (int)width * (int)height;
int *data = new int[dataLen];
for (long i = 0; i < dataLen; i++)
{
data[i] = carr[i];
}
imagedata = data;//Make a copy because it need to be done in GLThread
staticwidth = (int)width;
staticheight = (int)height;
env->ReleaseIntArrayElements(raw, carr, 0);
LOGD("set image: %d * %d", width, height);
}
Then call the following method somewhere duration layer init or other cocos2d-x code:
void createImage(const void *data, ssize_t dataLen, int width, int height)
{
Texture2D *image = new Texture2D();
if (!image->initWithData(data, dataLen, Texture2D::PixelFormat::BGRA8888, width, height, Size(width, height)))
{
delete image;
delete imagedata;
image = NULL;
imagedata = NULL;
userBackgroundImage = NULL;
return;
}
delete imagedata;
imagedata = NULL;
userBackgroundImage = image;
}
You can then use the Texture2D object to create a sprite or do whatever you want
To call this code from java:
public static int[] BitmapToRaw(Bitmap bitmap) {
Bitmap image = bitmap.copy(Bitmap.Config.ARGB_8888, false);
int width = image.getWidth();
int height = image.getHeight();
int[] raw = new int[width * height];
image.getPixels(raw, 0, width, 0, 0, width, height);
return raw;
}
Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
JniHelper.setBG(BitmapToRaw(image), image.getWidth(), image.getHeight());
Upvotes: 3
Reputation: 1817
I think the best and easy way to do it will be saving it in Java and then accessing the file from cpp and then deleting it after use.
Upvotes: 0
Reputation: 7341
I've only ever sent image data from cocos2d-x to Java, so you'll need to find a way to reverse this method. It's used to capture a node and pass it through for screenshots.
CCNode* node = <some node>;
const CCSize& size(node->getContentSize());
CCRenderTexture* render = CCRenderTexture::create(size.width, size.height);
// render node to the texturebuffer
render->clear(0, 0, 0, 1);
render->begin();
node->visit();
render->end();
CCImage* image = render->newCCImage();
// If we don't clear then the JNI call gets corrupted.
render->clear(0, 0, 0, 1);
// Create the array to pass in
jsize length = image->getDataLen();
jintArray imageBytes = t.env->NewIntArray(length);
unsigned char* imageData = image->getData();
t.env->SetIntArrayRegion(imageBytes, 0, length, const_cast<const jint*>(reinterpret_cast<jint*>(imageData)));
t.env->CallStaticVoidMethod(t.classID, t.methodID, imageBytes, (jint)image->getWidth(), (jint)image->getHeight());
image->release();
t.env->DeleteLocalRef(imageBytes);
t.env->DeleteLocalRef(t.classID);
The Java side looks like this:
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
public static Bitmap getImage(int[] imageData, int width, int height) {
Bitmap image = Bitmap.createBitmap(width, height, Config.ARGB_8888);
image.setPixels(imageData, 0, width, 0, 0, width, height);
return image;
}
Upvotes: 1