1

I have a Native android project that gets the internal storage directory of the current application and can also manipulate the pixels of a bitmap passed from the java to the c++.

My goal is to be able to read in an image file from that location as a jobject in the C itself, so I can then return to the calling function. The catch is that I wish to avoid using a java call to retrieve the bitmap itself and want it done purely by the Native. (i.e. nothing like env->CallObjectMethod)

The code I have so far gets the location/filename of the desired image file, but I do have another native file which is properly working with/manipulating passed in bitmaps(using bitmap.h), but since it's used afterwards and I'm comfortable with it I haven't included it. Here is the path/filename code:

#include "frameConstruction.h"
#include <string>
#include <unistd.h>

using namespace std;

#define  LOG_TAG    "TAG"
//macros to call the Log functions to allow for debugging. the tag is declared on the line above
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

JNIEXPORT jstring JNICALL Java_com_example_ndkbitmapcreation_FrameConstructionLib_constructFrame(
        JNIEnv* env, jobject obj, jobject javaThis, jstring stringSomething) {

    jclass cls = env->GetObjectClass(javaThis);

    jmethodID getFilesDir = env->GetMethodID(cls, "getFilesDir",
            "()Ljava/io/File;");

    jobject dirobj = env->CallObjectMethod(javaThis, getFilesDir);
    jclass dir = env->GetObjectClass(dirobj);

    jmethodID getStoragePath = env->GetMethodID(dir, "getAbsolutePath",
            "()Ljava/lang/String;");
    jstring path = (jstring) env->CallObjectMethod(dirobj, getStoragePath);
    const char *pathstr = env->GetStringUTFChars(path, 0);
    std::string fullPath = std::string(pathstr);
    chdir(pathstr);

    env->ReleaseStringUTFChars(path, pathstr);

    const char *filenamestr = env->GetStringUTFChars(stringSomething, 0);
    //need code here to call the File.separator method from java,
    //if someone knows how to do this that'd be great, currently
    //this just grabs the first char from the path which is (hopefully)
    //the proper file separator
    fullPath += fullPath[0];
    fullPath += filenamestr;

    env->ReleaseStringUTFChars(stringSomething, filenamestr);
    //pixel manip will go here

    return env->NewStringUTF(fullPath.c_str());
}

so how would I go about reading the data from that file into a jobject returnable as a bitmap (i.e.: return varName;) without calling a java method? Alternatively I could read it into a bytearray like from: JNI in C++ to read file to jbyteArray then the question becomes how to change a jbytearray into a jobject usable with again without calls to the Java?

I'm hoping to avoid making a bitmap in java then pass it into c++, but my code requires a lot of bitmap loading/manipulating and is causing OOM errors in the java, so I'm trying an approach in Native to try my best to avoid it. It's been a many month long project and this is hopefully one of the final hurdles, if anyone out there can help I'd sure appreciate it ^_^.

Community
  • 1
  • 1
codingNewb
  • 470
  • 1
  • 8
  • 23

2 Answers2

1

I'm pretty sure it is simply not possible to create a bitmap in native code without calling a java method.

If you're familiar with the bitmap.h header, you'll have seen that it offers only very limited possibilities: you can edit a bitmap in native, but not create it.

You can still avoid writing java code by calling the Bitmap constructors from the NDK part of the code!

mbrenon
  • 4,851
  • 23
  • 25
  • how would I go about doing that? – codingNewb Dec 03 '13 at 10:35
  • I guess [this answer](http://stackoverflow.com/a/7737034/1417179) will help you create a new Bitmap by calling the Java methods from native code! – mbrenon Dec 03 '13 at 10:38
  • will this take the same heap as my other calls (In Java itself) to creating the bitmaps? if not I'll all for it, but if I'm going to face the same OOM errors I'm stuck in the same boat =( – codingNewb Dec 03 '13 at 11:02
  • These are Java calls issued from native code, but they remain Java calls: they will use the same heap. But again, there is no way to create a Bitmap otherwise... If you are concerned about memory, you can maybe imagine storing the pixel data in pure native (not on the Java heap) and converting it to a Bitmap only when it is absolutely needed by the Java side. – mbrenon Dec 03 '13 at 11:19
0

One option is to load the bitmap with android.graphics.BitmapRegionDecoder. Say the bitmap is usually 20M big, you load 5M of the bitmap a time, save it to a native global object. Then with 4 times, you have your bitmap in native world, without blowing your java memory limit.

Another option is to use native OpenCV, but there are a lot of problems to tackle.

Ning
  • 189
  • 1
  • 10