Shrinidhi Rao
Shrinidhi Rao

Reputation: 275

How to pass a Image through JNI from Java to Cocos2d-x?

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

Answers (3)

sbhhbs
sbhhbs

Reputation: 625

  1. create a Java interface forJNI like:

    public static native void setBG(int[] raw, int width, int height);
    
  2. 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

  1. 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

Geo Paul
Geo Paul

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

Guy Kogus
Guy Kogus

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

Related Questions