diff options
author | Iliyan Malchev <malchev@google.com> | 2008-10-10 14:44:19 -0700 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2008-10-13 20:33:43 -0700 |
commit | 63e2b7f201d2f461f79c63f1d84eb69930d9c9cc (patch) | |
tree | 2fdbf3280af35fdbcd9fdb9908481596c3ff11a2 | |
parent | 365fc6e68e1c422d14f259261c7a128fce977b9e (diff) | |
download | tesseract-63e2b7f201d2f461f79c63f1d84eb69930d9c9cc.tar.gz |
save native context in object, not in static variables
Signed-off-by: Iliyan Malchev <malchev@google.com>
-rw-r--r-- | ccmain/jni.cpp | 129 |
1 files changed, 98 insertions, 31 deletions
diff --git a/ccmain/jni.cpp b/ccmain/jni.cpp index 8aba412..59b2304 100644 --- a/ccmain/jni.cpp +++ b/ccmain/jni.cpp @@ -27,19 +27,31 @@ #if DEBUG #include <stdio.h> BOOL_VAR (tessedit_write_images, TRUE, - "Capture the image from the IPE"); + "Capture the image from the IPE"); #endif -#define LOG_TAG "OcrLib" +#define LOG_TAG "OcrLib(native)" #include <utils/Log.h> -static tesseract::TessBaseAPI api; -static jbyteArray image_obj; -static jbyte* image_buffer; +static jfieldID field_mNativeData; + +struct native_data_t { + tesseract::TessBaseAPI api; + jbyteArray image_obj; + jbyte* image_buffer; +}; + +static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { + return (native_data_t *)(env->GetIntField(object, field_mNativeData)); +} jboolean ocr_open(JNIEnv *env, jobject thiz, jstring lang) { + LOGV(__FUNCTION__); + + native_data_t *nat = get_native_data(env, thiz); + if (lang == NULL) { LOGE("lang string is null!"); return JNI_FALSE; @@ -54,12 +66,12 @@ ocr_open(JNIEnv *env, jobject thiz, jstring lang) jboolean res = JNI_TRUE; LOGI("lang %s\n", c_lang); - if (api.Init("/sdcard/", c_lang)) { + if (nat->api.Init("/sdcard/", c_lang)) { LOGE("could not initialize tesseract!"); res = JNI_FALSE; } #if DEBUG - else if (!api.ReadConfigFile("/sdcard/tessdata/ratings")) { + else if (!nat->api.ReadConfigFile("/sdcard/tessdata/ratings")) { LOGE("could not read config file, using defaults!"); // This is not a fatal error. } @@ -102,8 +114,12 @@ ocr_recognize_image(JNIEnv *env, jobject thiz, jint bpp, jint rowWidth) { + LOGV(__FUNCTION__); + LOGI("recognize image x=%d, y=%d, rw=%d\n", width, height, rowWidth); + native_data_t *nat = get_native_data(env, thiz); + if (env->GetArrayLength(image) < width * height) { LOGE("image length = %d is less than width * height = %d!", env->GetArrayLength(image), @@ -111,9 +127,9 @@ ocr_recognize_image(JNIEnv *env, jobject thiz, } jbyte* buffer = env->GetByteArrayElements(image, NULL); - api.SetImage((const unsigned char *)buffer, + nat->api.SetImage((const unsigned char *)buffer, width, height, bpp, rowWidth); - char * text = api.GetUTF8Text(); + char * text = nat->api.GetUTF8Text(); env->ReleaseByteArrayElements(image, buffer, JNI_ABORT); dump_debug_data(text); @@ -129,11 +145,15 @@ ocr_set_image(JNIEnv *env, jobject thiz, jint bpp, jint rowWidth) { - LOG_ASSERT(image_obj == NULL && image_buffer == NULL, + LOGV(__FUNCTION__); + LOG_ASSERT(nat->image_obj == NULL && nat->image_buffer == NULL, "image and/or image_buffer are not NULL!"); - image_obj = (jbyteArray)env->NewGlobalRef(image); - image_buffer = env->GetByteArrayElements(image_obj, NULL); - api.SetImage((const unsigned char *)image_buffer, + + native_data_t *nat = get_native_data(env, thiz); + + nat->image_obj = (jbyteArray)env->NewGlobalRef(image); + nat->image_buffer = env->GetByteArrayElements(nat->image_obj, NULL); + nat->api.SetImage((const unsigned char *)nat->image_buffer, width, height, bpp, rowWidth); } @@ -142,12 +162,15 @@ ocr_set_rectangle(JNIEnv *env, jobject thiz, jint left, jint top, jint width, jint height) { + LOGV(__FUNCTION__); // Restrict recognition to a sub-rectangle of the image. Call after SetImage. // Each SetRectangle clears the recogntion results so multiple rectangles // can be recognized with the same image. - LOG_ASSERT(image_obj != NULL && image_buffer != NULL, + native_data_t *nat = get_native_data(env, thiz); + + LOG_ASSERT(nat->image_obj != NULL && nat->image_buffer != NULL, "image and/or image_buffer are NULL!"); - api.SetRectangle(left, top, width, height); + nat->api.SetRectangle(left, top, width, height); } jstring @@ -156,10 +179,14 @@ ocr_recognize(JNIEnv *env, jobject thiz, jint bpp, jint rowWidth) { - LOG_ASSERT(image_obj != NULL && image_buffer != NULL, + LOGV(__FUNCTION__); + + native_data_t *nat = get_native_data(env, thiz); + + LOG_ASSERT(nat->image_obj != NULL && nat->image_buffer != NULL, "image and/or image_buffer are NULL!"); - char * text = api.GetUTF8Text(); + char * text = nat->api.GetUTF8Text(); dump_debug_data(text); @@ -170,18 +197,22 @@ ocr_recognize(JNIEnv *env, jobject thiz, static jint ocr_mean_confidence(JNIEnv *env, jobject thiz) { + LOGV(__FUNCTION__); + native_data_t *nat = get_native_data(env, thiz); // Returns the (average) confidence value between 0 and 100. - return api.MeanTextConf(); + return nat->api.MeanTextConf(); } static jintArray ocr_word_confidences(JNIEnv *env, jobject thiz) { + LOGV(__FUNCTION__); // Returns all word confidences (between 0 and 100) in an array, terminated // by -1. The calling function must delete [] after use. // The number of confidences should correspond to the number of space- // delimited words in GetUTF8Text. - int* confs = api.AllWordConfidences(); + native_data_t *nat = get_native_data(env, thiz); + int* confs = nat->api.AllWordConfidences(); LOG_ASSERT(confs != NULL, "Could not get word-confidence values!"); int len, *trav; @@ -203,6 +234,7 @@ static void ocr_set_variable(JNIEnv *env, jobject thiz, jstring var, jstring value) { + LOGV(__FUNCTION__); // Set the value of an internal "variable" (of either old or new types). // Supply the name of the variable and the value as a string, just as // you would in a config file. @@ -211,11 +243,13 @@ ocr_set_variable(JNIEnv *env, jobject thiz, // Or SetVariable("bln_numericmode", "1"); to set numeric-only mode. // SetVariable may be used before Init, but settings will revert to // defaults on End(). + + native_data_t *nat = get_native_data(env, thiz); const char *c_var = env->GetStringUTFChars(var, NULL); const char *c_value = env->GetStringUTFChars(value, NULL); - api.SetVariable(c_var, c_value); + nat->api.SetVariable(c_var, c_value); env->ReleaseStringUTFChars(var, c_var); env->ReleaseStringUTFChars(value, c_value); @@ -224,46 +258,79 @@ ocr_set_variable(JNIEnv *env, jobject thiz, static void ocr_clear_results(JNIEnv *env, jobject thiz) { + LOGV(__FUNCTION__); // Free up recognition results and any stored image data, without actually // freeing any recognition data that would be time-consuming to reload. // Afterwards, you must call SetImage or TesseractRect before doing // any Recognize or Get* operation. LOGI("releasing all memory"); - api.Clear(); + native_data_t *nat = get_native_data(env, thiz); + nat->api.Clear(); // Call between pages or documents etc to free up memory and forget // adaptive data. LOGI("clearing adaptive classifier"); - api.ClearAdaptiveClassifier(); + nat->api.ClearAdaptiveClassifier(); - if (image_buffer != NULL) { + if (nat->image_buffer != NULL) { LOGI("releasing image buffer"); - env->ReleaseByteArrayElements(image_obj, image_buffer, JNI_ABORT); - env->DeleteGlobalRef(image_obj); - image_obj = NULL; - image_buffer = NULL; + env->ReleaseByteArrayElements(nat->image_obj, + nat->image_buffer, JNI_ABORT); + env->DeleteGlobalRef(nat->image_obj); + nat->image_obj = NULL; + nat->image_buffer = NULL; } } static void ocr_close(JNIEnv *env, jobject thiz) { - LOGI("quit"); + LOGV(__FUNCTION__); // Close down tesseract and free up all memory. End() is equivalent to // destructing and reconstructing your TessBaseAPI. Once End() has been // used, none of the other API functions may be used other than Init and // anything declared above it in the class definition. - api.End(); + native_data_t *nat = get_native_data(env, thiz); + nat->api.End(); } static void ocr_set_page_seg_mode(JNIEnv *env, jobject thiz, jint mode) { - // Set the current page segmentation mode. Defaults to PSM_AUTO. - // api.SetPageSegMode((tesseract::PageSegMode)mode); + LOGV(__FUNCTION__); + native_data_t *nat = get_native_data(env, thiz); + nat->api.SetPageSegMode((tesseract::PageSegMode)mode); +} + +static void class_init(JNIEnv* env, jclass clazz) { + LOGV(__FUNCTION__); + field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I"); +} + +static void initialize_native_data(JNIEnv* env, jobject object) { + LOGV(__FUNCTION__); + native_data_t *nat = new native_data_t; + if (nat == NULL) { + LOGE("%s: out of memory!", __FUNCTION__); + return; + } + + env->SetIntField(object, field_mNativeData, (jint)nat); +} + +static void cleanup_native_data(JNIEnv* env, jobject object) { + LOGV(__FUNCTION__); + native_data_t *nat = get_native_data(env, object); + if (nat) + delete nat; } static JNINativeMethod methods[] = { + /* name, signature, funcPtr */ + {"classInitNative", "()V", (void*)class_init}, + {"initializeNativeDataNative", "()V", (void *)initialize_native_data}, + {"cleanupNativeDataNative", "()V", (void *)cleanup_native_data}, + {"openNative", "(Ljava/lang/String;)Z", (void*)ocr_open}, {"setImageNative", "([BIIII)V", (void*)ocr_set_image}, {"setRectangleNative", "(IIII)V", (void*)ocr_set_rectangle}, |